first commit for chrg

This commit is contained in:
wmano
2025-08-16 22:58:22 +08:00
commit 52a3ed5862
2306 changed files with 1021208 additions and 0 deletions
+75
View File
@@ -0,0 +1,75 @@
*.pyc
*.map
*.dblite
*.elf
*.bin
*.hex
*.axf
*.exe
*.pdb
*.idb
*.ilk
*.old
*.crf
*.dtb*
build
Debug
.vs
rtthread
settings
documentation/html
*~
*.o
*.obj
*.bak
*.dep
*.lib
*.a
*.i
*.d
*.dfinish
*.su
#source insight 4 project files
*.si4project
packages
dist
rt-studio-project
cconfig.h
GPUCache
#cscope files
cscope.*
ncscope.*
#ctag files
tags
.idea
**/.cache/
.vscode
*.code-workspace
*.eide.*
.history
CMakeLists.txt
cmake-build-debug
*.mk
# vDSO
vdso_sys.os
vdso.lds
# cherryusb libraries
!components/drivers/usb/cherryusb/port/pusb2/*.a
!components/drivers/usb/cherryusb/port/xhci/phytium/*.a
# stm32cubemx
**/CubeMX_Config/Drivers/
**/CubeMX_Config/MDK-ARM/
# mac
.DS_Store
__pychache__
_rt_thread
~*
si4
+83
View File
@@ -0,0 +1,83 @@
/**
* Change Logs:
* 1. 增加长按按键恢复出厂固件的选项
* 2. 修改中断开启与关闭接口
*/
#ifndef __BSP_COMMON_H__
#define __BSP_COMMON_H__
#include "common.h"
#if (ENABLE_FACTORY_FIRMWARE_BUTTON)
#include "bsp_key.h"
#endif
#include "bsp_uart.h"
#include "drv_timer.h"
#include "bsp_flash.h"
#define BSP_VERSION_MAIN (0x01U) /*!< [15:8] main version */
#define BSP_VERSION_SUB (0x00U) /*!< [ 7:0] sub version */
#define BSP_VERSION ((BSP_VERSION_MAIN << 8) \
|(BSP_VERSION_SUB))
#define BSP_Delay(ms) HAL_Delay(ms)
#define BSP_INT_ENTER()
#define BSP_INT_EXIT()
#define BSP_INT_EN() __enable_irq()
#define BSP_INT_DIS() __disable_irq()
#define BSP_UART_ENABLE_RX(UARTx) UARTx.Instance->CR1 |= (uint32_t)0x0004
#define BSP_UART_DISABLE_RX(UARTx) UARTx.Instance->CR1 &= (~(uint32_t)0x0004)
typedef enum {
ERR_OK = 0x00,
ERR_UNKNOWN = 0x01, // 未知错误
/* 协议错误 */
ERR_DUPLICATE_FRAME = 0x02, // 重复帧
ERR_OMISSION_FRAME = 0x03, // 跳帧或遗漏帧
ERR_PKT_NUM_ERR = 0x04, // 正反序列号错误
ERR_FRAME_LENGTH = 0x05, // 帧长度错误
ERR_FRAME_VERIFY_ERR = 0x06, // 帧校验错误
ERR_HEADER_ERR = 0x07, // header 错误
ERR_EXE_FLOW = 0x08, // 执行流程错误,未按协议流程收到数据包
/* 业务错误 */
ERR_NO_FACTORY_FIRMWARE = 0x10, // 没有可供恢复出厂的固件
ERR_NO_THIS_PART, /* 找不到固件包指定的分区 */
ERR_READ_IS_EMPTY_ERR, /* 判断分区是否为空时读取错误 */
ERR_FIRMWARE_OVERSIZE, /* 固件大小超过分区容量 */
ERR_FIRMWARE_HEAD_VERIFY_ERR, /* 固件包头校验错误 */
ERR_VERIFY_READ_ERR, /* 校验固件时读取错误 */
ERR_RAW_BODY_VERIFY_ERR, /* 源固件包体校验错误 */
ERR_PKG_BODY_VERIFY_ERR, /* 打包后的固件包体校验错误 */
ERR_ERASE_PART_ERR, /* 擦除分区错误 */
ERR_WRITE_FIRST_ADDR_ERR, /* 数据写入分区首地址错误 */
ERR_JUMP_TO_APP_ERR, /* 跳转至 APP 时检测到错误 */
ERR_READ_FIRMWARE_HEAD_ERR, /* 读取固件包头错误 */
ERR_UPDATE_READ_ERR, /* 固件更新至 APP 分区时读取分区错误 */
ERR_UPDATE_VER_READ_ERR, /* 更新固件版本信息时读取分区错误 */
ERR_UPDATE_VER_ERASE_ERR, /* 更新固件版本信息时擦除分区错误 */
ERR_UPDATE_VER_WRITE_ERR, /* 更新固件版本信息时写入分区错误 */
ERR_WRITE_PART_ERR, /* 数据写入分区错误 */
ERR_FAULT_FIRMWARE, /* 错误的固件包 */
ERR_DECRYPT_ERR = 0x30, // 固件解密失败
ERR_NO_DECRYPT_COMPONENT, // 从机没有解密组件,无法解密
ERR_FLASH_NO_EMPTY, // flash 非空
ERR_READ_VER_ERR, // 读取固件的版本失败
ERR_WRITE_VER_ERR, // 固件的版本写入 APP 分区失败
ERR_VER_AREA_NO_ERASE, // APP 分区的固件版本区域没有擦除
ERR_CAN_NOT_PLACE_IN_APP, // 从机限制了多分区方案时不能指定固件包放置于 APP 分区
ERR_DOES_NOT_EXIST_DOWNLOAD, // 不存在 download 分区
ERR_DOES_NOT_EXIST_FACTORY, // 不存在 factory 分区
} eErrCode;
#endif
+341
View File
@@ -0,0 +1,341 @@
#include "bsp_flash.h"
static uint32_t _Get_STM32SectorIndex(uint32_t addr)
{
uint32_t sector = 0;
if ((addr < ADDR_FLASH_SECTOR_1) && (addr >= ADDR_FLASH_SECTOR_0))
{
sector = FLASH_SECTOR_0;
}
else if ((addr < ADDR_FLASH_SECTOR_2) && (addr >= ADDR_FLASH_SECTOR_1))
{
sector = FLASH_SECTOR_1;
}
else if ((addr < ADDR_FLASH_SECTOR_3) && (addr >= ADDR_FLASH_SECTOR_2))
{
sector = FLASH_SECTOR_2;
}
else if ((addr < ADDR_FLASH_SECTOR_4) && (addr >= ADDR_FLASH_SECTOR_3))
{
sector = FLASH_SECTOR_3;
}
else if ((addr < ADDR_FLASH_SECTOR_5) && (addr >= ADDR_FLASH_SECTOR_4))
{
sector = FLASH_SECTOR_4;
}
#if defined(FLASH_SECTOR_5)
else if ((addr < ADDR_FLASH_SECTOR_6) && (addr >= ADDR_FLASH_SECTOR_5))
{
sector = FLASH_SECTOR_5;
}
#endif
#if defined(FLASH_SECTOR_6)
else if ((addr < ADDR_FLASH_SECTOR_7) && (addr >= ADDR_FLASH_SECTOR_6))
{
sector = FLASH_SECTOR_6;
}
#endif
#if defined(FLASH_SECTOR_7)
else if ((addr < ADDR_FLASH_SECTOR_8) && (addr >= ADDR_FLASH_SECTOR_7))
{
sector = FLASH_SECTOR_7;
}
#endif
#if defined(FLASH_SECTOR_8)
else if ((addr < ADDR_FLASH_SECTOR_9) && (addr >= ADDR_FLASH_SECTOR_8))
{
sector = FLASH_SECTOR_8;
}
#endif
#if defined(FLASH_SECTOR_9)
else if ((addr < ADDR_FLASH_SECTOR_10) && (addr >= ADDR_FLASH_SECTOR_9))
{
sector = FLASH_SECTOR_9;
}
#endif
#if defined(FLASH_SECTOR_10)
else if ((addr < ADDR_FLASH_SECTOR_11) && (addr >= ADDR_FLASH_SECTOR_10))
{
sector = FLASH_SECTOR_10;
}
#endif
#if defined(FLASH_SECTOR_11)
else if ((addr < ADDR_FLASH_SECTOR_12) && (addr >= ADDR_FLASH_SECTOR_11))
{
sector = FLASH_SECTOR_11;
}
#endif
#if defined(FLASH_SECTOR_12)
else if ((addr < ADDR_FLASH_SECTOR_13) && (addr >= ADDR_FLASH_SECTOR_12))
{
sector = FLASH_SECTOR_12;
}
#endif
#if defined(FLASH_SECTOR_13)
else if ((addr < ADDR_FLASH_SECTOR_14) && (addr >= ADDR_FLASH_SECTOR_13))
{
sector = FLASH_SECTOR_13;
}
#endif
#if defined(FLASH_SECTOR_14)
else if ((addr < ADDR_FLASH_SECTOR_15) && (addr >= ADDR_FLASH_SECTOR_14))
{
sector = FLASH_SECTOR_14;
}
#endif
#if defined(FLASH_SECTOR_15)
else if ((addr < ADDR_FLASH_SECTOR_16) && (addr >= ADDR_FLASH_SECTOR_15))
{
sector = FLASH_SECTOR_15;
}
#endif
#if defined(FLASH_SECTOR_16)
else if ((addr < ADDR_FLASH_SECTOR_17) && (addr >= ADDR_FLASH_SECTOR_16))
{
sector = FLASH_SECTOR_16;
}
#endif
#if defined(FLASH_SECTOR_17)
else if ((addr < ADDR_FLASH_SECTOR_18) && (addr >= ADDR_FLASH_SECTOR_17))
{
sector = FLASH_SECTOR_17;
}
#endif
#if defined(FLASH_SECTOR_18)
else if ((addr < ADDR_FLASH_SECTOR_19) && (addr >= ADDR_FLASH_SECTOR_18))
{
sector = FLASH_SECTOR_18;
}
#endif
#if defined(FLASH_SECTOR_19)
else if ((addr < ADDR_FLASH_SECTOR_20) && (addr >= ADDR_FLASH_SECTOR_19))
{
sector = FLASH_SECTOR_19;
}
#endif
#if defined(FLASH_SECTOR_20)
else if ((addr < ADDR_FLASH_SECTOR_21) && (addr >= ADDR_FLASH_SECTOR_20))
{
sector = FLASH_SECTOR_20;
}
#endif
#if defined(FLASH_SECTOR_21)
else if ((addr < ADDR_FLASH_SECTOR_22) && (addr >= ADDR_FLASH_SECTOR_21))
{
sector = FLASH_SECTOR_21;
}
#endif
#if defined(FLASH_SECTOR_22)
else if ((addr < ADDR_FLASH_SECTOR_23) && (addr >= ADDR_FLASH_SECTOR_22))
{
sector = FLASH_SECTOR_22;
}
#endif
#if defined(FLASH_SECTOR_23)
else /* (addr < FLASH_END_ADDR) && (addr >= ADDR_FLASH_SECTOR_23) */
{
sector = FLASH_SECTOR_23;
}
#endif
return sector;
}
int read(long offset, uint8_t *buf, size_t size)
{
size_t i = 0;
uint32_t addr = offset;
if ((addr + size) > OFFSET_ONCHIP_FLASH_END) {
return -1;
}
for (i = 0; i < size; i++, buf++, addr++) {
*buf = *(uint8_t *) addr;
}
return size;
}
int write(long offset, const uint8_t *buf, size_t size)
{
int status = 0;
uint32_t addr = offset;
uint32_t end_addr = addr + size;
if (end_addr > OFFSET_ONCHIP_FLASH_END) {
printf("%s:%d\r\n", __func__, __LINE__);
return -1;
}
if (size < 1) {
printf("%s:%d\r\n", __func__, __LINE__);
return -1;
}
size_t data_len = size * sizeof(uint32_t);
uint32_t *data = (uint32_t *)buf;
HAL_FLASH_Unlock();
/* Clear pending flags (if any) */
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | \
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
for (uint32_t i = 0;
(i < data_len) && (addr <= (end_addr - sizeof(uint32_t)));
i++)
{
/* Device voltage range supposed to be [2.7V to 3.6V], the operation will
be done by word */
if (HAL_FLASH_Program(TYPEPROGRAM_WORD, addr, *(uint32_t *)(data + i)) == HAL_OK)
{
/* Check the written value */
if (*(uint32_t *)addr != *(uint32_t *)(data + i))
{
/* Flash content doesn't match SRAM content */
status = -1;
break;
}
/* Increment FLASH destination address */
addr += sizeof(uint32_t);
}
else
{
/* Error occurred while writing data in Flash memory */
status = -2;
break;
}
}
HAL_FLASH_Lock();
if (status < 0) {
printf("%s:%d %d\r\n", __func__, __LINE__, status);
return status;
}
return size;
}
int erase(long offset, size_t size)
{
uint32_t page_err = 0;
HAL_StatusTypeDef status = HAL_OK;
FLASH_EraseInitTypeDef erase_init = {0};
uint32_t addr = offset;
uint32_t end_addr = addr + size;
if (end_addr > OFFSET_ONCHIP_FLASH_END) {
return -1;
}
HAL_FLASH_Unlock();
/* Clear pending flags (if any) */
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | \
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
uint8_t sector_count;
uint32_t sector_head_num;
uint32_t sector_end_num;
sector_head_num = _Get_STM32SectorIndex( addr );
sector_end_num = _Get_STM32SectorIndex( end_addr-1 );
sector_count = sector_end_num - sector_head_num;
sector_count ++;
#if (ENABLE_DB1M_BIT)
if (sector_head_num > FLASH_SECTOR_7)
sector_head_num += 4;
#endif
erase_init.TypeErase = TYPEERASE_SECTORS;
erase_init.Sector = sector_head_num;
erase_init.NbSectors = sector_count;
erase_init.VoltageRange = VOLTAGE_RANGE_3;
/* Note: If an erase operation in Flash memory also concerns data in the data or instruction cache,
you have to make sure that these data are rewritten before they are accessed during code
execution. If this cannot be done safely, it is recommended to flush the caches by setting the
DCRST and ICRST bits in the FLASH_CR register. */
status = HAL_FLASHEx_Erase(&erase_init, &page_err);
HAL_FLASH_Lock();
if (status != HAL_OK)
return -2;
return size;
}
static struct BSP_FLASH *_part_head;
static void _Flash_Add(struct BSP_FLASH *part)
{
struct BSP_FLASH *target;
for (target = _part_head; target != NULL; target = target->next)
{
if (target == part)
return;
}
part->next = _part_head;
_part_head = part;
}
void BSP_Flash_Init(struct BSP_FLASH *part, const char *name, uint32_t addr, uint32_t size)
{
ASSERT(part != NULL);
memcpy(part->name, name, MAX_NAME_LEN);
part->addr = addr;
part->len = size;
_Flash_Add(part);
}
int BSP_Flash_Read(const struct BSP_FLASH *part, uint32_t relative_addr, uint8_t *buff, uint32_t size)
{
ASSERT(part != NULL);
return read(part->addr + relative_addr, buff, size);
}
inline int BSP_Flash_Write(const struct BSP_FLASH *part, uint32_t relative_addr, const uint8_t *buff, uint32_t size)
{
ASSERT(part != NULL);
return write(part->addr + relative_addr, buff, size);
}
inline int BSP_Flash_Erase(const struct BSP_FLASH *part, uint32_t relative_addr, uint32_t size)
{
ASSERT(part != NULL);
return erase(part->addr + relative_addr, size);
}
struct BSP_FLASH *BSP_Flash_GetHandle(const char *part_name)
{
struct BSP_FLASH *part;
for (part = _part_head; part != NULL; part = part->next)
{
if (strncmp(part->name, part_name, MAX_NAME_LEN) == 0)
return part;
}
return NULL;
}
+54
View File
@@ -0,0 +1,54 @@
#ifndef __BSP_FLASH_H__
#define __BSP_FLASH_H__
#include "bsp_common.h"
/* Base address of the Flash sectors Bank 1 */
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbytes */
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbytes */
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbytes */
#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbytes */
#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbytes */
#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) /* Base @ of Sector 6, 128 Kbytes */
#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) /* Base @ of Sector 7, 128 Kbytes */
#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08080000) /* Base @ of Sector 8, 128 Kbytes */
#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x080A0000) /* Base @ of Sector 9, 128 Kbytes */
#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) /* Base @ of Sector 10, 128 Kbytes */
#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) /* Base @ of Sector 11, 128 Kbytes */
/* Base address of the Flash sectors Bank 2 */
#define ADDR_FLASH_SECTOR_12 ((uint32_t)0x08100000) /* Base @ of Sector 0, 16 Kbytes */
#define ADDR_FLASH_SECTOR_13 ((uint32_t)0x08104000) /* Base @ of Sector 1, 16 Kbytes */
#define ADDR_FLASH_SECTOR_14 ((uint32_t)0x08108000) /* Base @ of Sector 2, 16 Kbytes */
#define ADDR_FLASH_SECTOR_15 ((uint32_t)0x0810C000) /* Base @ of Sector 3, 16 Kbytes */
#define ADDR_FLASH_SECTOR_16 ((uint32_t)0x08110000) /* Base @ of Sector 4, 64 Kbytes */
#define ADDR_FLASH_SECTOR_17 ((uint32_t)0x08120000) /* Base @ of Sector 5, 128 Kbytes */
#define ADDR_FLASH_SECTOR_18 ((uint32_t)0x08140000) /* Base @ of Sector 6, 128 Kbytes */
#define ADDR_FLASH_SECTOR_19 ((uint32_t)0x08160000) /* Base @ of Sector 7, 128 Kbytes */
#define ADDR_FLASH_SECTOR_20 ((uint32_t)0x08180000) /* Base @ of Sector 8, 128 Kbytes */
#define ADDR_FLASH_SECTOR_21 ((uint32_t)0x081A0000) /* Base @ of Sector 9, 128 Kbytes */
#define ADDR_FLASH_SECTOR_22 ((uint32_t)0x081C0000) /* Base @ of Sector 10, 128 Kbytes */
#define ADDR_FLASH_SECTOR_23 ((uint32_t)0x081E0000) /* Base @ of Sector 11, 128 Kbytes */
struct BSP_FLASH
{
char name[MAX_NAME_LEN];
uint32_t addr;
uint32_t len;
struct BSP_FLASH *next;
};
void BSP_Flash_Init (struct BSP_FLASH *part, const char *name, uint32_t addr, uint32_t size);
int BSP_Flash_Read (const struct BSP_FLASH *part, uint32_t relative_addr, uint8_t *buff, uint32_t size);
int BSP_Flash_Write (const struct BSP_FLASH *part, uint32_t relative_addr, const uint8_t *buff, uint32_t size);
int BSP_Flash_Erase (const struct BSP_FLASH *part, uint32_t relative_addr, uint32_t size);
struct BSP_FLASH * BSP_Flash_GetHandle (const char *part_name);
#endif
+314
View File
@@ -0,0 +1,314 @@
#include "bsp_gpio.h"
static const struct GPIO_INDEX _gpios[] = {
#if defined(GPIOA)
STM32_PIN(0 , A, 0 ),
STM32_PIN(1 , A, 1 ),
STM32_PIN(2 , A, 2 ),
STM32_PIN(3 , A, 3 ),
STM32_PIN(4 , A, 4 ),
STM32_PIN(5 , A, 5 ),
STM32_PIN(6 , A, 6 ),
STM32_PIN(7 , A, 7 ),
STM32_PIN(8 , A, 8 ),
STM32_PIN(9 , A, 9 ),
STM32_PIN(10, A, 10),
STM32_PIN(11, A, 11),
STM32_PIN(12, A, 12),
STM32_PIN(13, A, 13),
STM32_PIN(14, A, 14),
STM32_PIN(15, A, 15),
#endif
#if defined(GPIOB)
STM32_PIN(16, B, 0),
STM32_PIN(17, B, 1),
STM32_PIN(18, B, 2),
STM32_PIN(19, B, 3),
STM32_PIN(20, B, 4),
STM32_PIN(21, B, 5),
STM32_PIN(22, B, 6),
STM32_PIN(23, B, 7),
STM32_PIN(24, B, 8),
STM32_PIN(25, B, 9),
STM32_PIN(26, B, 10),
STM32_PIN(27, B, 11),
STM32_PIN(28, B, 12),
STM32_PIN(29, B, 13),
STM32_PIN(30, B, 14),
STM32_PIN(31, B, 15),
#endif
#if defined(GPIOC)
STM32_PIN(32, C, 0),
STM32_PIN(33, C, 1),
STM32_PIN(34, C, 2),
STM32_PIN(35, C, 3),
STM32_PIN(36, C, 4),
STM32_PIN(37, C, 5),
STM32_PIN(38, C, 6),
STM32_PIN(39, C, 7),
STM32_PIN(40, C, 8),
STM32_PIN(41, C, 9),
STM32_PIN(42, C, 10),
STM32_PIN(43, C, 11),
STM32_PIN(44, C, 12),
STM32_PIN(45, C, 13),
STM32_PIN(46, C, 14),
STM32_PIN(47, C, 15),
#endif
#if defined(GPIOD)
STM32_PIN(48, D, 0),
STM32_PIN(49, D, 1),
STM32_PIN(50, D, 2),
STM32_PIN(51, D, 3),
STM32_PIN(52, D, 4),
STM32_PIN(53, D, 5),
STM32_PIN(54, D, 6),
STM32_PIN(55, D, 7),
STM32_PIN(56, D, 8),
STM32_PIN(57, D, 9),
STM32_PIN(58, D, 10),
STM32_PIN(59, D, 11),
STM32_PIN(60, D, 12),
STM32_PIN(61, D, 13),
STM32_PIN(62, D, 14),
STM32_PIN(63, D, 15),
#endif
#if defined(GPIOE)
STM32_PIN(64, E, 0),
STM32_PIN(65, E, 1),
STM32_PIN(66, E, 2),
STM32_PIN(67, E, 3),
STM32_PIN(68, E, 4),
STM32_PIN(69, E, 5),
STM32_PIN(70, E, 6),
STM32_PIN(71, E, 7),
STM32_PIN(72, E, 8),
STM32_PIN(73, E, 9),
STM32_PIN(74, E, 10),
STM32_PIN(75, E, 11),
STM32_PIN(76, E, 12),
STM32_PIN(77, E, 13),
STM32_PIN(78, E, 14),
STM32_PIN(79, E, 15),
#endif
#if defined(GPIOF)
STM32_PIN(80, F, 0),
STM32_PIN(81, F, 1),
STM32_PIN(82, F, 2),
STM32_PIN(83, F, 3),
STM32_PIN(84, F, 4),
STM32_PIN(85, F, 5),
STM32_PIN(86, F, 6),
STM32_PIN(87, F, 7),
STM32_PIN(88, F, 8),
STM32_PIN(89, F, 9),
STM32_PIN(90, F, 10),
STM32_PIN(91, F, 11),
STM32_PIN(92, F, 12),
STM32_PIN(93, F, 13),
STM32_PIN(94, F, 14),
STM32_PIN(95, F, 15),
#endif
#if defined(GPIOG)
STM32_PIN(96, G, 0),
STM32_PIN(97, G, 1),
STM32_PIN(98, G, 2),
STM32_PIN(99, G, 3),
STM32_PIN(100, G, 4),
STM32_PIN(101, G, 5),
STM32_PIN(102, G, 6),
STM32_PIN(103, G, 7),
STM32_PIN(104, G, 8),
STM32_PIN(105, G, 9),
STM32_PIN(106, G, 10),
STM32_PIN(107, G, 11),
STM32_PIN(108, G, 12),
STM32_PIN(109, G, 13),
STM32_PIN(110, G, 14),
STM32_PIN(111, G, 15),
#endif
#if defined(GPIOH)
STM32_PIN(112, H, 0),
STM32_PIN(113, H, 1),
STM32_PIN(114, H, 2),
STM32_PIN(115, H, 3),
STM32_PIN(116, H, 4),
STM32_PIN(117, H, 5),
STM32_PIN(118, H, 6),
STM32_PIN(119, H, 7),
STM32_PIN(120, H, 8),
STM32_PIN(121, H, 9),
STM32_PIN(122, H, 10),
STM32_PIN(123, H, 11),
STM32_PIN(124, H, 12),
STM32_PIN(125, H, 13),
STM32_PIN(126, H, 14),
STM32_PIN(127, H, 15),
#endif
#if defined(GPIOI)
STM32_PIN(128, I, 0),
STM32_PIN(129, I, 1),
STM32_PIN(130, I, 2),
STM32_PIN(131, I, 3),
STM32_PIN(132, I, 4),
STM32_PIN(133, I, 5),
STM32_PIN(134, I, 6),
STM32_PIN(135, I, 7),
STM32_PIN(136, I, 8),
STM32_PIN(137, I, 9),
STM32_PIN(138, I, 10),
STM32_PIN(139, I, 11),
STM32_PIN(140, I, 12),
STM32_PIN(141, I, 13),
STM32_PIN(142, I, 14),
STM32_PIN(143, I, 15),
#endif
#if defined(GPIOJ)
STM32_PIN(144, J, 0),
STM32_PIN(145, J, 1),
STM32_PIN(146, J, 2),
STM32_PIN(147, J, 3),
STM32_PIN(148, J, 4),
STM32_PIN(149, J, 5),
STM32_PIN(150, J, 6),
STM32_PIN(151, J, 7),
STM32_PIN(152, J, 8),
STM32_PIN(153, J, 9),
STM32_PIN(154, J, 10),
STM32_PIN(155, J, 11),
STM32_PIN(156, J, 12),
STM32_PIN(157, J, 13),
STM32_PIN(158, J, 14),
STM32_PIN(159, J, 15),
#endif
#if defined(GPIOK)
STM32_PIN(160, K, 0),
STM32_PIN(161, K, 1),
STM32_PIN(162, K, 2),
STM32_PIN(163, K, 3),
STM32_PIN(164, K, 4),
STM32_PIN(165, K, 5),
STM32_PIN(166, K, 6),
STM32_PIN(167, K, 7),
STM32_PIN(168, K, 8),
STM32_PIN(169, K, 9),
STM32_PIN(170, K, 10),
STM32_PIN(171, K, 11),
STM32_PIN(172, K, 12),
STM32_PIN(173, K, 13),
STM32_PIN(174, K, 14),
STM32_PIN(175, K, 15),
#endif
};
static const uint8_t _gpio_qty = sizeof(_gpios) / sizeof(_gpios[0]);
static const struct GPIO_INDEX *_GPIO_GetPin (uint8_t io)
{
const struct GPIO_INDEX *index;
if (io < _gpio_qty) {
index = &_gpios[io];
if (index->index == -1)
index = NULL;
}
else
index = NULL;
return index;
};
void BSP_GPIO_Write (uint8_t io, uint8_t level)
{
const struct GPIO_INDEX *index;
index = _GPIO_GetPin(io);
if (index == NULL)
return;
HAL_GPIO_WritePin(index->gpio, index->pin, (GPIO_PinState)level);
}
uint8_t BSP_GPIO_Read(uint8_t io)
{
const struct GPIO_INDEX *index;
index = _GPIO_GetPin(io);
if (index == NULL)
return GPIO_HIGH;
return HAL_GPIO_ReadPin(index->gpio, index->pin);
}
void BSP_GPIO_Toggle(uint8_t io)
{
const struct GPIO_INDEX *index;
index = _GPIO_GetPin(io);
if (index == NULL)
return;
HAL_GPIO_TogglePin(index->gpio, index->pin);
}
/*
* mode: IO模式(This parameter can be a value of @ref GPIO_mode_define stm32f1xx_hal_gpio.h
* pull: 上下拉(GPIO_NOPULL、GPIO_PULLUP、GPIO_PULLDOWN
*/
void BSP_GPIO_SetMode (uint8_t io, uint32_t mode, uint32_t pull)
{
const struct GPIO_INDEX *index;
GPIO_InitTypeDef GPIO_InitStruct;
index = _GPIO_GetPin(io);
if (index == NULL)
return;
/* Configure GPIO_InitStructure */
GPIO_InitStruct.Pin = index->pin;
GPIO_InitStruct.Mode = mode;
GPIO_InitStruct.Pull = pull;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(index->gpio, &GPIO_InitStruct);
}
GPIO_TypeDef *BSP_GPIO_GetPort(uint8_t io)
{
const struct GPIO_INDEX *index;
index = _GPIO_GetPin(io);
if (index == NULL)
return NULL;
return index->gpio;
}
uint16_t BSP_GPIO_GetPin (uint8_t io)
{
const struct GPIO_INDEX *index;
index = _GPIO_GetPin(io);
if (index == NULL)
return NULL;
return index->pin;
}
+36
View File
@@ -0,0 +1,36 @@
#ifndef __BSP_GPIO_H__
#define __BSP_GPIO_H__
#include "bsp_common.h"
#define GPIO_LOW 0x00
#define GPIO_HIGH 0x01
#define STM32_PORT(port) GPIO##port##_BASE
#define GET_PIN(port, pin) (uint32_t)((16 * ( ((uint32_t)STM32_PORT(port) - (uint32_t)GPIOA_BASE)/(0x0400UL) )) + pin)
#define STM32_PIN(index, gpio, gpio_index) \
{ \
index, GPIO##gpio, GPIO_PIN_##gpio_index \
}
/* STM32 GPIO driver */
struct GPIO_INDEX
{
int index;
GPIO_TypeDef *gpio;
uint16_t pin;
};
void BSP_GPIO_Write (uint8_t io, uint8_t level);
uint8_t BSP_GPIO_Read (uint8_t io);
void BSP_GPIO_Toggle (uint8_t io);
void BSP_GPIO_SetMode (uint8_t io, uint32_t mode, uint32_t pull);
GPIO_TypeDef * BSP_GPIO_GetPort (uint8_t io);
uint16_t BSP_GPIO_GetPin (uint8_t io);
#endif
+274
View File
@@ -0,0 +1,274 @@
/* Includes ------------------------------------------------------------------*/
#include "bsp_key.h"
/* Private variables ---------------------------------------------------------*/
#define EVENT_CALLBACK(event) do{ \
if (key_index->Callback[ event ]) \
{ \
key_index->Callback[ event ]( key_index->id, event ); \
} \
} while(0)
/* Private function prototypes -----------------------------------------------*/
static struct BSP_KEY *_key_head;
/* Exported functions ---------------------------------------------------------*/
/**
* @brief 按键对象初始化
* @note
* @param[in] key: 按键句柄
* @param[in] id: 按键 ID,用于识别不同的按键
* @param[in] KEY_GetState: 按键状态获取回调函数
* @param[in] press_level: 按键按下时的电平状态
* @param[in] press_time: 设置按键长按的间隔时间
* @retval 执行结果
*/
#if (KEY_USER_DEFINE_PRESS_TIME)
int8_t BSP_Key_Init(struct BSP_KEY *key, uint8_t id, uint8_t (*KEY_GetState)(void), KEY_LEVEL press_level, uint16_t press_time)
#else
int8_t BSP_Key_Init(struct BSP_KEY *key, uint8_t id, uint8_t (*KEY_GetState)(void), KEY_LEVEL press_level)
#endif
{
memset(key, 0, sizeof(struct BSP_KEY));
key->id = id;
key->press_level = press_level;
key->continuous_value = 0xFF;
key->GetState = KEY_GetState;
#if (KEY_USER_DEFINE_PRESS_TIME)
key->press_time = press_time;
#endif
return 0;
}
/**
* @brief 按键启用
* @note 每个按键初始化并注册好相应的按键事件回调函数后,必须调用本函数才能使用
* @param[in] key: 按键句柄
* @retval 执行结果
*/
int8_t BSP_Key_Start(struct BSP_KEY *key)
{
struct BSP_KEY *key_index = _key_head;
while (key_index)
{
if (key_index == key)
return 1;
key_index = key_index->next;
}
key->next = _key_head;
_key_head = key;
return 0;
}
/**
* @brief 按键停用
* @note 当按键不再需要使用时,便可调用本函数
* @param[in] key:按键句柄
* @retval None
*/
void BSP_Key_Stop(struct BSP_KEY *key)
{
struct BSP_KEY *key_now = _key_head;
struct BSP_KEY *key_last;
for (; key_now; key_now = key_now->next)
{
if (key_now == key)
{
if (key == _key_head)
{
_key_head = key->next;
return;
}
if (key->next)
key_last->next = key->next;
else
key_last->next = NULL;
}
key_last = key_now;
}
}
/**
* @brief 注册按键事件触发时的回调函数
* @note 若需要使用按键,则至少应该注册一个按键事件的回调函数
* @param[in] key: 按键句柄
* @param[in] event: 按键事件
* @param[in] callback: 按键事件回调函数
* @retval None
*/
void BSP_Key_Register(struct BSP_KEY *key, KEY_EVENT event, Key_EventCallback callback)
{
key->Callback[ event ] = callback;
}
/**
* @brief 按键业务处理函数
* @note 若需要使用按键的任何功能,都需要调用本函数,并周期性的循环执行
* @param[in] ms: 告知本函数每隔多少毫秒被执行1次
* @retval None
*/
void BSP_Key_Handler(uint8_t ms)
{
uint8_t i = 0;
uint8_t times = 0xFF;
struct BSP_KEY *key_index = _key_head;
for (; i < (8 - KEY_CONSECUTIVE_READ_TIME); i++)
times >>= 1;
for (; key_index; key_index = key_index->next)
{
/* 获取按键电平值 */
key_index->continuous_value = (key_index->continuous_value << 1) | key_index->GetState();
/* 获取按键按下或弹起状态 */
if ((key_index->continuous_value & times) == 0x00)
{
if (key_index->press_level == KEY_PRESS_LOW)
key_index->key_state = KEY_DOWN;
else
key_index->key_state = KEY_UP;
}
else if((key_index->continuous_value & times) == times)
{
if (key_index->press_level == KEY_PRESS_HIGH)
key_index->key_state = KEY_DOWN;
else
key_index->key_state = KEY_UP;
}
/* 按键状态机 */
switch (key_index->state)
{
case 0:
{
if (key_index->key_state == KEY_DOWN) /* 首次按下 */
{
key_index->event = KEY_PRESS;
EVENT_CALLBACK( KEY_PRESS );
key_index->state = 1;
}
break;
}
case 1:
{
if (key_index->key_state == KEY_UP) /* 按下后放开 */
{
key_index->tick = 0;
#if (KEY_CLICK_EVENT_WHEN_DBLCLICK)
key_index->event = KEY_CLICK;
EVENT_CALLBACK( KEY_CLICK );
#endif
key_index->state = 2;
}
else if (key_index->key_state == KEY_DOWN) /* 还处于第一次按下的状态 */
{
key_index->tick += ms;
#if (KEY_USER_DEFINE_PRESS_TIME)
if (key_index->tick >= key_index->press_time) /* 第一次按下时间已超过长按触发时间 */
#else
if (key_index->tick >= KEY_LONG_PRESS_TIME) /* 超时未按下 */
#endif
{
key_index->tick = 0;
key_index->event = KEY_LONG_PRESS;
EVENT_CALLBACK( KEY_LONG_PRESS );
key_index->state = 4;
}
}
break;
}
case 2: /* 检测是否双击 */
{
if (key_index->key_state == KEY_DOWN) /* 单击后再次按下 */
{
if (KEY_DBLCLICK_PRESS_VALID) /* 第二次按下立即触发标志 */
{
key_index->event = KEY_DBLCLICK;
EVENT_CALLBACK( KEY_DBLCLICK );
}
key_index->tick = 0;
key_index->state = 3;
}
else if (key_index->key_state == KEY_UP) /* 未按下 */
{
key_index->tick += ms;
if (key_index->tick >= KEY_DBLCLICK_TIME) /* 单击后超时未再按下,事件结束 */
{
#if (KEY_CLICK_EVENT_WHEN_DBLCLICK == 0)
key_index->event = KEY_CLICK;
EVENT_CALLBACK( KEY_CLICK );
#endif
key_index->tick = 0;
key_index->state = 0;
key_index->event = KEY_NONE_EVENT;
}
}
break;
}
case 3: /* 双击事件,第二次已按下 */
{
if (key_index->key_state == KEY_UP) /* 第二次已放开按键 */
{
if (KEY_DBLCLICK_PRESS_VALID == 0) /* 第二次按下放开后才触发标志 */
{
key_index->event = KEY_DBLCLICK;
EVENT_CALLBACK( KEY_DBLCLICK );
}
key_index->tick = 0;
key_index->state = 0;
key_index->event = KEY_NONE_EVENT;
}
break;
}
case 4: /* 长时间按着(进入此处时长按回调事件已经被执行完毕) */
{
if (key_index->key_state == KEY_DOWN) /* 此时依旧被按着 */
{
key_index->tick += ms;
#if (KEY_LONG_PRESS_CONTINU_TRIG_TIME)
/* 需要长按保持触发 */
if (key_index->tick >= KEY_LONG_PRESS_CONTINU_TRIG_TIME)
{
key_index->tick = 0;
key_index->event = KEY_LONG_PRESS_HOLD;
EVENT_CALLBACK( KEY_LONG_PRESS_HOLD );
}
#endif
}
else if (key_index->key_state == KEY_UP) /* 用户已放开按键,流程结束 */
{
key_index->tick = 0;
key_index->state = 0;
key_index->event = KEY_NONE_EVENT;
}
break;
}
default :break;
}
}
}
+91
View File
@@ -0,0 +1,91 @@
#ifndef __BSP_KEY_H__
#define __BSP_KEY_H__
#include "bsp_common.h"
#define KEY_TEST 0
/* 常用配置项 */
#define KEY_CLICK_EVENT_WHEN_DBLCLICK 0 /* 设定当双击按键时是否还触发单击事件。1:双击时依旧触发单击事件;0:双击时不触发单击事件,但会触发双击事件 */
#define KEY_DBLCLICK_PRESS_VALID 0 /* 按键双击时,选择第二次按下时立即触发事件,或是第二次按下时放开按键后才触发事件 */
/* 1:第二次按下时立即触发事件;0:第二次按下并放开按键后才触发事件 */
#define KEY_LONG_PRESS_TIME FACTORY_FIRMWARE_BUTTON_TIME /* 长按间隔时间,单位:ms */
#define KEY_DBLCLICK_TIME 200 /* 双击间隔时间。单位:ms */
/* 非常用配置项 */
#define KEY_USER_DEFINE_PRESS_TIME 0 /* 用户想针对每个按键设定不同的长按触发时间,为 0 时表示全部按键的长按触发时间使用 KEY_LONG_PRESS_TIME 参数 */
/* 为 1 时表示用户想单独为每个按键设置长按事件的触发时间 */
#define KEY_LONG_PRESS_CONTINU_TRIG_TIME 0 /* 一直长按按键, KEY_LONG_PRESS_TIME 个单位时间后,此参数表示的是用户持续按下按键每隔一段时间触发一次 KEY_LONG_PRESS_HOLD 事件 */
/* 为 0 时表示不管用户一直按下按键持续多长时间,都只触发一次 KEY_LONG_PRESS 事件,直到用户放开按键为止,才能继续下个事件的操作 */
#define KEY_CONSECUTIVE_READ_TIME 4 /* 连续读取键值次数,此参数用于实现非阻塞式的按键消抖,最大值:8 */
/* 该值会影响读取最终键值和触发事件的时间 */
/* 按键的单击事件触发时间 = KEY_CONSECUTIVE_READ_TIME * 传入BSP_Key_Handler函数的参数值,单位:ms */
/* 其他按键事件基于以上时间叠加 */
typedef enum
{
KEY_PRESS_LOW = 0x00,
KEY_PRESS_HIGH = 0xFF
} KEY_LEVEL;
typedef enum
{
KEY_UP = 0,
KEY_DOWN
} KEY_STATE;
typedef enum
{
KEY_PRESS = 0, /* 刚按下(每个按键事件都会触发该事件,是否要处理该事件由用户选择是否注册该事件的回调函数) */
KEY_CLICK = 1, /* 单击 */
KEY_DBLCLICK = 2, /* 双击 */
KEY_LONG_PRESS = 3, /* 长按 */
KEY_LONG_PRESS_HOLD = 4, /* 长按保持 */
KEY_EVENT_NUM, /* 事件总数 */
KEY_NONE_EVENT /* 默认无事件 */
} KEY_EVENT;
typedef void (*Key_EventCallback)(uint8_t id, KEY_EVENT event);
struct BSP_KEY
{
KEY_EVENT event; /* 按键事件记录 */
KEY_LEVEL press_level; /* 记录按下按键是什么电平(高或低) */
KEY_STATE key_state; /* 记录当前按键状态(按下或弹起) */
uint8_t id; /* 提供给用户的按键 id,由于有些用户可能想将所有的按键回调都写成一个函数接口,此举方便用户程序识别为是哪个按键触发了事件 */
/* 由数据类型可见,一个按键接口函数中最大支持256个按键 id */
uint8_t state; /* 状态机 */
uint8_t continuous_value; /* 按键连续采样缓存,一共8位深度,用于存取一个按键不同时刻的按键状态,最大是8次 */
uint16_t tick; /* 用于计时的临时变量 */
#if (KEY_USER_DEFINE_PRESS_TIME)
uint16_t press_time; /* 长按间隔时间 */
#endif
uint8_t (*GetState)(void); /* 按键电平状态获取函数,需要用户实现 */
Key_EventCallback Callback[ KEY_EVENT_NUM ]; /* 按键回调函数,由按键事件触发,需要用户实现 */
struct BSP_KEY *next; /* 简单的单向链表 */
};
#if (KEY_USER_DEFINE_PRESS_TIME)
int8_t BSP_Key_Init(struct BSP_KEY *key, uint8_t id, uint8_t (*KEY_GetState)(void), KEY_LEVEL press_level, uint16_t press_time);
#else
int8_t BSP_Key_Init(struct BSP_KEY *key, uint8_t id, uint8_t (*KEY_GetState)(void), KEY_LEVEL press_level);
#endif
int8_t BSP_Key_Start(struct BSP_KEY *key);
void BSP_Key_Register(struct BSP_KEY *key, KEY_EVENT event, Key_EventCallback callback);
void BSP_Key_Handler(uint8_t ms);
#endif
+359
View File
@@ -0,0 +1,359 @@
/**
* Change Logs:
* 优化中断开关
*/
/* Includes ------------------------------------------------------------------*/
#include "bsp_uart.h"
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static void UART_CopyDataToUserBuff (struct UART_STRUCT *uart);
static void UART_RxIntHandler (struct UART_STRUCT *uart);
static void UART_RxIdleHandler (struct UART_STRUCT *uart);
static void UART_TxHandler (struct UART_STRUCT *uart);
/* Exported functions ---------------------------------------------------------*/
/**
* @brief UART 组件初始化
* @note 仅支持已实现的串口
* @param[in] id: 串口 ID
* @retval BSP_UART_ERR
*/
BSP_UART_ERR BSP_UART_Init(BSP_UART_ID id)
{
/* GPIO/UART/DMA 等的初始化代码已由 cubeMX 生成 */
struct UART_STRUCT *uart = BSP_UART_Port_GetHandle(id);
if (uart == NULL)
return BSP_UART_ERR_NOT_FOUND;
if (uart->init)
return BSP_UART_ERR_NO_INIT;
BSP_UART_Port_Init( uart,
UART_RxIntHandler,
UART_RxIdleHandler,
UART_CopyDataToUserBuff,
UART_TxHandler);
BSP_INT_DIS();
uart->init = 1;
BSP_INT_EN();
return BSP_UART_ERR_OK;
}
/**
* @brief 使能UART接收数据
* @note
* @param[in] id: 串口 ID
* @param[in] data: 接收的数据池
* @param[in] len: 指示接收数据长度的变量
* @param[in] max_len: 数据池的最大容量,单位 byte
* @retval BSP_UART_ERR
*/
BSP_UART_ERR BSP_UART_EnableReceive(BSP_UART_ID id, uint8_t *data, uint16_t *len, uint16_t max_len)
{
ASSERT(data != NULL && len != NULL && max_len != 0);
BSP_UART_ERR ret;
struct UART_STRUCT *uart = BSP_UART_Port_GetHandle(id);
if (uart == NULL)
return BSP_UART_ERR_NOT_FOUND;
uart->rx_data = data;
uart->rx_data_len = len;
uart->rx_data_max_len = max_len;
ret = BSP_UART_Port_EnableReceive(uart);
BSP_INT_DIS();
uart->rx_init = 1;
BSP_INT_EN();
return ret;
}
/**
* @brief 禁止 UART 接收数据
* @note
* @param[in] id: 串口 ID
* @retval BSP_UART_ERR
*/
BSP_UART_ERR BSP_UART_DisableReceive(BSP_UART_ID id)
{
struct UART_STRUCT *uart = BSP_UART_Port_GetHandle(id);
if (uart == NULL)
return BSP_UART_ERR_NOT_FOUND;
BSP_INT_DIS();
uart->rx_init = 0;
BSP_INT_EN();
return BSP_UART_Port_DisableReceive(uart);
}
/**
* @brief 判断 UART 是否收到了一帧数据
* @note 该接口为轮询的方式
* @param[in] id: 串口 ID
* @retval BSP_UART_ERR
*/
BSP_UART_ERR BSP_UART_IsFrameEnd(BSP_UART_ID id)
{
struct UART_STRUCT *uart = BSP_UART_Port_GetHandle(id);
if (uart == NULL)
return BSP_UART_ERR_NOT_FOUND;
// BSP_INT_DIS();
if (uart->idle_flag == 0)
{
// BSP_INT_EN();
return BSP_UART_ERR_NO_RECV_FRAME;
}
else
{
uart->idle_flag = 0;
// BSP_INT_EN();
return BSP_UART_ERR_OK;
}
}
/**
* @brief 挂载一个用户自定义的数据到 UART 对象上
* @note
* @param[in] id: 串口 ID
* @param[in] user_data: 用户自定义数据
* @retval BSP_UART_ERR
*/
BSP_UART_ERR BSP_UART_LinkUserData(BSP_UART_ID id, void *user_data)
{
struct UART_STRUCT *uart = BSP_UART_Port_GetHandle(id);
if (uart == NULL)
return BSP_UART_ERR_NOT_FOUND;
uart->user_data = user_data;
return BSP_UART_ERR_OK;
}
/**
* @brief 设置 UART 的发送完成指示回调函数
* @note
* @param[in] id: 串口 ID
* @param[in] TX_Complete: 函数指针
* @retval BSP_UART_ERR
*/
BSP_UART_ERR BSP_UART_SetTxIndicate(BSP_UART_ID id, uint8_t (*TX_Complete)(struct UART_STRUCT *uart))
{
struct UART_STRUCT *uart = BSP_UART_Port_GetHandle(id);
if (uart == NULL)
return BSP_UART_ERR_NOT_FOUND;
uart->TX_Complete = TX_Complete;
return BSP_UART_ERR_OK;
}
/**
* @brief 从 UART 发出一些数据
* @note 若使用 RTOS ,则 BSP_UART_Send、 BSP_UART_SendBlocking 均不能在中断中使用
* @param[in] id: 串口ID
* @param[in] data: 要发送的数据池
* @param[in] len: 要发送的数据长度,单位 byte
* @param[in] timeout: 发送最大超时等待时间,单位 ms
* @retval BSP_UART_ERR
*/
BSP_UART_ERR BSP_UART_Send(BSP_UART_ID id, const uint8_t *data, uint16_t len, uint16_t timeout)
{
ASSERT(data != NULL && len != 0);
struct UART_STRUCT *uart = BSP_UART_Port_GetHandle(id);
if (uart == NULL)
return BSP_UART_ERR_NOT_FOUND;
if (uart->init == 0)
return BSP_UART_ERR_NO_INIT;
return BSP_UART_Port_Send(uart, data, len, timeout);
}
/**
* @brief 清除用户传入的 UART 数据缓存池
* @note
* @param[in] id: 串口 ID
* @retval BSP_UART_ERR
*/
BSP_UART_ERR BSP_UART_ClearUserBuff(BSP_UART_ID id)
{
struct UART_STRUCT *uart = BSP_UART_Port_GetHandle(id);
if (uart == NULL)
return BSP_UART_ERR_NOT_FOUND;
BSP_INT_DIS();
if (uart->rx_data_len)
*(uart->rx_data_len) = 0;
BSP_INT_EN();
return BSP_UART_ERR_OK;
}
/* Private functions ---------------------------------------------------------*/
/**
* @brief 将 DMA 缓存池的 UART 数据搬运到用户数据池中
* @note
* @param[in] uart: UART 对象
* @retval None
*/
static void UART_CopyDataToUserBuff(struct UART_STRUCT *uart)
{
if (*(uart->rx_data_len) >= uart->rx_data_max_len)
return;
// BSP_INT_DIS();
uint8_t *user_buff = &uart->rx_data[0];
uint16_t *user_buff_len = (uint16_t *)(uart->rx_data_len);
uint16_t new_pos = uart->rx_buff_max_len - BSP_UART_Port_GetDmaCounter(uart); /* 计算缓冲区的接收字节数 */
uint16_t recv_len = 0;
if (new_pos != uart->old_pos) /* 收到新的数据 */
{
if (new_pos > uart->old_pos) /* 线性模式 */
{
recv_len = new_pos - uart->old_pos; /* 计算本次接收到的字节数 */
/* 数据超出用户 buff ,只能接收用户 buff 剩余空间的长度数据 */
if ((*user_buff_len) + recv_len > uart->rx_data_max_len)
{
recv_len = uart->rx_data_max_len - *user_buff_len;
}
memcpy(&user_buff[*user_buff_len], &uart->rx_buff[ uart->old_pos ], recv_len);
(*user_buff_len) += recv_len; /* 设置偏移量 */
}
else /* 溢出模式 */
{
/* 先处理未溢出的部分 */
recv_len = uart->rx_buff_max_len - uart->old_pos;
/* 数据超出用户 buff ,只能接收用户 buff 剩余空间的长度数据 */
if (*user_buff_len + recv_len > uart->rx_data_max_len)
{
recv_len = uart->rx_data_max_len - *user_buff_len;
}
memcpy(&user_buff[*user_buff_len], &uart->rx_buff[ uart->old_pos ], recv_len);
*user_buff_len += recv_len; /* 设置偏移量 */
/* 再处理溢出的部分 */
recv_len = new_pos;
if (recv_len != 0)
{
/* 数据超出用户 buff ,只能接收用户 buff 剩余空间的长度数据 */
if (*user_buff_len + recv_len > uart->rx_data_max_len)
{
recv_len = uart->rx_data_max_len - *user_buff_len;
}
memcpy(&user_buff[*user_buff_len], &uart->rx_buff[0], recv_len);
(*user_buff_len) += recv_len; /* 设置偏移量 */
}
}
}
uart->old_pos = new_pos;
if (uart->old_pos >= uart->rx_buff_max_len)
{
uart->old_pos = 0;
}
// BSP_INT_EN();
}
/**
* @brief 串口接收到单字节数据的中断处理函数
* @note
* @param[in] uart: UART 对象
* @retval None
*/
static void UART_RxIntHandler(struct UART_STRUCT *uart)
{
if (uart->rx_init == 0)
return;
uart->rx_data[ *(uart->rx_data_len) ] = (uint8_t)BSP_UART_Port_GetOneByte(uart);
*(uart->rx_data_len) += 1;
if (*(uart->rx_data_len) == uart->rx_data_max_len)
{
*(uart->rx_data_len) = 0;
}
}
/**
* @brief 串口发生空闲中断的处理函数
* @note
* @param[in] uart: UART 对象
* @retval None
*/
static void UART_RxIdleHandler(struct UART_STRUCT *uart)
{
if (uart->rx_init == 0)
return;
// BSP_INT_DIS();
uart->idle_flag = 1;
// BSP_INT_EN();
if (uart->handle.hdmarx)
UART_CopyDataToUserBuff(uart);
BSP_UART_Port_RxUnlock(uart);
}
/**
* @brief 串口发送完成的中断处理函数
* @note
* @param[in] uart: UART 对象
* @retval None
*/
static void UART_TxHandler(struct UART_STRUCT *uart)
{
BSP_UART_Port_TxUnlock(uart);
if (uart->TX_Complete)
uart->TX_Complete(uart);
}
+145
View File
@@ -0,0 +1,145 @@
#ifndef __BSP_UART_H__
#define __BSP_UART_H__
#include "bsp_common.h"
#include "bsp_uart_config.h"
#define UART_INIT_PARA(x) \
{ \
.id = BSP_UART##x, \
.rx_buff = _uart##x##_buff, \
.rx_buff_max_len = BSP_UART_BUFF_SIZE, \
}
#define UART(x) _uart##x
#define UART_CREATE(x) static uint8_t _uart##x##_buff[BSP_UART_BUFF_SIZE]; \
static struct UART_STRUCT _uart##x = UART_INIT_PARA(x);
/* 定义项 */
typedef enum
{
#if (BSP_USING_UART1)
BSP_UART1 = 0x01,
#endif
#if (BSP_USING_UART2)
BSP_UART2 = 0x02,
#endif
#if (BSP_USING_UART2_RE)
BSP_UART2_RE = 0x82,
#endif
#if (BSP_USING_UART3)
BSP_UART3 = 0x03,
#endif
#if (BSP_USING_UART3_RE)
BSP_UART3_RE = 0x83,
#endif
#if (BSP_USING_UART4)
BSP_UART4 = 0x04,
#endif
#if (BSP_USING_UART5)
BSP_UART5 = 0x05,
#endif
#if (BSP_USING_UART6)
BSP_UART6 = 0x06,
#endif
} BSP_UART_ID;
typedef enum
{
BSP_UART_ERR_OK = 0x00U,
BSP_UART_ERR_COMM_ERR = 0x01U, /* 通讯错误(源自 HAL 库) */
BSP_UART_ERR_BUSY = 0x02U, /* UART 外设忙碌(源自 HAL 库) */
BSP_UART_ERR_TIMEOUT = 0x03U, /* 处理时间超时(源自 HAL 库) */
BSP_UART_ERR_NOT_FOUND = 0x04U, /* 未找到对应的 UART 对象 */
BSP_UART_ERR_LOCK_INIT_ERR = 0x05U, /* 通讯信号锁初始化失败 */
BSP_UART_ERR_LOCK_ERR = 0x06U, /* 通讯信号上锁失败 */
BSP_UART_ERR_UNLOCK_ERR = 0x07U, /* 通讯信号解锁失败 */
BSP_UART_ERR_NO_RECV_FRAME = 0x08U, /* 还未收到一帧完整的数据 */
BSP_UART_ERR_NO_INIT = 0x09U, /* 使用的 UART 对象还未初始化 */
BSP_UART_ERR_NAME_DUPLICATE = 0x0AU, /* UART 对象命名重复 */
} BSP_UART_ERR;
struct UART_STRUCT
{
UART_HandleTypeDef handle;
/* 串口唯一标识信息 */
const uint8_t id;
/* 用户串口数据,需要用户传入(二级缓存),当一级缓存半满和全满时,将会写入二级缓存 */
uint8_t *rx_data;
uint16_t * volatile rx_data_len;
uint16_t rx_data_max_len;
/* 一些标志位 */
volatile uint8_t init :1; /* 串口组件初始化标志位 */
volatile uint8_t rx_init :1; /* 串口组件的接收功能初始化标志位 */
// volatile uint8_t user_buff_full :1; /* 暂无使用 */
volatile uint8_t idle_flag :1; /* 是否发生空闲中断的标志位 */
volatile uint8_t :0;
/* 串口数据一级缓存(由 DMA 无条件写入) */
const uint8_t *rx_buff;
const uint16_t rx_buff_max_len;
/* 环形缓存的“写”位置 */
uint16_t old_pos;
/* 回调函数 */
uint8_t (*RX_Indicate)(struct UART_STRUCT *uart);
uint8_t (*TX_Complete)(struct UART_STRUCT *uart);
void *user_data;
};
typedef void (*UART_Callback_t)(struct UART_STRUCT *uart);
/**
* BSP UART 用户接口
*/
BSP_UART_ERR BSP_UART_Init (BSP_UART_ID id);
BSP_UART_ERR BSP_UART_EnableReceive (BSP_UART_ID id, uint8_t *data, uint16_t *len, uint16_t max_len);
BSP_UART_ERR BSP_UART_DisableReceive (BSP_UART_ID id);
BSP_UART_ERR BSP_UART_LinkUserData (BSP_UART_ID id, void *user_data);
BSP_UART_ERR BSP_UART_Send (BSP_UART_ID id, const uint8_t *data, uint16_t len, uint16_t timeout);
#if (ENABLE_DEBUG_PRINT)
void BSP_Printf (const char *fmt, ...);
#endif
BSP_UART_ERR BSP_UART_SetTxIndicate (BSP_UART_ID id, uint8_t (*TX_Complete)(struct UART_STRUCT *uart));
BSP_UART_ERR BSP_UART_ClearUserBuff (BSP_UART_ID id);
BSP_UART_ERR BSP_UART_IsFrameEnd (BSP_UART_ID id);
/**
* BSP UART 移植接口,不对外使用
*/
void BSP_UART_Port_Init ( struct UART_STRUCT *uart,
UART_Callback_t rx_callback,
UART_Callback_t rx_idle_callback,
UART_Callback_t dma_rx_callback,
UART_Callback_t dma_tx_callback);
BSP_UART_ERR BSP_UART_Port_EnableReceive (struct UART_STRUCT *uart);
BSP_UART_ERR BSP_UART_Port_DisableReceive (struct UART_STRUCT *uart);
BSP_UART_ERR BSP_UART_Port_Send (struct UART_STRUCT *uart, const uint8_t *data, uint16_t len, uint16_t timeout);
uint32_t BSP_UART_Port_GetDmaCounter (struct UART_STRUCT *uart);
uint32_t BSP_UART_Port_GetOneByte (struct UART_STRUCT *uart);
struct UART_STRUCT *BSP_UART_Port_GetHandle (BSP_UART_ID id);
/* 通讯锁 */
BSP_UART_ERR BSP_UART_Port_LockInit (struct UART_STRUCT *uart);
BSP_UART_ERR BSP_UART_Port_RxLock (struct UART_STRUCT *uart);
BSP_UART_ERR BSP_UART_Port_RxUnlock (struct UART_STRUCT *uart);
BSP_UART_ERR BSP_UART_Port_TxLock (struct UART_STRUCT *uart);
BSP_UART_ERR BSP_UART_Port_TxUnlock (struct UART_STRUCT *uart);
#endif
+61
View File
@@ -0,0 +1,61 @@
#ifndef __BSP_UART_CONFIG_H__
#define __BSP_UART_CONFIG_H__
#include "app_config.h"
#define BSP_PRINTF_BUFF_SIZE 256
#define BSP_PRINTF_HANDLE UART(1)
#define BSP_UART_BUFF_SIZE 64
#define BSP_USING_UART1 1
#define BSP_USING_UART2 1
#define BSP_USING_UART2_RE 0
#define BSP_USING_UART3 0
#define BSP_USING_UART3_RE 0
#define BSP_USING_UART4 0
#define BSP_USING_UART5 0
#define BSP_USING_UART6 0
/* 配置项 */
#define UART1_HANDLE huart1
#define UART2_HANDLE huart2
#define UART3_HANDLE huart3
#define UART4_HANDLE huart4
#define UART5_HANDLE huart5
#define UART6_HANDLE huart6
/* 移植时到不同型号的单片机时需要修改 */
#if defined(STM32F411xE)||defined(STM32F401xC)
#define UART1_DMA_RX_IRQHandler DMA2_Stream2_IRQHandler
#define UART1_DMA_TX_IRQHandler DMA2_Stream7_IRQHandler
#define UART2_DMA_RX_IRQHandler DMA1_Stream5_IRQHandler
#define UART2_DMA_TX_IRQHandler DMA1_Stream6_IRQHandler
#define UART6_DMA_RX_IRQHandler DMA2_Stream1_IRQHandler
#define UART6_DMA_TX_IRQHandler DMA2_Stream6_IRQHandler
#elif defined(STM32F407xx) || defined(STM32F405xx)
#define UART1_DMA_RX_IRQHandler DMA2_Stream2_IRQHandler
#define UART1_DMA_TX_IRQHandler DMA2_Stream7_IRQHandler
#define UART2_DMA_RX_IRQHandler DMA1_Stream5_IRQHandler
#define UART2_DMA_TX_IRQHandler DMA1_Stream6_IRQHandler
#define UART3_DMA_RX_IRQHandler DMA1_Stream1_IRQHandler
#define UART3_DMA_TX_IRQHandler DMA1_Stream3_IRQHandler
#define UART4_DMA_RX_IRQHandler DMA1_Stream2_IRQHandler
#define UART4_DMA_TX_IRQHandler DMA1_Stream4_IRQHandler
#define UART5_DMA_RX_IRQHandler DMA1_Stream0_IRQHandler
#define UART5_DMA_TX_IRQHandler DMA1_Stream7_IRQHandler
#define UART6_DMA_RX_IRQHandler DMA2_Stream1_IRQHandler
#define UART6_DMA_TX_IRQHandler DMA2_Stream6_IRQHandler
#elif defined(STM32F103xE) || defined(STM32F103xB)
#define UART1_DMA_RX_IRQHandler DMA1_Channel5_IRQHandler
#define UART1_DMA_TX_IRQHandler DMA1_Channel4_IRQHandler
#define UART2_DMA_RX_IRQHandler DMA1_Channel6_IRQHandler
#define UART3_DMA_RX_IRQHandler DMA1_Channel3_IRQHandler
#define UART4_DMA_RX_IRQHandler DMA2_Channel3_IRQHandler
#elif defined(STM32L475xx)
#define UART1_DMA_RX_IRQHandler DMA1_Channel5_IRQHandler
#define UART1_DMA_TX_IRQHandler DMA1_Channel4_IRQHandler
#endif
#endif
+693
View File
@@ -0,0 +1,693 @@
/**
* Change Logs:
* 憓𧼮 __HAL_UART_FLUSH_DRREGISTER
*/
/* Includes ------------------------------------------------------------------*/
#include "bsp_uart.h"
/* Private variables ---------------------------------------------------------*/
#if (BSP_USING_UART2_RE || BSP_USING_UART3_RE)
static volatile uint8_t _uart2_alter;
static volatile uint8_t _uart3_alter;
#endif
static UART_Callback_t _UART_RxCallback;
static UART_Callback_t _UART_RxIdleCallback;
static UART_Callback_t _UART_DMA_RxCallback;
static UART_Callback_t _UART_DMA_TxCallback;
#if (BSP_USING_UART1)
UART_CREATE(1);
#endif
#if (BSP_USING_UART2)
UART_CREATE(2);
#endif
#if (BSP_USING_UART2_RE)
UART_CREATE(2_RE);
#endif
#if (BSP_USING_UART3)
UART_CREATE(3);
#endif
#if (BSP_USING_UART3_RE)
UART_CREATE(3_RE);
#endif
#if (BSP_USING_UART4)
UART_CREATE(4);
#endif
#if (BSP_USING_UART5)
UART_CREATE(5);
#endif
#if (BSP_USING_UART6)
UART_CREATE(6);
#endif
struct UART_STRUCT *_uart_group[] =
{
#if (BSP_USING_UART1)
&UART(1),
#endif
#if (BSP_USING_UART2)
&UART(2),
#endif
#if (BSP_USING_UART2_RE)
&UART(2_RE),
#endif
#if (BSP_USING_UART3)
&UART(3),
#endif
#if (BSP_USING_UART3_RE)
&UART(3_RE),
#endif
#if (BSP_USING_UART4)
&UART(4),
#endif
#if (BSP_USING_UART5)
&UART(5),
#endif
#if (BSP_USING_UART6)
&UART(6),
#endif
};
static const uint8_t _uart_qty = sizeof(_uart_group) / sizeof(struct UART_STRUCT *);
/* Private function prototypes -----------------------------------------------*/
static inline void _UART_IntHandler (struct UART_STRUCT *uart);
static inline void _UART_Alternate (struct UART_STRUCT *uart);
/* Exported functions ---------------------------------------------------------*/
/**
* @brief UART 亙藁? * @note ?UART 憭𤥁挽𡝗𧋦賣㺭憭銵?UART 憭𤥁挽滚虾靚
* @param[in] uart: UART 撖寡情
* @param[in] rx_callback: 交𤣰桐葉賣㺭
* @param[in] rx_idle_callback: 蝛粹𤦭銝剜鱏? * @param[in] dma_rx_callback: DMA 交𤣰銝剜鱏? * @param[in] dma_tx_callback: DMA 賣㺭
* @retval None
*/
void BSP_UART_Port_Init( struct UART_STRUCT *uart,
UART_Callback_t rx_callback,
UART_Callback_t rx_idle_callback,
UART_Callback_t dma_rx_callback,
UART_Callback_t dma_tx_callback)
{
BSP_UART_Port_LockInit(uart);
_UART_RxCallback = rx_callback;
_UART_RxIdleCallback = rx_idle_callback;
_UART_DMA_RxCallback = dma_rx_callback;
_UART_DMA_TxCallback = dma_tx_callback;
/**
* 敶?uart->handle 霈曄眏蝟餌𡝗𧒄嚗䔶憒?CubeMX 憪见嚗䔶誑銝贝雿𨀣糓敹? * 嚗屸䌊撌勗 uart->handle ? * 望迨嚗?BSP_UART_Port_Init ?UART 憭𤥁挽𡝗𧋦賣㺭憭銵?UART 憭𤥁挽滚虾靚? */
switch (uart->id)
{
#if (BSP_USING_UART1)
case BSP_UART1: uart->handle = UART1_HANDLE; break;
#endif
#if (BSP_USING_UART2)
case BSP_UART2: uart->handle = UART2_HANDLE; break;
#endif
#if (BSP_USING_UART2_RE)
case BSP_UART2_RE: uart->handle = UART2_HANDLE; break;
#endif
#if (BSP_USING_UART3)
case BSP_UART3: uart->handle = UART3_HANDLE; break;
#endif
#if (BSP_USING_UART3_RE)
case BSP_UART3_RE: uart->handle = UART3_HANDLE; break;
#endif
#if (BSP_USING_UART4)
case BSP_UART4: uart->handle = UART4_HANDLE; break;
#endif
#if (BSP_USING_UART5)
case BSP_UART5: uart->handle = UART5_HANDLE; break;
#endif
#if (BSP_USING_UART6)
case BSP_UART6: uart->handle = UART6_HANDLE; break;
#endif
default: break;
}
if (uart->handle.hdmatx)
uart->handle.hdmatx->Parent = &uart->handle;
/* Clean the input path */
__HAL_UART_FLUSH_DRREGISTER(&uart->handle);
}
/**
* @brief UART 亙藁帋縑? * @note
* @param[in] uart: UART 撖寡情
* @retval BSP_UART_ERR
*/
BSP_UART_ERR BSP_UART_Port_LockInit(struct UART_STRUCT *uart)
{
return BSP_UART_ERR_OK;
}
/**
* @brief UART 蝑匧交𤣰唳旿
* @note
* @param[in] uart: UART 撖寡情
* @retval BSP_UART_ERR
*/
inline BSP_UART_ERR BSP_UART_Port_RxLock(struct UART_STRUCT *uart)
{
return BSP_UART_ERR_OK;
}
/**
* @brief UART 交𤣰唳㺭靽∪噡? * @note
* @param[in] uart: UART 撖寡情
* @retval BSP_UART_ERR
*/
inline BSP_UART_ERR BSP_UART_Port_RxUnlock(struct UART_STRUCT *uart)
{
return BSP_UART_ERR_OK;
}
/**
* @brief UART
* @note
* @param[in] uart: UART 撖寡情
* @retval BSP_UART_ERR
*/
inline BSP_UART_ERR BSP_UART_Port_TxLock(struct UART_STRUCT *uart)
{
return BSP_UART_ERR_OK;
}
/**
* @brief UART 瘥閗圾? * @note
* @param[in] uart: UART 撖寡情
* @retval BSP_UART_ERR
*/
inline BSP_UART_ERR BSP_UART_Port_TxUnlock(struct UART_STRUCT *uart)
{
return BSP_UART_ERR_OK;
}
/**
* @brief 雿輯 UART 交𤣰唳旿
* @note
* @param[in] uart: UART 撖寡情
* @retval BSP_UART_ERR
*/
BSP_UART_ERR BSP_UART_Port_EnableReceive(struct UART_STRUCT *uart)
{
BSP_UART_ERR ret = BSP_UART_ERR_OK;
if (uart->handle.hdmarx)
uart->handle.hdmarx->Parent = &uart->handle;
_UART_Alternate(uart);
if (uart->handle.hdmarx)
ret = (BSP_UART_ERR)HAL_UART_Receive_DMA(&uart->handle, (uint8_t *)uart->rx_buff, uart->rx_buff_max_len);
else
__HAL_UART_ENABLE_IT(&uart->handle, UART_IT_RXNE);
/* 撘舐征脖葉?*/
__HAL_UART_ENABLE_IT(&uart->handle, UART_IT_IDLE);
return ret;
}
/**
* @brief 蝳迫 UART 交𤣰唳旿
* @note
* @param[in] uart: UART 撖寡情
* @retval BSP_UART_ERR
*/
BSP_UART_ERR BSP_UART_Port_DisableReceive(struct UART_STRUCT *uart)
{
BSP_UART_ERR ret = BSP_UART_ERR_OK;
if (uart->handle.hdmarx)
ret = (BSP_UART_ERR)HAL_UART_DMAPause(&uart->handle);
else
__HAL_UART_DISABLE_IT(&uart->handle, UART_IT_RXNE);
__HAL_UART_DISABLE_IT(&uart->handle, UART_IT_IDLE);
return ret;
}
/**
* @brief UART 撣扳㺭? * @note
* @param[in] uart: UART 撖寡情
* @param[in] data: 閬唳旿
* @param[in] len: 閬唳旿踹漲嚗雿?byte憭折鵭摨? 65535 byte
* @param[in] timeout: 憭批嗆𧒄 ms憭扳摰𡁏𧒄? 65535 ms
* @retval BSP_UART_ERR
*/
BSP_UART_ERR BSP_UART_Port_Send(struct UART_STRUCT *uart, const uint8_t *data, uint16_t len, uint16_t timeout)
{
_UART_Alternate(uart);
if (timeout == 0)
{
if (uart->handle.hdmatx)
return (BSP_UART_ERR)HAL_UART_Transmit_DMA(&uart->handle, (uint8_t *)data, len);
else
return (BSP_UART_ERR)HAL_UART_Transmit_IT(&uart->handle, (uint8_t *)data, len);
}
else
return (BSP_UART_ERR)HAL_UART_Transmit(&uart->handle, (uint8_t *)data, len, timeout);
}
/**
* @brief 隞?UART 銝芸唳旿
* @note
* @param[in] uart: UART 撖寡情
* @retval UART 唳旿
*/
inline uint32_t BSP_UART_Port_GetOneByte(struct UART_STRUCT *uart)
{
return uart->handle.Instance->DR;
}
/**
* @brief DMA 敶枏? * @note
* @param[in] uart: UART 撖寡情
* @retval 霈⊥㺭? */
inline uint32_t BSP_UART_Port_GetDmaCounter(struct UART_STRUCT *uart)
{
return __HAL_DMA_GET_COUNTER(uart->handle.hdmarx);
}
/**
* @brief UART ID UART 撖寡情
* @note
* @param[in] id: 銝脣藁 ID
* @retval NULL: ?ID NULL: UART 撖寡情
*/
struct UART_STRUCT *BSP_UART_Port_GetHandle(BSP_UART_ID id)
{
for (uint8_t i = 0; i < _uart_qty; i++)
{
if (_uart_group[i]->id == id)
{
return _uart_group[i];
}
}
return NULL;
}
/* Private functions ---------------------------------------------------------*/
/**
* @brief UART 銝剜鱏銝剖? * @note
* @param[in] uart: UART 撖寡情
* @retval None
*/
static inline void _UART_IntHandler(struct UART_STRUCT *uart)
{
if (uart->handle.Instance == NULL)
return;
if (__HAL_UART_GET_FLAG(&uart->handle, UART_FLAG_RXNE) != RESET)
{
/* RXNE 銝剜鱏雿滢刻粉?DR 撖瘜閧&摰?_UART_RxCallback 臬炏隡朞粉靝R撖
隞亙銁甇文餈𥡝甈⊥?*/
__HAL_UART_CLEAR_FLAG(&uart->handle, UART_FLAG_RXNE);
if (_UART_RxCallback)
_UART_RxCallback(uart);
}
else if ((__HAL_UART_GET_FLAG(&uart->handle, UART_FLAG_IDLE) != RESET)
&& (__HAL_UART_GET_IT_SOURCE(&uart->handle, UART_IT_IDLE) != RESET))
{
/* IDLE 銝剜鱏雿滚蘨質蔓隞嗆?*/
__HAL_UART_CLEAR_IDLEFLAG(&uart->handle);
if (_UART_RxIdleCallback)
_UART_RxIdleCallback(uart);
}
else
{
HAL_UART_IRQHandler(&(uart->handle));
}
}
/**
* @brief 銝脣藁憭滨鍂賣㺭
* @note
* @param[in] uart: UART 撖寡情
* @retval None
*/
static inline void _UART_Alternate(struct UART_STRUCT *uart)
{
#if (BSP_USING_UART2_RE || BSP_USING_UART3_RE)
switch (uart->id)
{
case BSP_UART2:
case BSP_UART2_RE:
{
if (_uart2_alter != uart->id) /* 憭滨鍂揢 */
{
if (uart->id == BSP_UART2)
{
BSP_GPIO_SetMode(GET_PIN(A, 2), GPIO_MODE_AF_PP, GPIO_PULLUP); /* TX */
BSP_GPIO_SetMode(GET_PIN(A, 3), GPIO_MODE_INPUT, GPIO_PULLUP); /* RX */
__HAL_AFIO_REMAP_USART2_DISABLE();
}
else
{
BSP_GPIO_SetMode(GET_PIN(D, 5), GPIO_MODE_AF_PP, GPIO_PULLUP); /* TX */
BSP_GPIO_SetMode(GET_PIN(D, 6), GPIO_MODE_INPUT, GPIO_PULLUP); /* RX */
__HAL_AFIO_REMAP_USART2_ENABLE();
}
_uart2_alter = uart->id;
}
break;
}
case BSP_UART3:
case BSP_UART3_RE:
{
if (_uart3_alter != uart->id) /* 憭滨鍂揢 */
{
if (uart->id == BSP_UART3)
{
BSP_GPIO_SetMode(GET_PIN(B, 10), GPIO_MODE_AF_PP, GPIO_PULLUP); /* TX */
BSP_GPIO_SetMode(GET_PIN(B, 11), GPIO_MODE_INPUT, GPIO_PULLUP); /* RX */
__HAL_AFIO_REMAP_USART3_DISABLE();
}
else
{
BSP_GPIO_SetMode(GET_PIN(D, 8), GPIO_MODE_AF_PP, GPIO_PULLUP); /* TX */
BSP_GPIO_SetMode(GET_PIN(D, 9), GPIO_MODE_INPUT, GPIO_PULLUP); /* RX */
__HAL_AFIO_REMAP_USART3_ENABLE();
}
_uart3_alter = uart->id;
}
break;
}
default: break;
}
#endif
}
/* Callback functions ---------------------------------------------------------*/
/* 隞乩 4 銝芸遆?HAL 摨?UART 剖遆賣㺭 */
/* UART DMA 交𤣰𦠜說銝剜鱏 */
void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
{
struct UART_STRUCT *uart = (struct UART_STRUCT *)huart;
if (_UART_DMA_RxCallback)
_UART_DMA_RxCallback(uart);
}
/* UART DMA 交𤣰冽說銝剜鱏 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
struct UART_STRUCT *uart = (struct UART_STRUCT *)huart;
if (_UART_DMA_RxCallback)
_UART_DMA_RxCallback(uart);
}
/* UART DMA 𣂷葉?*/
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
struct UART_STRUCT *uart = (struct UART_STRUCT *)huart;
if (_UART_DMA_TxCallback)
_UART_DMA_TxCallback(uart);
}
/* UART 銝剜鱏璉瘚见躰秤?*/
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
struct UART_STRUCT *uart = (struct UART_STRUCT *)huart;
//printf("%s: %d %d\r\n", __FUNCTION__, uart->id, huart->ErrorCode);
}
/* Interrupt request functions ---------------------------------------------------------*/
#if (BSP_USING_UART1)
void USART1_IRQHandler(void)
{
BSP_INT_ENTER();
_UART_IntHandler(&UART(1));
BSP_INT_EXIT();
}
void UART1_DMA_RX_IRQHandler(void)
{
BSP_INT_ENTER();
if (UART(1).rx_init)
{
HAL_DMA_IRQHandler(UART(1).handle.hdmarx);
}
BSP_INT_EXIT();
}
void UART1_DMA_TX_IRQHandler(void)
{
BSP_INT_ENTER();
HAL_DMA_IRQHandler(UART(1).handle.hdmatx);
BSP_INT_EXIT();
}
#endif
#if (BSP_USING_UART2)
void USART2_IRQHandler(void)
{
BSP_INT_ENTER();
#if (BSP_USING_UART2_RE)
if (_uart2_alter == BSP_UART2)
_UART_IntHandler(&UART(2));
else
_UART_IntHandler(&UART(2_RE));
#else
_UART_IntHandler(&UART(2));
#endif
BSP_INT_EXIT();
}
void UART2_DMA_RX_IRQHandler(void)
{
BSP_INT_ENTER();
if (UART(2).rx_init)
{
#if (BSP_USING_UART2_RE)
if (_uart2_alter == BSP_UART2)
HAL_DMA_IRQHandler(UART(2).handle.hdmarx);
else
HAL_DMA_IRQHandler(UART(2_RE).handle.hdmarx);
#else
HAL_DMA_IRQHandler(UART(2).handle.hdmarx);
#endif
}
BSP_INT_EXIT();
}
void UART2_DMA_TX_IRQHandler(void)
{
BSP_INT_ENTER();
#if (BSP_USING_UART2_RE)
if (_uart2_alter == BSP_UART2)
HAL_DMA_IRQHandler(UART(2).handle.hdmatx);
else
HAL_DMA_IRQHandler(UART(2_RE).handle.hdmarx);
#else
HAL_DMA_IRQHandler(UART(2).handle.hdmarx);
#endif
BSP_INT_EXIT();
}
#endif
#if (BSP_USING_UART3)
void USART3_IRQHandler(void)
{
BSP_INT_ENTER();
#if (BSP_USING_UART3_RE)
if (_uart3_alter == BSP_UART3)
_UART_IntHandler(&UART(3));
else
_UART_IntHandler(&UART(3_RE));
#else
_UART_IntHandler(&UART(3));
#endif
BSP_INT_EXIT();
}
void UART3_DMA_RX_IRQHandler(void)
{
BSP_INT_ENTER();
if (UART(3).rx_init)
{
#if (BSP_USING_UART3_RE)
if (_uart3_alter == BSP_UART3)
HAL_DMA_IRQHandler(UART(3).handle.hdmarx);
else
HAL_DMA_IRQHandler(UART(3_RE).handle.hdmarx);
#else
HAL_DMA_IRQHandler(UART(3).handle.hdmarx);
#endif
}
BSP_INT_EXIT();
}
void UART3_DMA_TX_IRQHandler(void)
{
BSP_INT_ENTER();
#if (BSP_USING_UART3_RE)
if (_uart3_alter == BSP_UART3)
HAL_DMA_IRQHandler(UART(3).handle.hdmarx);
else
HAL_DMA_IRQHandler(UART(3_RE).handle.hdmarx);
#else
HAL_DMA_IRQHandler(UART(3).handle.hdmarx);
#endif
BSP_INT_EXIT();
}
#endif
#if (BSP_USING_UART4)
void UART4_IRQHandler(void)
{
BSP_INT_ENTER();
_UART_IntHandler(&UART(4));
BSP_INT_EXIT();
}
void UART4_DMA_RX_IRQHandler(void)
{
BSP_INT_ENTER();
if (UART(4).rx_init)
{
HAL_DMA_IRQHandler(UART(4).handle.hdmarx);
}
BSP_INT_EXIT();
}
void UART4_DMA_TX_IRQHandler(void)
{
BSP_INT_ENTER();
HAL_DMA_IRQHandler(UART(4).handle.hdmatx);
BSP_INT_EXIT();
}
#endif
#if (BSP_USING_UART5)
void UART5_IRQHandler(void)
{
BSP_INT_ENTER();
_UART_IntHandler(&UART(5));
BSP_INT_EXIT();
}
void UART5_DMA_RX_IRQHandler(void)
{
BSP_INT_ENTER();
if (UART(5).rx_init)
{
HAL_DMA_IRQHandler(UART(5).handle.hdmarx);
}
BSP_INT_EXIT();
}
void UART5_DMA_TX_IRQHandler(void)
{
BSP_INT_ENTER();
HAL_DMA_IRQHandler(UART(5).handle.hdmatx);
BSP_INT_EXIT();
}
#endif
#if (BSP_USING_UART6)
void USART6_IRQHandler(void)
{
BSP_INT_ENTER();
_UART_IntHandler(&UART(6));
BSP_INT_EXIT();
}
void UART6_DMA_RX_IRQHandler(void)
{
BSP_INT_ENTER();
if (UART(6).rx_init)
{
HAL_DMA_IRQHandler(UART(6).handle.hdmarx);
}
BSP_INT_EXIT();
}
void UART6_DMA_TX_IRQHandler(void)
{
BSP_INT_ENTER();
HAL_DMA_IRQHandler(UART(6).handle.hdmatx);
BSP_INT_EXIT();
}
#endif
+82
View File
@@ -0,0 +1,82 @@
#ifndef __INCLUDES_H__
#define __INCLUDES_H__
/* 配置文件 */
#include "app_config.h"
/* 用户库 */
#include "main.h"
/* 工具库 */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
/* Component */
#if (CONFIG_DECRYPT)
#include "aes.h"
#endif
//! \note for IAR
#ifdef __IS_COMPILER_IAR__
# undef __IS_COMPILER_IAR__
#endif
#if defined(__IAR_SYSTEMS_ICC__)
# define __IS_COMPILER_IAR__ 1
#endif
//! \note for arm compiler 5
#ifdef __IS_COMPILER_ARM_COMPILER_5__
# undef __IS_COMPILER_ARM_COMPILER_5__
#endif
#if ((__ARMCC_VERSION >= 5000000) && (__ARMCC_VERSION < 6000000))
# define __IS_COMPILER_ARM_COMPILER_5__ 1
#endif
//! @}
//! \note for arm compiler 6
#ifdef __IS_COMPILER_ARM_COMPILER_6__
# undef __IS_COMPILER_ARM_COMPILER_6__
#endif
#if ((__ARMCC_VERSION >= 6000000) && (__ARMCC_VERSION < 7000000))
# define __IS_COMPILER_ARM_COMPILER_6__ 1
#endif
#ifdef __IS_COMPILER_ARM_COMPILER__
# undef __IS_COMPILER_ARM_COMPILER__
#endif
#if defined(__IS_COMPILER_ARM_COMPILER_5__) && __IS_COMPILER_ARM_COMPILER_5__ \
|| defined(__IS_COMPILER_ARM_COMPILER_6__) && __IS_COMPILER_ARM_COMPILER_6__
# define __IS_COMPILER_ARM_COMPILER__ 1
#endif
#ifdef __IS_COMPILER_LLVM__
# undef __IS_COMPILER_LLVM__
#endif
#if defined(__clang__) && !__IS_COMPILER_ARM_COMPILER_6__
# define __IS_COMPILER_LLVM__ 1
#else
//! \note for gcc
#ifdef __IS_COMPILER_GCC__
# undef __IS_COMPILER_GCC__
#endif
#if defined(__GNUC__) && !(__IS_COMPILER_ARM_COMPILER_6__ || __IS_COMPILER_LLVM__)
# define __IS_COMPILER_GCC__ 1
#endif
//! @}
#endif
//! @}
#if (ENABLE_ASSERT)
extern void Assert_Failed(uint8_t *func, uint32_t line);
#define ASSERT(expr) ((expr) ? (void)0U : Assert_Failed((uint8_t *)__func__, __LINE__))
#else
#define ASSERT(expr) ((void)0U)
#endif
#endif
+130
View File
@@ -0,0 +1,130 @@
#include "drv_timer.h"
static struct drv_timer_t *timerHead;
void drv_timer_start (struct drv_timer_t *timer)
{
ASSERT(timer != NULL);
timer->start = 1;
}
void drv_timer_restart (struct drv_timer_t *timer)
{
ASSERT(timer != NULL);
timer->start = 0;
timer->time_temp = 0;
timer->period = timer->period_temp;
timer->start = 1;
}
void drv_timer_pause (struct drv_timer_t *timer)
{
ASSERT(timer != NULL);
timer->start = 0;
timer->time_temp = 0;
return;
}
void drv_timer_detach (struct drv_timer_t *timer)
{
struct drv_timer_t **now_target;
struct drv_timer_t *entry;
ASSERT(timer != NULL);
for (now_target = &timerHead; *now_target; ) {
entry = *now_target;
if (entry == timer) {
*now_target = entry->next;
return;
} else {
now_target = &entry->next;
}
}
return;
}
static void drv_timer_attach (struct drv_timer_t *timer)
{
struct drv_timer_t *target;
for (target = timerHead; target != NULL; target = target->next) {
if (target == timer) {
return;
}
}
timer->next = timerHead;
timerHead = timer;
}
// call in tick interrupt
void drv_timer_handler (uint8_t ms)
{
struct drv_timer_t *timer;
for (timer = timerHead; timer != NULL; timer = timer->next) {
if (timer->start) {
timer->time_temp += ms;
if (timer->time_temp >= timer->timeout) {
timer->time_temp = 0;
if ((timer->type & TIMER_TYPE_HARDWARE) != 0) {
if (timer->timerCallback) {
timer->timerCallback(timer->user_data);
}
if ((timer->type & TIMER_ONE_SHOT) != 0) {
--timer->period;
if (timer->period == 0) {
drv_timer_pause(timer);
}
}
} else {
timer->timeout_flag = 1;
}
}
}
}
}
void drv_timer_linkUserData (struct drv_timer_t *timer, void *user_data)
{
ASSERT(timer != NULL);
timer->user_data = user_data;
}
void drv_timer_init (struct drv_timer_t *timer,
void (*timerCallback)(void *user_data),
uint32_t timeout,
uint16_t period)
{
ASSERT(timer != NULL);
timer->period = period;
timer->timeout = timeout;
timer->type = TIMER_TYPE_HARDWARE;
timer->timerCallback = timerCallback;
timer->time_temp = 0;
timer->period_temp = period;
if (period == 0) {
timer->type |= TIMER_PERIODIC;
} else {
timer->type |= TIMER_ONE_SHOT;
}
drv_timer_attach(timer);
}
+58
View File
@@ -0,0 +1,58 @@
#ifndef __DRV_TIMER_H__
#define __DRV_TIMER_H__
#include "bsp_common.h"
#define TIMER_RUN_FOREVER 0
#define TIMER_RUN_ONE_SHOT 1
#define TIMER_ONE_SHOT (0x04)
#define TIMER_PERIODIC (0x08)
typedef enum {
TIMER_TYPE_HARDWARE = (0x01), // 硬件 timer ,实时性较强,定时精度较高,占用中断时间
TIMER_TYPE_SOFTWARE = (0x02) // 软件 timer ,实时性较差,定时精度较差,不占用中断时间
} eTIMERTYPE;
struct drv_timer_t {
void (*timerCallback)(void *user_data);
void *user_data;
eTIMERTYPE type; // 类型 bit3:持续 bit2:单次 bit1:软件 bit0:硬件
uint8_t start :1;
uint8_t timeout_flag :1;
uint8_t :0;
uint16_t period; // 执行次数
uint16_t period_temp; // 暂存执行次数, 用于重置
uint32_t timeout; // 计时,单位为 ms
uint32_t time_temp; // 计时计数
struct drv_timer_t *next;
};
extern void drv_timer_start (struct drv_timer_t *timer);
extern void drv_timer_restart (struct drv_timer_t *timer);
extern void drv_timer_pause (struct drv_timer_t *timer);
extern void drv_timer_detach (struct drv_timer_t *timer);
extern void drv_timer_handler (uint8_t ms);
extern void drv_timer_linkUserData (struct drv_timer_t *timer, void *user_data);
extern void drv_timer_init (struct drv_timer_t *timer,
void (*timerCallback)(void *user_data),
uint32_t timeout,
uint16_t period);
#endif /* __DRV_TIMER_H__ */
+569
View File
@@ -0,0 +1,569 @@
/*
This is an implementation of the AES algorithm, specifically ECB, CTR and CBC mode.
Block size can be chosen in aes.h - available choices are AES128, AES192, AES256.
The implementation is verified against the test vectors in:
National Institute of Standards and Technology Special Publication 800-38A 2001 ED
ECB-AES128
----------
plain-text:
6bc1bee22e409f96e93d7e117393172a
ae2d8a571e03ac9c9eb76fac45af8e51
30c81c46a35ce411e5fbc1191a0a52ef
f69f2445df4f9b17ad2b417be66c3710
key:
2b7e151628aed2a6abf7158809cf4f3c
resulting cipher
3ad77bb40d7a3660a89ecaf32466ef97
f5d3d58503b9699de785895a96fdbaaf
43b1cd7f598ece23881b00e3ed030688
7b0c785e27e8ad3f8223207104725dd4
NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0)
You should pad the end of the string with zeros if this is not the case.
For AES192/256 the key size is proportionally larger.
*/
/*****************************************************************************/
/* Includes: */
/*****************************************************************************/
#include <string.h> // CBC mode, for memset
#include "aes.h"
/*****************************************************************************/
/* Defines: */
/*****************************************************************************/
// The number of columns comprising a state in AES. This is a constant in AES. Value=4
#define Nb 4
#if defined(AES256) && (AES256 == 1)
#define Nk 8
#define Nr 14
#elif defined(AES192) && (AES192 == 1)
#define Nk 6
#define Nr 12
#else
#define Nk 4 // The number of 32 bit words in a key.
#define Nr 10 // The number of rounds in AES Cipher.
#endif
// jcallan@github points out that declaring Multiply as a function
// reduces code size considerably with the Keil ARM compiler.
// See this link for more information: https://github.com/kokke/tiny-AES-C/pull/3
#ifndef MULTIPLY_AS_A_FUNCTION
#define MULTIPLY_AS_A_FUNCTION 0
#endif
/*****************************************************************************/
/* Private variables: */
/*****************************************************************************/
// state - array holding the intermediate results during decryption.
typedef uint8_t state_t[4][4];
// The lookup-tables are marked const so they can be placed in read-only storage instead of RAM
// The numbers below can be computed dynamically trading ROM for RAM -
// This can be useful in (embedded) bootloader applications, where ROM is often limited.
static const uint8_t sbox[256] = {
//0 1 2 3 4 5 6 7 8 9 A B C D E F
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 };
static const uint8_t rsbox[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d };
// The round constant word array, Rcon[i], contains the values given by
// x to the power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8)
static const uint8_t Rcon[11] = {
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
/*
* Jordan Goulder points out in PR #12 (https://github.com/kokke/tiny-AES-C/pull/12),
* that you can remove most of the elements in the Rcon array, because they are unused.
*
* From Wikipedia's article on the Rijndael key schedule @ https://en.wikipedia.org/wiki/Rijndael_key_schedule#Rcon
*
* "Only the first some of these constants are actually used up to rcon[10] for AES-128 (as 11 round keys are needed),
* up to rcon[8] for AES-192, up to rcon[7] for AES-256. rcon[0] is not used in AES algorithm."
*/
/*****************************************************************************/
/* Private functions: */
/*****************************************************************************/
/*
static uint8_t getSBoxValue(uint8_t num)
{
return sbox[num];
}
*/
#define getSBoxValue(num) (sbox[(num)])
/*
static uint8_t getSBoxInvert(uint8_t num)
{
return rsbox[num];
}
*/
#define getSBoxInvert(num) (rsbox[(num)])
// This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states.
static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key)
{
unsigned i, j, k;
uint8_t tempa[4]; // Used for the column/row operations
// The first round key is the key itself.
for (i = 0; i < Nk; ++i)
{
RoundKey[(i * 4) + 0] = Key[(i * 4) + 0];
RoundKey[(i * 4) + 1] = Key[(i * 4) + 1];
RoundKey[(i * 4) + 2] = Key[(i * 4) + 2];
RoundKey[(i * 4) + 3] = Key[(i * 4) + 3];
}
// All other round keys are found from the previous round keys.
for (i = Nk; i < Nb * (Nr + 1); ++i)
{
{
k = (i - 1) * 4;
tempa[0]=RoundKey[k + 0];
tempa[1]=RoundKey[k + 1];
tempa[2]=RoundKey[k + 2];
tempa[3]=RoundKey[k + 3];
}
if (i % Nk == 0)
{
// This function shifts the 4 bytes in a word to the left once.
// [a0,a1,a2,a3] becomes [a1,a2,a3,a0]
// Function RotWord()
{
const uint8_t u8tmp = tempa[0];
tempa[0] = tempa[1];
tempa[1] = tempa[2];
tempa[2] = tempa[3];
tempa[3] = u8tmp;
}
// SubWord() is a function that takes a four-byte input word and
// applies the S-box to each of the four bytes to produce an output word.
// Function Subword()
{
tempa[0] = getSBoxValue(tempa[0]);
tempa[1] = getSBoxValue(tempa[1]);
tempa[2] = getSBoxValue(tempa[2]);
tempa[3] = getSBoxValue(tempa[3]);
}
tempa[0] = tempa[0] ^ Rcon[i/Nk];
}
#if defined(AES256) && (AES256 == 1)
if (i % Nk == 4)
{
// Function Subword()
{
tempa[0] = getSBoxValue(tempa[0]);
tempa[1] = getSBoxValue(tempa[1]);
tempa[2] = getSBoxValue(tempa[2]);
tempa[3] = getSBoxValue(tempa[3]);
}
}
#endif
j = i * 4; k=(i - Nk) * 4;
RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0];
RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1];
RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2];
RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3];
}
}
void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key)
{
KeyExpansion(ctx->RoundKey, key);
}
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv)
{
KeyExpansion(ctx->RoundKey, key);
memcpy (ctx->Iv, iv, AES_BLOCKLEN);
}
void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv)
{
memcpy (ctx->Iv, iv, AES_BLOCKLEN);
}
#endif
// This function adds the round key to state.
// The round key is added to the state by an XOR function.
static void AddRoundKey(uint8_t round, state_t* state, const uint8_t* RoundKey)
{
uint8_t i,j;
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
{
(*state)[i][j] ^= RoundKey[(round * Nb * 4) + (i * Nb) + j];
}
}
}
// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
static void SubBytes(state_t* state)
{
uint8_t i, j;
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
{
(*state)[j][i] = getSBoxValue((*state)[j][i]);
}
}
}
// The ShiftRows() function shifts the rows in the state to the left.
// Each row is shifted with different offset.
// Offset = Row number. So the first row is not shifted.
static void ShiftRows(state_t* state)
{
uint8_t temp;
// Rotate first row 1 columns to left
temp = (*state)[0][1];
(*state)[0][1] = (*state)[1][1];
(*state)[1][1] = (*state)[2][1];
(*state)[2][1] = (*state)[3][1];
(*state)[3][1] = temp;
// Rotate second row 2 columns to left
temp = (*state)[0][2];
(*state)[0][2] = (*state)[2][2];
(*state)[2][2] = temp;
temp = (*state)[1][2];
(*state)[1][2] = (*state)[3][2];
(*state)[3][2] = temp;
// Rotate third row 3 columns to left
temp = (*state)[0][3];
(*state)[0][3] = (*state)[3][3];
(*state)[3][3] = (*state)[2][3];
(*state)[2][3] = (*state)[1][3];
(*state)[1][3] = temp;
}
static uint8_t xtime(uint8_t x)
{
return ((x<<1) ^ (((x>>7) & 1) * 0x1b));
}
// MixColumns function mixes the columns of the state matrix
static void MixColumns(state_t* state)
{
uint8_t i;
uint8_t Tmp, Tm, t;
for (i = 0; i < 4; ++i)
{
t = (*state)[i][0];
Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ;
Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ;
Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ;
Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ;
Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ;
}
}
// Multiply is used to multiply numbers in the field GF(2^8)
// Note: The last call to xtime() is unneeded, but often ends up generating a smaller binary
// The compiler seems to be able to vectorize the operation better this way.
// See https://github.com/kokke/tiny-AES-c/pull/34
#if MULTIPLY_AS_A_FUNCTION
static uint8_t Multiply(uint8_t x, uint8_t y)
{
return (((y & 1) * x) ^
((y>>1 & 1) * xtime(x)) ^
((y>>2 & 1) * xtime(xtime(x))) ^
((y>>3 & 1) * xtime(xtime(xtime(x)))) ^
((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))); /* this last call to xtime() can be omitted */
}
#else
#define Multiply(x, y) \
( ((y & 1) * x) ^ \
((y>>1 & 1) * xtime(x)) ^ \
((y>>2 & 1) * xtime(xtime(x))) ^ \
((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \
((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \
#endif
#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
// MixColumns function mixes the columns of the state matrix.
// The method used to multiply may be difficult to understand for the inexperienced.
// Please use the references to gain more information.
static void InvMixColumns(state_t* state)
{
int i;
uint8_t a, b, c, d;
for (i = 0; i < 4; ++i)
{
a = (*state)[i][0];
b = (*state)[i][1];
c = (*state)[i][2];
d = (*state)[i][3];
(*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09);
(*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d);
(*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b);
(*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e);
}
}
// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
static void InvSubBytes(state_t* state)
{
uint8_t i, j;
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
{
(*state)[j][i] = getSBoxInvert((*state)[j][i]);
}
}
}
static void InvShiftRows(state_t* state)
{
uint8_t temp;
// Rotate first row 1 columns to right
temp = (*state)[3][1];
(*state)[3][1] = (*state)[2][1];
(*state)[2][1] = (*state)[1][1];
(*state)[1][1] = (*state)[0][1];
(*state)[0][1] = temp;
// Rotate second row 2 columns to right
temp = (*state)[0][2];
(*state)[0][2] = (*state)[2][2];
(*state)[2][2] = temp;
temp = (*state)[1][2];
(*state)[1][2] = (*state)[3][2];
(*state)[3][2] = temp;
// Rotate third row 3 columns to right
temp = (*state)[0][3];
(*state)[0][3] = (*state)[1][3];
(*state)[1][3] = (*state)[2][3];
(*state)[2][3] = (*state)[3][3];
(*state)[3][3] = temp;
}
#endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
// Cipher is the main function that encrypts the PlainText.
static void Cipher(state_t* state, const uint8_t* RoundKey)
{
uint8_t round = 0;
// Add the First round key to the state before starting the rounds.
AddRoundKey(0, state, RoundKey);
// There will be Nr rounds.
// The first Nr-1 rounds are identical.
// These Nr rounds are executed in the loop below.
// Last one without MixColumns()
for (round = 1; ; ++round)
{
SubBytes(state);
ShiftRows(state);
if (round == Nr) {
break;
}
MixColumns(state);
AddRoundKey(round, state, RoundKey);
}
// Add round key to last round
AddRoundKey(Nr, state, RoundKey);
}
#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
static void InvCipher(state_t* state, const uint8_t* RoundKey)
{
uint8_t round = 0;
// Add the First round key to the state before starting the rounds.
AddRoundKey(Nr, state, RoundKey);
// There will be Nr rounds.
// The first Nr-1 rounds are identical.
// These Nr rounds are executed in the loop below.
// Last one without InvMixColumn()
for (round = (Nr - 1); ; --round)
{
InvShiftRows(state);
InvSubBytes(state);
AddRoundKey(round, state, RoundKey);
if (round == 0) {
break;
}
InvMixColumns(state);
}
}
#endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
/*****************************************************************************/
/* Public functions: */
/*****************************************************************************/
#if defined(ECB) && (ECB == 1)
void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf)
{
// The next function call encrypts the PlainText with the Key using AES algorithm.
Cipher((state_t*)buf, ctx->RoundKey);
}
void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf)
{
// The next function call decrypts the PlainText with the Key using AES algorithm.
InvCipher((state_t*)buf, ctx->RoundKey);
}
#endif // #if defined(ECB) && (ECB == 1)
#if defined(CBC) && (CBC == 1)
static void XorWithIv(uint8_t* buf, const uint8_t* Iv)
{
uint8_t i;
for (i = 0; i < AES_BLOCKLEN; ++i) // The block in AES is always 128bit no matter the key size
{
buf[i] ^= Iv[i];
}
}
void AES_CBC_encrypt_buffer(struct AES_ctx *ctx, uint8_t* buf, uint32_t length)
{
uintptr_t i;
uint8_t *Iv = ctx->Iv;
for (i = 0; i < length; i += AES_BLOCKLEN)
{
XorWithIv(buf, Iv);
Cipher((state_t*)buf, ctx->RoundKey);
Iv = buf;
buf += AES_BLOCKLEN;
}
/* store Iv in ctx for next call */
memcpy(ctx->Iv, Iv, AES_BLOCKLEN);
}
void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length)
{
uintptr_t i;
uint8_t storeNextIv[AES_BLOCKLEN];
for (i = 0; i < length; i += AES_BLOCKLEN)
{
memcpy(storeNextIv, buf, AES_BLOCKLEN);
InvCipher((state_t*)buf, ctx->RoundKey);
XorWithIv(buf, ctx->Iv);
memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN);
buf += AES_BLOCKLEN;
}
}
#endif // #if defined(CBC) && (CBC == 1)
#if defined(CTR) && (CTR == 1)
/* Symmetrical operation: same function for encrypting as for decrypting. Note any IV/nonce should never be reused with the same key */
void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length)
{
uint8_t buffer[AES_BLOCKLEN];
unsigned i;
int bi;
for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi)
{
if (bi == AES_BLOCKLEN) /* we need to regen xor compliment in buffer */
{
memcpy(buffer, ctx->Iv, AES_BLOCKLEN);
Cipher((state_t*)buffer,ctx->RoundKey);
/* Increment Iv and handle overflow */
for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi)
{
/* inc will overflow */
if (ctx->Iv[bi] == 255)
{
ctx->Iv[bi] = 0;
continue;
}
ctx->Iv[bi] += 1;
break;
}
bi = 0;
}
buf[i] = (buf[i] ^ buffer[bi]);
}
}
#endif // #if defined(CTR) && (CTR == 1)
+1180
View File
File diff suppressed because it is too large Load Diff
+862
View File
@@ -0,0 +1,862 @@
#include "firmware.h"
static uint8_t _fw_start_write_flag; /* 固件开始写入的标志位 */
static uint16_t _update_progress; /* 固件更新的进度, 10000 制 */
static uint16_t _update_progress_step_num; /* 固件更新进度的步进单位 */
static uint16_t _storage_data_size; /* 固件包写入时记录暂存的固件分包大小,单位 byte */
static uint32_t _write_part_addr; /* 固件包写入时记录写入 flash 的相对地址 */
static uint16_t _write_last_pkg_size; /* 固件包写入时最后一个分包的大小,单位 byte */
static uint8_t _fw_first_bytes[CONFIG_WRITE_BYTES_LEASET]; /* 固件包的前几个字节 */
static uint8_t _upk_min_handle_buff[UPK_LEAST_HANDLE_BYTE]; /* upk 固件最小处理单位的缓存区,多次使用以降低系统资源开销 */
static struct upk_head_t upkHdr; /* 用于存放 upk 固件包头 */
#if (CONFIG_DECRYPT)
static struct AES_ctx aesCtx; /* AES 对象 */
#endif
static struct BSP_FLASH _flash_app_part; /* APP 分区 */
#if (CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION)
static struct BSP_FLASH _flash_download_part; /* download 分区 */
#if (CONFIG_CHIP_PARTS == USE_TRIPLE_PARTITION)
static struct BSP_FLASH _flash_factory_part; /* factory 分区 */
#endif
#endif
/* Extern function prototypes ------------------------------------------------*/
extern void Firmware_OperateCallback(uint16_t progress);
/* Private function prototypes -----------------------------------------------*/
static eErrCode _Write_FirmwareSubPackage( const struct BSP_FLASH *part,
uint8_t *data,
uint16_t pkg_size,
uint8_t decrypt,
FM_FIRMWARE_WRITE_DIR write_dir);
static void _Reset_Write(void);
/* Exported functions ---------------------------------------------------------*/
/**
* @brief 初始化接口
* @note
* @retval None
*/
void FM_Init (void)
{
BSP_Flash_Init(&_flash_app_part, NAME_PART_APPLICATION, BASE_APPLICATION, SIZE_PART_APPLICATION);
#if (CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION)
BSP_Flash_Init(&_flash_download_part, NAME_PART_DOWNLOAD, BASE_DOWNLOAD, SIZE_PART_DOWNLOAD);
#if (CONFIG_CHIP_PARTS > USE_DOUBLE_PARTITION)
BSP_Flash_Init(&_flash_factory_part, NAME_PART_FACTORY, BASE_FACTORY, SIZE_PART_FACTORY);
#endif
#endif
printf("onchip size : 0x%lX\r\n", SIZE_ONCHIP_FLASH);
printf("0x%08lX+0x%lX 'parameters'.\r\n", BASE_PARAMETERS, SIZE_PART_PARAMETERS);
printf("0x%08X+0x%X 'app'.\r\n", _flash_app_part.addr, _flash_app_part.len);
#if (CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION)
printf("0x%08X+0x%X 'download'.\r\n", _flash_download_part.addr, _flash_app_part.len);
#if (CONFIG_CHIP_PARTS > USE_DOUBLE_PARTITION)
printf("0x%08X+0x%X 'factory'.\r\n", _flash_factory_part.addr, _flash_app_part.len);
#endif
#endif
#if (CONFIG_DECRYPT)
AES_init_ctx_iv(&aesCtx, (uint8_t *)AES256_KEY, (uint8_t *)AES256_IV);
#endif
}
/**
* @brief 固件包是否有加密
* @note 调用前需确保 upkHdr 已经读入了数据
* @retval 0: 未加密。1: 有加密
*/
inline uint8_t FM_IsEncrypt(void)
{
/* 读取加密选项 */
if (upkHdr.config[1] == 0x01)
return 1;
return 0;
}
/**
* @brief 检测某个分区是否为空
* @note ERR_OK: 分区数据空
* @param[in] part_name: 分区名
* @retval eErrCode
*/
eErrCode FM_IsEmpty(const char *part_name)
{
int read_len = 0;
uint16_t i = 0;
uint16_t need_read_size = UPK_LEAST_HANDLE_BYTE;
uint32_t *p_data = (uint32_t *)_upk_min_handle_buff;
uint32_t read_posit = 0;
ASSERT(part_name != NULL);
const struct BSP_FLASH *part = NULL;
part = BSP_Flash_GetHandle(part_name);
if (part == NULL) {
printf("%s: '%s' not found.\r\n", __func__, part_name);
return ERR_NO_THIS_PART;
}
for (read_posit = 0; read_posit < part->len; ) {
if ((part->len - read_posit) < UPK_LEAST_HANDLE_BYTE) {
need_read_size = part->len - read_posit;
}
read_len = BSP_Flash_Read(part, read_posit, _upk_min_handle_buff, need_read_size);
if (read_len < 0) {
printf("%s: read error (%d).\r\n", __func__, __LINE__);
return ERR_READ_IS_EMPTY_ERR;
}
for (i = 0; i < (UPK_LEAST_HANDLE_BYTE / sizeof(p_data)); i++) {
if (p_data[i] != 0xFFFFFFFF) {
printf("part '%s' not empty.\r\n", part_name);
return ERR_FLASH_NO_EMPTY;
}
}
read_posit += read_len;
}
//printf("%s: '%s' part empty.\r\n", __func__, part_name);
return ERR_OK;
}
/**
* @brief 获取固件包的固件版本
* @note 调用前需确保 upkHdr 已经读入了数据
* @retval 固件新版本
*/
inline char * FM_GetNewFirmwareVersion(void)
{
return upkHdr.fw_new_ver;
}
/**
* @brief 获取源固件的 CRC32 值
* @note 调用前需确保 upkHdr 已经读入了数据
* @retval 源固件的 CRC32 值
*/
inline uint32_t FM_GetRawCRC32(void)
{
return upkHdr.raw_crc;
}
/**
* @brief 暂存固件包头
* @note 会同时校验固件包头
* @param[in] part_name: 分区名
* @param[in] data: 数据
* @retval eErrCode
*/
eErrCode FM_StorageFirmwareHead(const char *part_name, uint8_t *data)
{
uint32_t head_crc = 0xFFFFFFFF;
uint8_t *pHdr = (uint8_t *)&upkHdr;
ASSERT(part_name != NULL);
ASSERT(data != NULL);
_Reset_Write();
memcpy(pHdr, data, UPK_HEAD_SIZE);
#if (!CONFIG_DECRYPT)
/* 若固件包加密,检查是否有解密组件 */
if (FM_IsEncrypt()) {
printf("%s: no decrypt component\r\n", __func__);
return ERR_NO_DECRYPT_COMPONENT;
}
#endif
const struct BSP_FLASH *part = NULL;
part = BSP_Flash_GetHandle(part_name);
if (part == NULL) {
printf("%s: not found.\r\n", __func__);
return ERR_NO_THIS_PART;
}
//printf("%s: '%s' part.\r\n", __func__, part_name);
if (strncmp(upkHdr.name, "upk", sizeof("upk")) != 0) {
return ERR_FAULT_FIRMWARE;
}
if ((upkHdr.pkg_size > part->len)
|| (upkHdr.raw_size > part->len)) {
return ERR_FIRMWARE_OVERSIZE;
}
head_crc = crc32_step(head_crc, pHdr, UPK_HEAD_SIZE - 4);
if (head_crc != upkHdr.head_crc) {
printf("%s: head crc verify failed. (%.8X - %.8X)\r\n", __func__, upkHdr.head_crc, head_crc);
return ERR_FIRMWARE_HEAD_VERIFY_ERR;
}
printf("\n\r--------------------\n\r");
printf("head: \t\t%s\n\r", upkHdr.name);
printf("config: \t%d %d %d %d\n\r", upkHdr.config[0], upkHdr.config[1], upkHdr.config[2], upkHdr.config[3]);
printf("old_ver: \t%d.%d.%d.%d\n\r", upkHdr.fw_old_ver[0], upkHdr.fw_old_ver[1], upkHdr.fw_old_ver[2], upkHdr.fw_old_ver[3]);
printf("new_ver: \t%d.%d.%d.%d\n\r", upkHdr.fw_new_ver[0], upkHdr.fw_new_ver[1], upkHdr.fw_new_ver[2], upkHdr.fw_new_ver[3]);
printf("string: \t%s\n\r",upkHdr.user_string);
printf("partition: \t%s\n\r", upkHdr.part_name);
printf("raw_size: \t%d\n\r", upkHdr.raw_size);
printf("pkg_size: \t%d\n\r", upkHdr.pkg_size);
printf("timestamp: \t%d\n\r", upkHdr.timestamp);
printf("raw_crc: \t%.8X\n\r", upkHdr.raw_crc);
printf("pkg_crc: \t%.8X\n\r", upkHdr.pkg_crc);
printf("head_crc: \t%.8X\n\r", upkHdr.head_crc);
printf("--------------------\n\r");
/* 计算固件更新进度的最小单位,降低过程计算量,无更新进度需求可删除 */
_update_progress_step_num = upkHdr.pkg_size / UPK_LEAST_HANDLE_BYTE;
_update_progress_step_num += upkHdr.pkg_size % UPK_LEAST_HANDLE_BYTE;
_update_progress_step_num = 10000 / _update_progress_step_num;
//printf("%s: progress unit: %d\r\n", __func__, _update_progress_step_num);
return ERR_OK;
}
/**
* @brief 校验已放置在分区的固件包的包体数据的正确性
* @note 一般要先校验包头,注意各分区包体的偏移地址有区别
* @param[in] part_name: 分区名称
* @param[in] crc32: 需进行比对的 CRC32 校验值
* @param[in] is_auto_fill: 是否自动填充固件的首地址数据
* @retval eErrCode
*/
eErrCode FM_VerifyFirmware (const char *part_name, uint32_t crc32, uint8_t is_auto_fill)
{
int read_len = 0;
uint8_t app_part_flag = 0;
uint32_t pkg_size = 0;
uint32_t body_crc = 0xFFFFFFFF;
uint32_t read_posit = 0;
uint32_t read_posit_temp = 0;
uint16_t need_read_size = UPK_LEAST_HANDLE_BYTE;
#if (CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION)
uint8_t first_flag = 0;
#endif
ASSERT(part_name != NULL);
#if (!CONFIG_DECRYPT)
/* 若固件包加密,检查是否有解密组件 */
if (FM_IsEncrypt()) {
printf("%s: no decrypt component\r\n", __func__);
return ERR_NO_DECRYPT_COMPONENT;
}
#endif
if (strncmp(part_name, NAME_PART_APPLICATION, MAX_NAME_LEN) == 0) {
app_part_flag = 1;
}
const struct BSP_FLASH *part = NULL;
part = BSP_Flash_GetHandle(part_name);
if (part == NULL) {
printf("%s: not found.\r\n", part_name);
return ERR_NO_THIS_PART;
}
hex_printf((uint8_t *)&upkHdr, UPK_HEAD_SIZE);
printf("--------------------\n\r");
printf("head: \t\t%s\n\r", upkHdr.name);
printf("config: \t%d %d %d %d\n\r", upkHdr.config[0], upkHdr.config[1], upkHdr.config[2], upkHdr.config[3]);
printf("old_ver: \t%d.%d.%d.%d\n\r", upkHdr.fw_old_ver[0], upkHdr.fw_old_ver[1], upkHdr.fw_old_ver[2], upkHdr.fw_old_ver[3]);
printf("new_ver: \t%d.%d.%d.%d\n\r", upkHdr.fw_new_ver[0], upkHdr.fw_new_ver[1], upkHdr.fw_new_ver[2], upkHdr.fw_new_ver[3]);
printf("string: \t%s\n\r",upkHdr.user_string);
printf("partition: \t%s\n\r", upkHdr.part_name);
printf("raw_size: \t%d\n\r", upkHdr.raw_size);
printf("pkg_size: \t%d\n\r", upkHdr.pkg_size);
printf("timestamp: \t%d\n\r", upkHdr.timestamp);
printf("raw_crc: \t%.8X\n\r", upkHdr.raw_crc);
printf("pkg_crc: \t%.8X\n\r", upkHdr.pkg_crc);
printf("head_crc: \t%.8X\n\r", upkHdr.head_crc);
printf("--------------------\n\r");
if (app_part_flag) {
pkg_size = upkHdr.raw_size;
} else {
pkg_size = upkHdr.pkg_size;
}
/* 校验固件包体的数据正确性 */
for (; read_posit < pkg_size; ) {
/* 剩余的数据数小于最小处理单位时,按剩余字节数处理 */
if ((pkg_size - read_posit) < UPK_LEAST_HANDLE_BYTE) {
need_read_size = pkg_size - read_posit;
}
/* 非 APP 分区,需要偏移包头的地址才是包体 */
if (app_part_flag) {
read_posit_temp = read_posit;
} else {
read_posit_temp = read_posit + UPK_HEAD_SIZE;
}
read_len = BSP_Flash_Read(part, read_posit_temp, _upk_min_handle_buff, need_read_size);
if (read_len < 0) {
printf("%s: read error (%d).\r\n", __func__, __LINE__);
return ERR_VERIFY_READ_ERR;
}
#if (CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION)
if (is_auto_fill) {
if (first_flag == 0) {
first_flag = 1;
for (uint8_t i = 0; i < CONFIG_WRITE_BYTES_LEASET; i++) {
_upk_min_handle_buff[i] = _fw_first_bytes[i];
}
}
}
#endif
body_crc = crc32_step(body_crc, _upk_min_handle_buff, read_len);
read_posit += read_len;
}
if (body_crc != crc32) {
printf("%s: '%s' body crc verify failed. (%08X vs %08X)\r\n", __func__, part_name, crc32, body_crc);
if (app_part_flag) {
return ERR_RAW_BODY_VERIFY_ERR;
} else {
return ERR_PKG_BODY_VERIFY_ERR;
}
}
return ERR_OK;
}
/**
* @brief 擦除某个分区的固件
* @note
* @param[in] part_name: 分区名称
* @retval eErrCode
*/
eErrCode FM_EraseFirmware(const char *part_name)
{
ASSERT(part_name != NULL);
const struct BSP_FLASH *part = NULL;
part = BSP_Flash_GetHandle(part_name);
if (part == NULL)
{
printf("%s: not found %s part.\r\n", __func__, part_name);
return ERR_NO_THIS_PART;
}
if (BSP_Flash_Erase(part, 0, part->len) < 0)
{
printf("%s: %s part erase failed.\r\n", __func__, part_name);
return ERR_ERASE_PART_ERR;
}
return ERR_OK;
}
/**
* @brief 固件写入分区的最终阶段,将分区首地址的几个字节数据写入 flash
* @note 程序调用 _Write_FirmwareSubPackage 函数时已暂存进 _fw_first_bytes
* @param[in] part_name: 分区名称
* @retval eErrCode
*/
eErrCode FM_WriteFirmwareDone (const char *part_name)
{
ASSERT(part_name != NULL);
const struct BSP_FLASH *part = NULL;
part = BSP_Flash_GetHandle(part_name);
if (part == NULL) {
printf("%s: not found part.\r\n", __func__);
return ERR_NO_THIS_PART;
}
if (BSP_Flash_Write(part, 0, _fw_first_bytes, CONFIG_WRITE_BYTES_LEASET) < 0) {
printf("%s: write error (%d).\r\n", __func__, __LINE__);
return ERR_WRITE_FIRST_ADDR_ERR;
}
_Reset_Write();
Firmware_OperateCallback(10000);
return ERR_OK;
}
/**
* @brief 将固件分包按顺序写入分区
* @note 由于固件包头已经写入,这里写入的是固件包体,需要注意在 flash 的偏移位置
* @param[in] part_name: 分区名称
* @param[in] data: 数据包
* @param[in] pkg_size: 数据包大小,单位 byte
* @retval eErrCode
*/
eErrCode FM_WriteFirmwareSubPackage(const char *part_name, uint8_t *data, uint16_t pkg_size)
{
ASSERT(part_name != NULL);
ASSERT(data != NULL);
ASSERT(pkg_size != 0);
const struct BSP_FLASH *part = NULL;
part = BSP_Flash_GetHandle(part_name);
if (part == NULL)
{
printf("%s: not found %s part.\r\n", __func__, part_name);
return ERR_NO_THIS_PART;
}
printf(",");
#if (CONFIG_CHIP_PARTS == USE_SINGLE_PARTITION)
uint8_t decrypt = 0;
/* 读取加密选项 */
decrypt = FM_IsEncrypt();
return _Write_FirmwareSubPackage(part, data, pkg_size, decrypt, FM_DIR_HOST_TO_APP); /* 写入前解密 */
#else
return _Write_FirmwareSubPackage(part, data, pkg_size, 0, FM_DIR_HOST_TO_DOWNLOAD); /* 写入前不解密 */
#endif
}
/**
* @brief 检查固件的完整性
* @note 通过首地址数据最后写入的机制,判断首地址 4 个字节是否有正确的数据
* @param[in] addr: 分区首地址
* @retval eErrCode
*/
eErrCode FM_CheckFirmwareIntegrity(uint32_t addr)
{
uint32_t value = *(volatile uint32_t *)addr;
eErrCode fw_integrity = ERR_JUMP_TO_APP_ERR;
printf("\r\nvalue = 0x%08X @ offset 0x%.8X", value, addr);
if (BASE_APPLICATION == addr) {
fw_integrity = ((value & 0x2FF00000) == 0x20000000) ? ERR_OK : ERR_JUMP_TO_APP_ERR;
}
#if (CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION)
else if ((BASE_DOWNLOAD == addr)||(BASE_FACTORY == addr)) {
if (UPK_IDENTIFIER == value) {
fw_integrity = ERR_OK;
}
}
#endif
return fw_integrity;
}
#if (CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION)
/**
* @brief 判断是否要进行固件自动更新
* @note 调用前需确保 upkHdr 已经读入了数据
* @retval 0: 无须更新。1: 需自动更新
*/
uint8_t FM_IsNeedAutoUpdate(void)
{
#if (CONFIG_AUTO_UPDATE_MODE == MODE_APPEND_TO_APP)
const struct BSP_FLASH *part = NULL;
part = BSP_Flash_GetHandle(NAME_PART_APPLICATION);
if (part == NULL) {
printf("%s: not found app part.\r\n", __func__);
return ERR_NO_THIS_PART;
}
if (BSP_Flash_Read(part, (SIZE_PART_APPLICATION - UPK_VERSION_SIZE), (uint8_t *)&upkHdr.fw_old_ver[0], UPK_VERSION_SIZE) < 0)
{
printf("%s: read error.\r\n", __func__);
return ERR_READ_VER_ERR;
}
#endif
printf("fw old ver: V%d.%d.%d.%d\r\n", upkHdr.fw_old_ver[0], upkHdr.fw_old_ver[1], upkHdr.fw_old_ver[2], upkHdr.fw_old_ver[3]);
printf("fw new ver: V%d.%d.%d.%d\r\n", upkHdr.fw_new_ver[0], upkHdr.fw_new_ver[1], upkHdr.fw_new_ver[2], upkHdr.fw_new_ver[3]);
if (upkHdr.fw_old_ver[0] != upkHdr.fw_new_ver[0]
|| upkHdr.fw_old_ver[1] != upkHdr.fw_new_ver[1]
|| upkHdr.fw_old_ver[2] != upkHdr.fw_new_ver[2]
|| upkHdr.fw_old_ver[3] != upkHdr.fw_new_ver[3]) {
printf("Need to update.\r\n");
return 1;
}
return 0;
}
/**
* @brief 获取当前操作的固件包的分区名称
* @note 调用前需确保 upkHdr 已经读入了数据
* @retval 分区名称
*/
inline char * FM_GetPartName(void)
{
return upkHdr.part_name;
}
/**
* @brief 获取旧的固件版本,即 APP 分区正在运行的固件版本
* @note 调用前需确保 upkHdr 已经读入了数据
* @retval 固件旧版本
*/
inline char * FM_GetOldFirmwareVersion(void)
{
return upkHdr.fw_old_ver;
}
/**
* @brief 获取打包后固件的 CRC32 值
* @note 调用前需确保 upkHdr 已经读入了数据
* @retval 打包后固件的CRC32值
*/
inline uint32_t FM_GetPackageCRC32(void)
{
return upkHdr.pkg_crc;
}
/**
* @brief 将分区内的固件包头读出
* @note 读出后的数据将放在 upkHdr 中
* @param[in] part_name: 分区名称
* @retval eErrCode
*/
eErrCode FM_ReadFirmwareHead(const char *part_name)
{
ASSERT(part_name != NULL);
_Reset_Write();
const struct BSP_FLASH *part = NULL;
part = BSP_Flash_GetHandle(part_name);
if (part == NULL)
{
printf("%s: not found.\r\n", __func__);
return ERR_NO_THIS_PART;
}
if (BSP_Flash_Read(part, 0, (uint8_t *)&upkHdr, UPK_HEAD_SIZE) < 0)
{
printf("%s: read error.\r\n", __func__);
return ERR_READ_FIRMWARE_HEAD_ERR;
}
return ERR_OK;
}
/**
* @brief 从某个分区将固件包更新至 APP 分区
* @note 读取 -> 解密 -> 写入
* @param[in] from_part_name: 放置需要更新至 APP 分区的固件包的分区
* @retval eErrCode
*/
eErrCode FM_UpdateToAPP(const char *from_part_name)
{
int read_len = 0;
uint8_t decrypt = 0;
uint32_t read_posit = 0;
uint32_t write_posit = 0;
uint32_t need_read_size = UPK_LEAST_HANDLE_BYTE;
eErrCode result = ERR_OK;
ASSERT(from_part_name != NULL);
const struct BSP_FLASH *app_part = NULL;
const struct BSP_FLASH *firmware_part = NULL;
app_part = BSP_Flash_GetHandle(NAME_PART_APPLICATION);
if (app_part == NULL) {
printf("%s: not found.\r\n", __func__);
return ERR_NO_THIS_PART;
}
firmware_part = BSP_Flash_GetHandle(from_part_name);
if (firmware_part == NULL) {
printf("%s: not found %s part.\r\n", __func__, from_part_name);
return ERR_NO_THIS_PART;
}
_Reset_Write();
printf("part '%s' write to 'app'.\r\n", from_part_name);
/* 读取加密选项 */
decrypt = FM_IsEncrypt();
for (write_posit = 0; write_posit < upkHdr.pkg_size; ) {
if ((upkHdr.pkg_size - read_posit) < UPK_LEAST_HANDLE_BYTE) {
need_read_size = upkHdr.pkg_size - read_posit;
}
read_len = BSP_Flash_Read(firmware_part, (read_posit + UPK_HEAD_SIZE), _upk_min_handle_buff, need_read_size);
if (read_len < 0) {
printf("%s: read error (%d).\r\n", __func__, __LINE__);
return ERR_UPDATE_READ_ERR;
}
result = _Write_FirmwareSubPackage(app_part, _upk_min_handle_buff, read_len, decrypt, FM_DIR_DOWNLOAD_TO_APP);
if (result) {
printf("%s: write error (%d).\r\n", __func__, __LINE__);
return result;
}
read_posit += read_len;
write_posit += read_len;
}
return ERR_OK;
}
#if (CONFIG_AUTO_UPDATE_MODE == MODE_UPDATE_DOWNLOAD_HEAD)
/**
* @brief 更新固件包中的版本信息
* @note
* @param[in] part_name: 分区名称
* @retval eErrCode
*/
eErrCode FM_UpdateFirmwareVersion(const char *part_name)
{
ASSERT(part_name != NULL);
#if (ONCHIP_FLASH_ERASE_GRANULARITY > UPK_LEAST_HANDLE_BYTE)
#error "erase granularity oversize than _upk_min_handle_buff array"
#endif
/* 将 download 分区首地址的数据读出,长度为片内 flash 最小擦除粒度 */
const struct BSP_FLASH *part = NULL;
part = BSP_Flash_GetHandle(part_name);
if (part == NULL)
{
printf("%s: not found.\r\n", __func__);
return ERR_NO_THIS_PART;
}
printf("%s: part name: %s\r\n", __func__, part_name);
if (BSP_Flash_Read(part, 0, &_upk_min_handle_buff[0], ONCHIP_FLASH_ERASE_GRANULARITY) < 0)
{
printf("%s: read error.\r\n", __func__);
return ERR_UPDATE_VER_READ_ERR;
}
/* 修改固件包头中旧版本字段的版本信息为新的固件版本 */
struct upk_head_t *p_pkg_head = (struct upk_head_t *)&_upk_min_handle_buff[0];
p_pkg_head->fw_old_ver[0] = p_pkg_head->fw_new_ver[0];
p_pkg_head->fw_old_ver[1] = p_pkg_head->fw_new_ver[1];
p_pkg_head->fw_old_ver[2] = p_pkg_head->fw_new_ver[2];
p_pkg_head->fw_old_ver[3] = p_pkg_head->fw_new_ver[3];
/* 将读出数据的区域擦除 */
if (BSP_Flash_Erase(part, 0, ONCHIP_FLASH_ERASE_GRANULARITY) < 0)
{
printf("%s: %s part erase failed.\r\n", __func__, part_name);
return ERR_UPDATE_VER_ERASE_ERR;
}
/* 将新的数据写入擦除的区域 */
if (BSP_Flash_Write(part, 0, &_upk_min_handle_buff[0], ONCHIP_FLASH_ERASE_GRANULARITY) < 0)
{
printf("%s: write error (%d).\r\n", __func__, __LINE__);
return ERR_UPDATE_VER_WRITE_ERR;
}
memcpy((uint8_t *)&upkHdr, &_upk_min_handle_buff[0], UPK_HEAD_SIZE);
printf("fw old ver: V%d.%d.%d.%d\r\n", p_pkg_head->fw_old_ver[0], p_pkg_head->fw_old_ver[1], p_pkg_head->fw_old_ver[2], p_pkg_head->fw_old_ver[3]);
printf("fw new ver: V%d.%d.%d.%d\r\n", p_pkg_head->fw_new_ver[0], p_pkg_head->fw_new_ver[1], p_pkg_head->fw_new_ver[2], p_pkg_head->fw_new_ver[3]);
return ERR_OK;
}
#elif (CONFIG_AUTO_UPDATE_MODE == MODE_APPEND_TO_APP)
/**
* @brief 更新固件包中的版本信息
* @note
* @param[in] part_name: 分区名称
* @retval eErrCode
*/
eErrCode FM_UpdateFirmwareVersion(const char *part_name)
{
const struct BSP_FLASH *part = NULL;
part = BSP_Flash_GetHandle(NAME_PART_APPLICATION);
if (part == NULL)
{
printf("%s: not found APP part.\r\n", __func__);
return ERR_NO_THIS_PART;
}
if (BSP_Flash_Read(part, (SIZE_PART_APPLICATION - UPK_VERSION_SIZE), (uint8_t *)&upkHdr.fw_old_ver[0], UPK_VERSION_SIZE) < 0)
{
printf("%s: read error.\r\n", __func__);
return ERR_READ_VER_ERR;
}
if (upkHdr.fw_old_ver[0] != 0xFF
|| upkHdr.fw_old_ver[1] != 0xFF
|| upkHdr.fw_old_ver[2] != 0xFF
|| upkHdr.fw_old_ver[3] != 0xFF)
{
printf("%s: version area no erase.\r\n", __func__);
return ERR_VER_AREA_NO_ERASE;
}
if (BSP_Flash_Write(part, (SIZE_PART_APPLICATION - UPK_VERSION_SIZE), (uint8_t *)&upkHdr.fw_new_ver[0], UPK_VERSION_SIZE) < 0)
{
printf("%s: write error.\r\n", __func__);
return ERR_WRITE_VER_ERR;
}
return ERR_OK;
}
#endif /* #if (CONFIG_AUTO_UPDATE_MODE == MODE_UPDATE_DOWNLOAD_HEAD) */
#endif /* #if (CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION) */
/* Private functions ---------------------------------------------------------*/
/**
* @brief 复位写固件的一些记录信息
* @note
* @retval None
*/
static void _Reset_Write(void)
{
_fw_start_write_flag = 0; /* 固件开始写入的标志位 */
_update_progress = 0; /* 固件更新的进度, 10000 制 */
_storage_data_size = 0; /* 固件包写入时记录暂存的固件分包大小,单位 byte */
_write_part_addr = 0; /* 固件包写入时记录写入 flash 的相对地址 */
_write_last_pkg_size = 0; /* 固件包写入时最后一个分包的大小,单位 byte */
}
uint32_t wcrc32 = 0xFFFFFFFF;
uint32_t wlen = 0;
/**
* @brief 将固件分包按顺序写入某个分区
* @note 循环调用本函数,无须指定写入地址,函数内部自行记录已写入的大小
* @param[in] part: 分区对象
* @param[in] data: 数据
* @param[in] pkg_size: 数据大小,单位 byte
* @param[in] decrypt: 0: 固件包无加密。1: 固件包有加密
* @retval eErrCode
*/
static eErrCode _Write_FirmwareSubPackage( const struct BSP_FLASH *part,
uint8_t *data,
uint16_t pkg_size,
uint8_t decrypt,
FM_FIRMWARE_WRITE_DIR write_dir)
{
uint8_t *fw_4096byte_buff = data;
/* 主机直接下发的固件分包不满 UPK_LEAST_HANDLE_BYTE 个字节,需要先暂存至满足后再写入 */
if (write_dir == FM_DIR_HOST_TO_APP) {
fw_4096byte_buff = &_upk_min_handle_buff[0];
/* 判断是否是最后一个包 */
if (_storage_data_size == 0) {
if (upkHdr.pkg_size - _write_part_addr < UPK_LEAST_HANDLE_BYTE)
{
/* 最后一个固件分包的标志 */
_write_last_pkg_size = upkHdr.pkg_size - _write_part_addr;
printf("_write_last_pkg_size : %d\r\n", _write_last_pkg_size);
}
}
/* 小于最小处理单位时,暂存 */
if (_storage_data_size < UPK_LEAST_HANDLE_BYTE) {
memcpy(&fw_4096byte_buff[_storage_data_size], data, pkg_size);
_storage_data_size += pkg_size;
if (_write_last_pkg_size) {
if (_storage_data_size < _write_last_pkg_size) {
return ERR_OK;
}
} else if (_storage_data_size < UPK_LEAST_HANDLE_BYTE) {
return ERR_OK;
}
}
}
/* 从 download 或 factory 更新至 APP ,因可以直接读取 UPK_LEAST_HANDLE_BYTE 个字节,所以无须暂存 */
else {
if (_fw_start_write_flag == 0) {
wlen = upkHdr.pkg_size;
_storage_data_size = pkg_size;
} else {
if (wlen >= pkg_size) {
wlen -= pkg_size;
_storage_data_size = pkg_size;
} else {
_storage_data_size = wlen;
}
}
}
#if (CONFIG_DECRYPT)
if (decrypt) {
AES_CBC_decrypt_buffer(&aesCtx, fw_4096byte_buff, _storage_data_size);
}
#endif
/* 保存首地址的几个字节数据,等待最后写入 */
if (_fw_start_write_flag == 0) {
for (uint8_t i = 0; i < CONFIG_WRITE_BYTES_LEASET; i++) {
_fw_first_bytes[i] = fw_4096byte_buff[i];
}
fw_4096byte_buff += CONFIG_WRITE_BYTES_LEASET;
_storage_data_size -= CONFIG_WRITE_BYTES_LEASET;
_write_part_addr = CONFIG_WRITE_BYTES_LEASET;
}
if (BSP_Flash_Write(part, _write_part_addr, fw_4096byte_buff, _storage_data_size) < 0) {
printf("%s: write error (%d) 0x%08X + 0x%08X, len %d.\r\n", __func__, __LINE__,
part->addr,_write_part_addr, _storage_data_size);
_Reset_Write();
return ERR_WRITE_PART_ERR;
}
if (_storage_data_size!=92) {
wcrc32 = crc32_step(wcrc32, fw_4096byte_buff, _storage_data_size);
}
_write_part_addr += _storage_data_size;
_storage_data_size = 0;
_fw_start_write_flag = 1;
_update_progress += _update_progress_step_num;
Firmware_OperateCallback(_update_progress);
return ERR_OK;
}
+47
View File
@@ -0,0 +1,47 @@
/**
* 此文件用于关闭 semihosting
*/
#include "common.h"
/* 告诉编译器若没有使用 MicroLIB ,则 main() 函数不需要入口参数 */
#if __IS_COMPILER_ARM_COMPILER_6__
#ifndef __MICROLIB
__asm(".global __ARM_use_no_argv\n\t");
#endif
#endif
/* 关闭 semihosting */
#if __IS_COMPILER_ARM_COMPILER_6__
__asm(".global __use_no_semihosting");
/* AC6 会因为关闭 semihosting 缺这个函数,所以要补上 */
void _sys_exit(int ret)
{
(void)ret;
while(1) {}
}
#elif __IS_COMPILER_ARM_COMPILER_5__
#pragma import(__use_no_semihosting)
#endif
/* AC5 和 AC6 都会因为关闭 semihosting 缺这个函数,所以要补上 */
#if __IS_COMPILER_ARM_COMPILER__
void _ttywrch(int ch)
{
(void)ch;
}
#endif
/* 当使用 AC6 开启 MicroLIB 时,若有使用 assert() 的需求,需要自己实现 __aeabi_assert() */
#if __IS_COMPILER_ARM_COMPILER_6__ && defined(__MICROLIB)
void __aeabi_assert(const char *chCond, const char *chLine, int wErrCode)
{
(void)chCond;
(void)chLine;
(void)wErrCode;
while(1) {
__NOP();
}
}
#endif
+100
View File
@@ -0,0 +1,100 @@
#include "transfer.h"
#if (DT_ENABLE_BROKEN_FRAME_DETECT)
static uint8_t timeo_frame = 0;
static struct drv_timer_t timerFrameBroken;
static void timerFrameBrokenCallback (void *user_data)
{
timeo_frame = 1;
//printf("frame detect clock time up!\r\n");
}
#endif
static uint8_t DT_Port_IsRecvData (struct transfer_t *xfer)
{
#if (DT_ENABLE_BROKEN_FRAME_DETECT)
if (timeo_frame) {
timeo_frame = 0;
return BSP_UART_ERR_OK;
} else if (BSP_UART_IsFrameEnd((BSP_UART_ID)xfer->if_id) == BSP_UART_ERR_OK) {
drv_timer_linkUserData(&timerFrameBroken, xfer);
drv_timer_restart(&timerFrameBroken);
return BSP_UART_ERR_NO_RECV_FRAME;
}
return BSP_UART_ERR_NO_RECV_FRAME;
#else
return BSP_UART_IsFrameEnd((BSP_UART_ID)xfer->if_id);
#endif
}
void DT_Send (struct transfer_t *xfer, uint8_t *data, uint32_t len)
{
BSP_UART_Send((BSP_UART_ID)xfer->if_id, data, len, 0xFFFF);
}
/**
* @brief 检测是否接收到一帧数据的轮询接口
* @note
* @param[in] xfer: 传输控制块对象
* @retval exRESULT
*/
exRESULT DT_PollingReceive (struct transfer_t *xfer)
{
exRESULT state = X_RESULT_NO_DATA;
if (DT_Port_IsRecvData(xfer) == 0) {
state = X_RESULT_RECV_FRAME;
}
return state;
}
/**
* @brief 数据传输层初始化
* @note
* @param[in] xfer: 传输控制块对象
* @param[in] if_id: 传输接口 ID
* @param[in] buff: 用于接收数据的缓冲池,单位 byte
* @param[in] len: 指示接收到的数据长度,单位 byte
* @param[in] buff_size: 数据池最大容量,单位 byte
* @retval None
*/
void DT_Init (struct transfer_t *xfer, uint8_t if_id, uint8_t *buff, uint16_t *len, uint32_t buff_size)
{
ASSERT(xfer != NULL);
xfer->if_id = if_id;
xfer->rx_buff = buff;
xfer->rx_len = len;
xfer->rx_buff_size = buff_size;
BSP_UART_Init((BSP_UART_ID)xfer->if_id);
BSP_UART_LinkUserData((BSP_UART_ID)xfer->if_id, xfer);
BSP_UART_EnableReceive( (BSP_UART_ID)xfer->if_id,
xfer->rx_buff,
xfer->rx_len,
xfer->rx_buff_size);
#if (DT_ENABLE_BROKEN_FRAME_DETECT)
drv_timer_init(&timerFrameBroken,
timerFrameBrokenCallback,
BROKEN_FRAME_INTERVAL_TIME,
TIMER_RUN_ONE_SHOT);
#endif
}
+104
View File
@@ -0,0 +1,104 @@
/* Includes ------------------------------------------------------------------*/
#include "utils.h"
#include "bsp_common.h"
const char Hex2Ascii[17] = "0123456789ABCDEF";
int hex_printf (const uint8_t *buff, int count)
{
uint32_t i = 0, j = 0;
char str_val[75] = {0};
uint32_t index = 0;
uint32_t str_index = 0;
uint32_t cnt = (count+15)>>4;
if (count < 0) {
return -1;
}
if (cnt > 16) {
cnt = 16;
//BSP_printf("!!! TOO LONG. ONLY SHOW HEAD 256 bytes !!!\n");
}
for (i = 0; i < cnt; i++) {
index = 0;
str_index = 0;
for (j = 0; j < 16; j++) {
if (j + (i << 4) < count) {
str_val[index++] = Hex2Ascii[(buff[j + (i << 4)] & 0xF0) >> 4];
str_val[index++] = Hex2Ascii[buff[j + (i << 4)] & 0xF];
str_val[index++] = ' ';
} else {
str_val[index++] = ' ';
str_val[index++] = ' ';
str_val[index++] = ' ';
}
}
index += str_index;
str_val[index++] = '\0';
str_val[index++] = '\0';
printf("%s\r\n", str_val);
}
return 0;
}
/******************************************************************************
* Name: CRC-16/XMODEM x16+x12+x5+1
* Poly: 0x1021
* Init: 0x0000
* Refin: False
* Refout: False
* Xorout: 0x0000
* Alias: CRC-16/ZMODEM,CRC-16/ACORN
*****************************************************************************/
uint16_t crc16_xmodem (uint8_t *data, uint16_t length)
{
uint8_t i;
uint16_t crc = 0; // Initial value
while(length--)
{
crc ^= (uint16_t)(*data++) << 8; // crc ^= (uint16_t)(*data)<<8; data++;
for (i = 0; i < 8; ++i)
{
if ( crc & 0x8000 )
crc = (crc << 1) ^ 0x1021;
else
crc <<= 1;
}
}
return crc;
}
uint32_t crc32_step (uint32_t in_crc, const void *buf, uint32_t size)
{
static uint32_t crc_table[256] = {0, 0,};
uint32_t i = 0, j = 0, crc = 0;
if (!crc_table[1]) {
for (i = 0; i < 256; i++) {
crc = i;
for (j = 0; j < 8; j++) {
crc = (crc & 1) ? ((crc>>1)^0xEDB88320ul) : (crc>>1);
}
crc_table[i] = crc;
}
}
crc = in_crc ^ 0xFFFFFFFFul;
for (i = 0; i < size; i++) {
crc = crc_table[(crc ^ ((const uint8_t *)buf)[i]) & 0xFF]^(crc>>8);
}
return crc ^ 0xFFFFFFFFul;
}
+336
View File
@@ -0,0 +1,336 @@
#include "ymodem.h"
struct ymodem_info_t {
uint8_t isBusy; /* 正在处理主机数据的标志位 */
uint8_t enRecv; /* 使能接收主机的指令包 */
uint16_t rxLen; /* 接收到的数据长度 */
uint8_t *rxData; /* 协议解析的数据来源 */
uint8_t numPkt; /* 记录 YModem 协议的 packet number */
eYmFLOW flow; /* 记录协议的执行流程 */
union message_raw_t *msg; /* 接收主机数据包的缓存池,称为主机消息 */
struct tx_raw_t txPkt; /* 用于存放设备上发数据组包的部分参数 */
ymSend send; /* 数据发送接口 */
ymPrepareCallback prepare; /* 收到主机指令时的预备处理接口 */
ymReplyCallback reply; /* 正在执行指令时响应主机查询执行过程和结果的接口 */
};
static struct ymodem_info_t yM;
static struct drv_timer_t timerSendC; /* 用于定时向主机发送数据的定时器 */
static void timerSendCCallback (void *user_data)
{
static uint8_t c[1] = {YMODEM_C};
yM.send(c, 1, HAL_MAX_DELAY);
}
/**
* @brief 复位一些全局变量和标志信息
* @note
* @retval None
*/
static void ymodemReset (void)
{
yM.isBusy = 0;
yM.enRecv = 1;
yM.numPkt = 0;
yM.flow = YMODEM_FLOW_NONE;
}
/**
* @brief 对主机下发的心跳包的处理
* @note 对主机下发的数据帧进行回复, ymodem 没有心跳包,此处只是模拟
* @retval None
*/
static void ymodemHeartBeatProcess (void)
{
static eRESULT result;
yM.reply((eYmCMD)yM.msg->pkg.header, &result, NULL, NULL);
switch (result) {
case YM_RESULT_OK:
//yM.txPkt.response = YMODEM_ACK;
break;
case YM_RESULT_FAILED: {
/* 因前面已经加 1 ,此处是由于对数据处理有问题,非协议本身问题,因此需要减回 */
yM.numPkt--;
yM.txPkt.response = YMODEM_NAK;
break;
}
case YM_RESULT_CANCEL:
yM.txPkt.response = YMODEM_CAN;
break;
default:
/* 业务层还在处理数据,暂时不回复主机 */
return;
}
yM.isBusy = 0;
yM.send(&yM.txPkt.response, 1, HAL_MAX_DELAY);
}
/**
* @brief 对主机下发指令的处理
* @note
* @retval None
*/
static void ymodemCommandProcess (void)
{
uint16_t data_len = 0;
yM.isBusy = 1;
if ((yM.msg->pkg.header == YMODEM_SOH)||(yM.msg->pkg.header == YMODEM_STX)) {
data_len = yM.rxLen - YMODEM_FRAME_FIXED_LEN;
}
yM.prepare((eYmCMD)yM.msg->pkg.header, yM.msg->pkg.data, data_len);
}
/**
* @brief 设置协议执行流程
* @note
* @param[in] cmd: 主机的指令
* @retval eErrCode
*/
static eErrCode ymodemExeFlow (eYmCMD cmd)
{
switch (cmd) {
case YM_CMD_SOH: {
if (yM.flow == YMODEM_FLOW_NONE) { /* 第一个 SOH 数据帧 */
yM.flow = YMODEM_FLOW_START;
yM.txPkt.response = YMODEM_ACK;
} else if (yM.flow == YMODEM_FLOW_SECOND_EOT) { /* 最后一个空的 SOH 数据帧 */
drv_timer_pause(&timerSendC);
yM.flow = YMODEM_FLOW_SUCCESS;
yM.numPkt = 0;
yM.txPkt.response = YMODEM_ACK;
} else { /* 正在传输数据的 SOH 数据帧 */
/* 暂停发送字符“ C ”的定时器 */
drv_timer_pause(&timerSendC);
yM.txPkt.response = YMODEM_ACK;
}
break;
}
case YM_CMD_STX: {
/* 因为第一个有数据的数据帧可能是 STX ,因此此处有必要暂停发送字符“ C ”的定时器 */
drv_timer_pause(&timerSendC);
yM.txPkt.response = YMODEM_ACK;
break;
}
case YM_CMD_EOT: {
if (yM.flow == YMODEM_FLOW_START) { /* 第一个 EOT */
yM.flow = YMODEM_FLOW_FIRST_EOT;
yM.txPkt.response = YMODEM_NAK;
} else if (yM.flow == YMODEM_FLOW_FIRST_EOT) { /* 第二个 EOT */
yM.flow = YMODEM_FLOW_SECOND_EOT;
yM.numPkt = 0;
yM.txPkt.response = YMODEM_ACK;
/* 发完 ACK 需要继续发“ C ” */
drv_timer_restart(&timerSendC);
} else {
return ERR_EXE_FLOW;
}
break;
}
case YM_CMD_CAN: {
yM.flow = YMODEM_FLOW_CANCEL;
yM.txPkt.response = YMODEM_ACK;
break;
}
default:
break;
}
return ERR_OK;
}
/**
* @brief 协议解析处理函数
* @note 需要循环调用
* @retval eErrCode
*/
eErrCode ymodemHandler (uint8_t *data, uint16_t len)
{
eErrCode err_code;
/* 有数据 */
if (data && len && yM.enRecv) {
/* 暂存和格式化 */
yM.rxData = data;
yM.rxLen = len;
yM.msg = (union message_raw_t *)yM.rxData;
//hex_printf(data, len);
/* 只有数据帧才做以下错误检查 */
if (yM.msg->pkg.header == YMODEM_SOH || yM.msg->pkg.header == YMODEM_STX) {
/* 判断序列号是否符合顺序 */
if (yM.msg->pkg.pkt_num != yM.numPkt) {
if (yM.msg->pkg.pkt_num == (yM.numPkt - 1)) {
printf("error: duplicate frame %d %d\r\n", yM.msg->pkg.pkt_num, yM.numPkt);
err_code = ERR_DUPLICATE_FRAME;
} else {
printf("error: omission frame %d %d\r\n", yM.msg->pkg.pkt_num, yM.numPkt);
err_code = ERR_OMISSION_FRAME;
}
goto __error_exit;
}
/* 判断正反序列号是否正确 */
uint8_t pkt_num = ~(yM.msg->pkg.pkt_num);
if (yM.msg->pkg.not_pkt_num != pkt_num) {
printf("error: packet number: %.2X %.2X\r\n", yM.msg->pkg.pkt_num, yM.msg->pkg.not_pkt_num);
err_code = ERR_PKT_NUM_ERR;
goto __error_exit;
}
/* 获取协议帧中的数据字段长度 */
uint16_t data_len;
if (yM.msg->pkg.header == YMODEM_SOH) {
data_len = YMODEM_SOH_DATA_LEN;
} else if (yM.msg->pkg.header == YMODEM_STX) {
data_len = YMODEM_STX_DATA_LEN;
}
/* 帧长度判断 */
/* 奇怪的是, Xshell 在发送最后一个空 SOH 数据帧时会附加两个字节的 0x4F ,原因未知。
* 为了处理这个问题,避免误判为数据帧长度有误,此处嵌套了“ ymodem_pkt_num != 0 ”的判断 */
if (yM.numPkt != 0) {
if (yM.rxLen != (data_len + YMODEM_FRAME_FIXED_LEN)) {
//printf("error: _dev_rx_len: %d\r\n", yM.rxLen);
err_code = ERR_FRAME_LENGTH;
goto __error_exit;
}
}
/* 校验数据是否正确 */
uint16_t crc16 = crc16_xmodem(yM.msg->pkg.data, data_len);
printf("%04X", crc16);
uint16_t raw_crc16 = (yM.msg->pkg.data[data_len] << 8) | yM.msg->pkg.data[data_len + 1];
if (crc16 != raw_crc16) {
printf("error: crc16: %.4X\r\n", crc16);
printf("error: raw crc16: %.4X\r\n", raw_crc16);
err_code = ERR_FRAME_VERIFY_ERR;
goto __error_exit;
}
//printf("crc16 ok.\r\n");
/* 执行到此处记录序列号加1 */
yM.numPkt++;
}
//printf("Ymodem recv len: %d (%02X %02X %02X)\r\n",
// yM.rxLen, yM.msg->pkg.header, yM.msg->pkg.pkt_num, yM.msg->pkg.not_pkt_num);
/* 设置流程 */
if (ymodemExeFlow((eYmCMD)yM.msg->pkg.header)) {
//printf("error: flow illegal\r\n");
err_code = ERR_EXE_FLOW;
goto __error_exit;
}
/* 除了最后一个空的SOH数据帧,其他都会执行 ,包括 EOT CAN */
/* 需要注意是, 执行完后仍未回复主机,回复部分由 ymodemHeartBeatProcess 处理 */
ymodemCommandProcess();
return ERR_OK;
__error_exit:
yM.txPkt.response = YMODEM_NAK;
yM.send(&yM.txPkt.response, 1, HAL_MAX_DELAY);
return err_code;
}
if (yM.isBusy) {
/* 模拟主机的心跳处理,查询是否对协议包处理完毕,以向主机回复 */
ymodemHeartBeatProcess();
}
return ERR_OK;
}
/**
* @brief 配置协议析构层的参数
* @note
* @param[in] para: 需要进行配置的选型或参数
* @param[in] value: 对应的数据或值
* @retval None
*/
void ymodemConfig (eYmMODE mode, void *value)
{
switch (mode) {
case YM_MODE_RESET:
ymodemReset();
drv_timer_restart(&timerSendC);
break;
case YM_MODE_RECV: {
uint8_t *enable = (uint8_t *)value;
yM.enRecv = *enable;
if (yM.enRecv == 0) {
drv_timer_pause(&timerSendC);
}
break;
}
default:
break;
}
}
/**
* @brief 协议析构层的初始化
* @note
* @param[in] Send: 底层数据发送接口
* @param[in] HeartbeatCallback: 心跳包的响应接口
* @param[in] PrepareCallback: 指令包的处理接口
* @param[in] Set_ReplyInfo: 查询指令执行结果的处理接口
* @retval None
*/
void ymodem_init (ymSend Send,
ymPrepareCallback PrepareCallback,
ymReplyCallback Set_ReplyInfo)
{
yM.send = Send;
yM.prepare = PrepareCallback;
yM.reply = Set_ReplyInfo;
ymodemReset();
drv_timer_init(&timerSendC,
timerSendCCallback,
1000,
TIMER_RUN_FOREVER);
drv_timer_start(&timerSendC);
}
+90
View File
@@ -0,0 +1,90 @@
#ifndef _AES_H_
#define _AES_H_
#include <stdint.h>
// #define the macros below to 1/0 to enable/disable the mode of operation.
//
// CBC enables AES encryption in CBC-mode of operation.
// CTR enables encryption in counter-mode.
// ECB enables the basic ECB 16-byte block algorithm. All can be enabled simultaneously.
// The #ifndef-guard allows it to be configured before #include'ing or at compile time.
#ifndef CBC
#define CBC 1
#endif
#ifndef ECB
#define ECB 0
#endif
#ifndef CTR
#define CTR 0
#endif
//#define AES128 1
//#define AES192 1
#define AES256 1
#define AES_BLOCKLEN 16 // Block length in bytes - AES is 128b block only
#if defined(AES256) && (AES256 == 1)
#define AES_KEYLEN 32
#define AES_keyExpSize 240
#elif defined(AES192) && (AES192 == 1)
#define AES_KEYLEN 24
#define AES_keyExpSize 208
#else
#define AES_KEYLEN 16 // Key length in bytes
#define AES_keyExpSize 176
#endif
struct AES_ctx
{
uint8_t RoundKey[AES_keyExpSize];
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
uint8_t Iv[AES_BLOCKLEN];
#endif
};
void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key);
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv);
void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv);
#endif
#if defined(ECB) && (ECB == 1)
// buffer size is exactly AES_BLOCKLEN bytes;
// you need only AES_init_ctx as IV is not used in ECB
// NB: ECB is considered insecure for most uses
void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf);
void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf);
#endif // #if defined(ECB) && (ECB == !)
#if defined(CBC) && (CBC == 1)
// buffer size MUST be mutile of AES_BLOCKLEN;
// Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
// NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv()
// no IV should ever be reused with the same key
void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length);
void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length);
#endif // #if defined(CBC) && (CBC == 1)
#if defined(CTR) && (CTR == 1)
// Same function for encrypting as for decrypting.
// IV is incremented for every block, and used after encryption as XOR-compliment for output
// Suggesting https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
// NOTES: you need to set IV in ctx with AES_init_ctx_iv() or AES_ctx_set_iv()
// no IV should ever be reused with the same key
void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length);
#endif // #if defined(CTR) && (CTR == 1)
#endif // _AES_H_
+91
View File
@@ -0,0 +1,91 @@
#ifndef __APP_H__
#define __APP_H__
#include "firmware.h"
#include "ymodem.h"
#include "transfer.h"
#include "utils.h"
typedef enum {
EXE_FLOW_NOTHING = 0x00,
EXE_FLOW_ACCIDENT_UPDATE, /* 意外更新固件流程 */
EXE_FLOW_NEED_HOST_SEND_FIRMWARE, /* 需要主机下发固件包 */
EXE_FLOW_FIND_RUNNING_FIRMWARE, /* (0) 在各分区查找可运行的固件 */
EXE_FLOW_WAIT_FIRMWARE, /* 等待接收固件包 */
EXE_FLOW_VERIFY_FIRMWARE_HEAD, /* (1) 校验收到的固件包头 */
EXE_FLOW_ERASE_OLD_FIRMWARE, /* 擦除旧固件 */
EXE_FLOW_ERASE_OLD_FIRMWARE_DONE, /* 完成擦除旧固件 */
EXE_FLOW_WRITE_FIRMWARE_HEAD, /* 将固件包头写入 flash */
EXE_FLOW_WRITE_FIRMWARE_HEAD_DONE, /* 完成固件包头的写入 */
EXE_FLOW_VERIFY_FIRMWARE_PKG, /* (2) 校验固件分包数据的正确性 */
EXE_FLOW_WRITE_NEW_FIRMWARE, /* 写入新的固件分包到分区 */
EXE_FLOW_WRITE_NEW_FIRMWARE_DONE, /* 写入新的固件分包完成 */
EXE_FLOW_UPDATE_FIRMWARE, /* (3) 开始更新固件 */
EXE_FLOW_VERIFY_FIRMWARE, /* 校验整个固件包体的数据正确性 */
EXE_FLOW_VERIFY_FIRMWARE_DONE, /* 完成校验整个固件包体的数据正确性 */
EXE_FLOW_ERASE_APP, /* 擦除 APP 分区的固件 */
EXE_FLOW_UPDATE_TO_APP, /* 将其它分区的固件更新到 APP 分区 */
EXE_FLOW_VERIFY_APP, /* 校验 APP 分区固件的数据正确性 */
EXE_FLOW_UPDATE_TO_APP_DONE, /* 校验 APP 分区固件通过后,将剩余数据写入 */
EXE_FLOW_ERASE_DOWNLOAD, /* 擦除 download 分区 */
EXE_FLOW_ERASE_DOWNLOAD_DONE, /* 完成擦除 download 分区 */
EXE_FLOW_JUMP_TO_APP, /* 跳转至 APP 运行 */
EXE_FLOW_RECOVERY, /* 恢复出厂固件 */
EXE_FLOW_FAILED, /* 失败流程 */
} eFLOW;
/* 固件更新的缩略步骤,用于计算固件更新的进度 */
typedef enum {
STEP_VERIFY_FIRMWARE = 0x00, /* 校验接收到的固件包 */
STEP_ERASE_APP, /* 擦除 APP 分区 */
STEP_UPDATE_TO_APP, /* 更新固件包到 APP 分区 */
STEP_VERIFY_APP, /* 校验 APP 固件 */
STEP_ERASE_DOWNLOAD, /* 擦除 download 分区 */
} eSTAGE;
/* 应用状态 */
typedef enum {
BOOT_STATUS_NONE = 0x00,
BOOT_STATUS_NO_UPDATE, /* 无须更新固件的标志 */
BOOT_STATUS_ENTER_UPDATE_MODE, /* 进入固件更新模式的标志 */
BOOT_STATUS_ACCIDENT_UPDATE, /* 意外更新固件中 */
BOOT_STATUS_UPDATE_SUCCESS, /* 更新固件成功 */
BOOT_STATUS_UPDATE_FAILED, /* 更新固件失败 */
BOOT_STATUS_NO_FIRMWARE, /* 无任何可用固件 */
BOOT_STATUS_NO_APP, /* 无 APP 固件 */
BOOT_STATUS_READ_PART_ERR, /* 读取分区失败 */
BOOT_STATUS_APP_VERIFY_ERR, /* APP 固件校验错误 */
BOOT_STATUS_APP_CAN_NOT_VERIFY, /* APP 固件无法校验 */
BOOT_STATUS_AUTO_UPDATE_FAILED, /* 自动更新失败 */
} eSTATE;
struct upgrade_t {
eSTATE state; /* 记录 bootloader 所处的状态 */
eFLOW flow; /* 应用执行的流程 */
eSTAGE stage; /* 固件的更新阶段,便于程序判断 progress 的增加系数 */
eRESULT result; /* 指令执行结果 */
eErrCode errCode; /* 指令执行失败时的故障码 */
uint8_t start :1; /* 开始固件更新流程的标志 */
uint8_t :0;
uint8_t progress; /* 固件更新的总进度, 0-100 */
};
extern void System_Init (void);
extern void APP_Init (void);
extern void APP_Running (void);
#endif
+233
View File
@@ -0,0 +1,233 @@
#ifndef __APP_CONFIG_H__
#define __APP_CONFIG_H__
#define VERSION_MAIN 1
#define VERSION_SUB 0
#define VERSION_FIX 0
#define BOOT_VERSION ((VERSION_MAIN<<16)|(VERSION_SUB<<8)|VERSION_FIX)
#define BUILD_TIMESTAMP __DATE__", "__TIME__
#define NAME_PART_APPLICATION "app"
#define NAME_PART_DOWNLOAD "download"
#define NAME_PART_FACTORY "factory"
/** 配置各个分区的大小
需页对齐, 分区首地址必须是 Flash 的 每个独立 page 或 sector 的首地址,否则固件无法运行
*/
#if defined(STM32F405xx)
#define NAME_CHIP "STM32F405xx"
#define SIZE_ONCHIP_FLASH (1024 * 1024ul) // 片上 flash 总容量
#elif defined(STM32F411xE)
#define NAME_CHIP "STM32F411xE"
#define SIZE_ONCHIP_FLASH (512 * 1024ul)
#elif defined(STM32F401xC)
#define NAME_CHIP "STM32F401xC"
#define SIZE_ONCHIP_FLASH (256 * 1024ul)
#else
#error "no chip size defined"
#endif
#define SIZE_PART_BOOTLOADER (32 * 1024ul) // bootloader 占用空间(需要大于本程序bin大小)
#define SIZE_PART_PARAMETERS (32 * 1024ul) // 参数 占用空间
#define SIZE_PART_APPLICATION (SIZE_ONCHIP_FLASH/4) // app 占用空间 不少于1/4
#define SIZE_PART_DOWNLOAD (SIZE_PART_APPLICATION) // download 占用空间(不用时0)
#define SIZE_PART_FACTORY (SIZE_PART_APPLICATION) // factory 占用空间(不用时0)
#define BASE_ONCHIP_FLASH (FLASH_BASE) // on chip flash 首地址
#define OFFSET_ONCHIP_FLASH_END (BASE_ONCHIP_FLASH + SIZE_ONCHIP_FLASH)
/*
chipsize (256KB/512KB/1024KB) eg: 1024KB
32KB - bootloader = 0x00000 + 32*1024
32KB - parameter = 0x08000 + 32*1024
chipsize/2-64KB - application = 0x10000 + 448*1024
chipsize/4 - download = 0x80000 + 256*1024
chipsize/4 - factory = 0xC0000 + 256*1024
*/
#define BASE_BOOTLOADER (BASE_ONCHIP_FLASH)
#define BASE_PARAMETERS (BASE_BOOTLOADER + SIZE_PART_BOOTLOADER) // 参数分区起始地址
#define BASE_APPLICATION (BASE_ONCHIP_FLASH + SIZE_PART_BOOTLOADER+SIZE_PART_PARAMETERS) // app 分区起始地址
#define BASE_DOWNLOAD (BASE_ONCHIP_FLASH + SIZE_ONCHIP_FLASH/2) // download 分区起始地址
#define BASE_FACTORY (BASE_DOWNLOAD + SIZE_PART_DOWNLOAD) // factory 分区起始地址
/* 片上分区数量选项
* app: 可运行的固件区域
* download: 用于更新固件时的固件临时存放区域
* factory: 用于存放可在紧急情况下恢复固件使用的区域
*/
#define USE_SINGLE_PARTITION 0 // 单分区方案 仅 app
#define USE_DOUBLE_PARTITION 1 // 双分区方案 含 app + download
#define USE_TRIPLE_PARTITION 2 // 三分区方案 含 app + download + factory
#define CONFIG_CHIP_PARTS USE_TRIPLE_PARTITION
#define ENABLE_ASSERT 0 /* 是否使能函数入口参数检查 */
#define ENABLE_DEBUG_PRINT 1 /* 是否使能调试信息打印 */
#define MAX_NAME_LEN 8
// 本 bootloader 运行窗口最小时间
#define CONFIG_TIMEOUT_HOST_START (5*1000) // 设置等待主机数据的最大等待时间,单位 ms
#define CONFIG_DECRYPT 1
#if (CONFIG_DECRYPT)
// 以下同步给 upk 打包工具
#define AES256_KEY "0123456789ABCDEF0123456789ABCDEF" // 必须是 32 字节
#define AES256_IV "0123456789ABCDEF" // 必须是 16 字节
#endif
/* 判断固件包是否超过分区大小 */
#define CONFIG_CHECK_SIZE 1
/* 单次写入的最小字节数*/
#define CONFIG_WRITE_BYTES_LEASET 4
/* 自动更新固件的处理选项
* 1. 在固件更新过程中设备异常断电或重启后,选择是否自动更新已下载好的固件以及自动更新的处理方案
* 2. 该选项的执行优先级低于上位机更新的方式,这意味着除非上位机超时未发送数据,否则将会优先执行上位机的固件更新
*
* MODE_NOT_AUTO_UPDATE: 不需要自动更新,不希望有这种断电恢复固件的机制
* MODE_CLEAR_DOWNLOAD_PART: 更新完成后擦除 download 分区。设备上电时会通过检测 download 分区有无可用固件
* 以判断是否需要自动更新固件
* 选择此方案后,将无法选择是否在上电后对 APP 的固件进行安规校验( CONFIG_CHECK_APP_SECURITY )。
* 因为 APP 固件安规校验的数据来源是 download 分区的固件包。
* MODE_UPDATE_DOWNLOAD_HEAD: 更新完成后修改 download 分区的固件表头的版本信息。设备上电时会对比 download 分区固件包头记录的新旧版本,
* 若新旧版本不一致,则开始自动更新固件
* 此种方式需要修改 download 分区的数据,有以下优劣势:
* 1. 优势:上电时可校验 APP 分区的固件数据正确性和完整性,以提高 APP 固件有损坏或遭篡改时的安全性,甚至
* 可以将固件恢复正常,有效提高系统的安全等级
* 2. 劣势:需要对表头所在的 flash sector 擦除后再重新写入,这意味着每次更新都会擦除同个 sector 两次。
* MODE_APPEND_TO_APP: 更新完成后将新的固件版本写进 APP 分区的尾部,占用 16 byte ,设备上电时会对比 download 分区固件包头
* 记录的版本和 APP 存放的版本,若两个版本不一致,则开始自动更新固件
* 此种方式有以下优劣势:
* 1. 优势:上电时可校验 APP 分区的固件数据正确性和完整性,以提高 APP 固件有损坏或遭篡改时的安全性,甚至
* 可以将固件恢复正常,有效提高系统的安全等级
* 2. 劣势:需要占用 APP 分区 16 byte 的空间
*/
#define MODE_NOT_AUTO_UPDATE 0
#define MODE_CLEAR_DOWNLOAD_PART 1
#define MODE_UPDATE_DOWNLOAD_HEAD 2
#define MODE_APPEND_TO_APP 3
#if (CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION)
#define CONFIG_AUTO_UPDATE_MODE MODE_APPEND_TO_APP
#endif
/** 是否在上电后对 APP 的固件进行安规校验 及 APP 固件检查有问题时的操作
* 1. CONFIG_AUTO_UPDATE_MODE = MODE_UPDATE_DOWNLOAD_HEAD 时,本配置才会起效
* 2. 部分产品对固件的完整性有安规等级要求,本组件支持 APP 固件的数据完整性检查,通过配置以选择是否启用
* 3. 当启用时,通过配置 USING_APP_SAFETY_PROJECT 可选择 APP 固件检查有问题时的操作方案
* DO_NOT_CHECK : 不校验 APP 固件,即不启用
* CHECK_UNLESS_EMPTY: 校验 APP 固件,但无法校验时不校验,确保能运行 APP 而不至于等在 bootloader 中。若 APP 固件校验错误,将会
* 自动把可用和正确的固件更新至 APP
* * 无法进行 APP 固件校验的情况是: download 分区和 factory 分区均无可用固件包
* AUTO_UPDATE_APP : APP 固件校验错误后自动将可用和正确的固件更新至 APP
* * 需要注意的是,当选择了本选项,意味着你十分重视 APP 的数据完整性,也就是说,当 APP 固件校验不通过或
* 无法校验时,若 download 分区和 factory 分区均无可用固件包,则会停留在 bootloader 中,不会跳转至 APP
* 即便 APP 存在固件
* * 需要特别声明的是,有一种情况会导致 APP 无法被执行,那便是通过烧录器将固件烧录进 MCU 的 flash 中,
* 因为此时不是通过正常的固件更新程序执行, download 分区和 factory 分区均无可用固件包, APP 固件无法进行
* 完整性校验,建议采用正常的固件更新流程,即由 bootloader 处理固件更新,或选择 CHECK_UNLESS_EMPTY 选型
* * 此处的自动更新和 CONFIG_AUTO_UPDATE_MODE 的不同,本选项仅在 APP 固件校验不通过时才会
* 自动更新,而 CONFIG_AUTO_UPDATE_MODE 则是无视本选项进行固件自动更新
* DO_NOT_DO_ANYTHING: APP固件校验错误后不要做任何操作,停在 bootloader 即可,即便 download 分区或 factory 分区有可用的固件包
* * 需要注意的是, DO_NOT_DO_ANYTHING 这个选项并不能阻止 APP 分区为空时且 CONFIG_AUTO_UPDATE_MODE 启用了
* 自动更新的情况, DO_NOT_DO_ANYTHING 只能阻拦APP分区不为空且校验不通过的情况,要阻止自动更新,需要修改
* 上方的 CONFIG_AUTO_UPDATE_MODE 选项为 DO_NOT_AUTO_UPDATE
*/
#define DO_NOT_CHECK 0
#define CHECK_UNLESS_EMPTY 1
#define AUTO_UPDATE_APP 2
#define DO_NOT_DO_ANYTHING 3
#if ((CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION) \
&&((CONFIG_AUTO_UPDATE_MODE == MODE_UPDATE_DOWNLOAD_HEAD) \
||(CONFIG_AUTO_UPDATE_MODE == MODE_APPEND_TO_APP)))
#define CONFIG_CHECK_APP_SECURITY CHECK_UNLESS_EMPTY
#endif
/**
* 【选择是否可以使用 factory 分区的固件包】
* 说明:
* 当启用自动更新或校验 APP 固件完整性时,若 APP 固件不可用,且 download 分区没有可用的固件时,假设有 factory 分区,
* 且 factory 分区有可用的固件,选择是否将 factory 的固件更新至 APP 中
* 选项:
* 0: 不使用
* 1: 使用
*/
#if ((CONFIG_CHIP_PARTS == USE_TRIPLE_PARTITION) \
&&((CONFIG_CHECK_APP_SECURITY == CHECK_UNLESS_EMPTY) \
||(CONFIG_CHECK_APP_SECURITY == AUTO_UPDATE_APP)))
#define CONFIG_FACTORY_RESTORE 1
#endif
/** 是否自动纠正固件的分区
* 说明:
* 该选项是为了修正人为的将分区名写错的情况,是一种能最大程度保证固件更新正常的挽救措施
* 单分区方案下,无论本功能是否启用,固件包指定的其它分区名都会被修正为 APP 分区,使其可以正常更新
* 多分区方案下,启用后,固件包指定为 APP 分区时将会被修正为 download 分区,使其可以正常更新
* 多分区方案下,若不启用,固件包指定为 APP 分区时将会报错,并标记为更新失败
* 选项:
* 0: 不启用
* 1: 启用
*/
#if (CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION)
#define CONFIG_AUTO_CORRECT 1
#endif
/**
* 【选择是否使用按键恢复出厂固件的选项】
* 说明:
* 1. 使用本选项的前提是三分区方案,本选项能起效的前提是正确配置了按键且 factory 分区有可用的固件
* 2. 选择使用按键恢复出厂固件时,需要配置按键的引脚,如使用的按键和本案例不同,则需要自己配置和初始化 GPIO
* 3. 本选项仅设备在运行 bootloader 时,可通过按键恢复出厂固件,若设备运行着 APP ,则本选项是无法起效的,因此需要 APP 也同步配置
* 4. 本选项和通过指令恢复出厂固件的方式不冲突,可以同时使用,也可以不启用本选项
* 5. 当无 factory 或 factory 无可用固件时,强行恢复出厂固件,将会触发 FACTORY_NO_FIRMWARE_SOLUTION 选项
* 解释:
* ENABLE_FACTORY_FIRMWARE_BUTTON: 选择是否启用长按按键恢复出厂固件
* FACTORY_FIRMWARE_BUTTON_PRESS: 按键按下时的电平逻辑
* FACTORY_FIRMWARE_BUTTON_TIME: 按键长按的持续时间,单位 ms
* 选项:
* ENABLE_FACTORY_FIRMWARE_BUTTON 选项:
* 0: 不启用
* 1: 启用
* FACTORY_FIRMWARE_BUTTON_PRESS 选项:
* KEY_PRESS_LOW: 表示按下时为低电平
* KEY_PRESS_HIGH: 表示按下时为高电平
* FACTORY_FIRMWARE_BUTTON_TIME 选项:
* 按键长按的持续时间,单位 ms ,不能大于 65535
*/
#if (CONFIG_CHIP_PARTS == USE_TRIPLE_PARTITION)
#define ENABLE_FACTORY_FIRMWARE_BUTTON 0
#define FACTORY_FIRMWARE_BUTTON_PRESS KEY_PRESS_LOW
#define FACTORY_FIRMWARE_BUTTON_TIME 3000
#endif
/**
* 【片内 Flash 放置固件包所在 sector 的擦除粒度 ( TODO: 暂未实现 )】
* 说明:
* CONFIG_AUTO_UPDATE_MODE = MODE_UPDATE_DOWNLOAD_HEAD 时,需要给出固件包所在 sector 的擦除粒度,单位是 byte
*/
#if (CONFIG_AUTO_UPDATE_MODE == MODE_UPDATE_DOWNLOAD_HEAD)
#define ONCHIP_FLASH_ERASE_GRANULARITY UPK_LEAST_HANDLE_BYTE
#endif
#endif
+72
View File
@@ -0,0 +1,72 @@
#ifndef __FIRMWARE_MANAGE_H__
#define __FIRMWARE_MANAGE_H__
#include "bsp_common.h"
#include "utils.h"
/* upk: upgrade Package */
#define UPK_LEAST_HANDLE_BYTE 4096
#define UPK_VERSION_SIZE 16
#define UPK_USER_STRING_SIZE 16
#define UPK_PART_NAME_SIZE 16
#define UPK_HEAD_SIZE sizeof(struct upk_head_t)
#define UPK_IDENTIFIER 0x006B7075 // 'upk'
/* 固件写入的方向 */
typedef enum
{
FM_DIR_HOST_TO_APP = 0x00, /* 从主机方向将固件写入 APP 分区 */
FM_DIR_HOST_TO_DOWNLOAD, /* 从主机方向将固件写入 download/factory 分区 */
FM_DIR_DOWNLOAD_TO_APP, /* 从 download/factory 分区方向将固件写入 APP 分区 */
} FM_FIRMWARE_WRITE_DIR;
#pragma pack(1)
/* upk 固件表头的内容详见《upk固件包表头信息.xlsx》 */
struct upk_head_t {
char name[4]; /* upk 文件标识 */
uint8_t config[4]; /* 配置选项 */
char fw_old_ver[UPK_VERSION_SIZE]; /* 固件旧版本 */
char fw_new_ver[UPK_VERSION_SIZE]; /* 固件新版本 */
char user_string[UPK_USER_STRING_SIZE]; /* 用户自定义的字符水印 */
char part_name[UPK_PART_NAME_SIZE]; /* 固件包存放的分区名 */
uint32_t raw_size; /* 源固件的大小,不包含本表头 */
uint32_t pkg_size; /* 打包后固件的大小,不包含本表头 */
uint32_t timestamp; /* 打包时的 unix 时间戳,可转换为年月日时分秒信息 */
uint32_t raw_crc; /* 源固件的 CRC32 值 */
uint32_t pkg_crc; /* 打包后固件的 CRC32 值 */
uint32_t head_crc; /* 本表头的 CRC32 值 */
};
#pragma pack()
void FM_Init (void);
uint8_t FM_IsEncrypt (void);
eErrCode FM_IsEmpty (const char *part_name);
char * FM_GetNewFirmwareVersion (void);
uint32_t FM_GetRawCRC32 (void);
eErrCode FM_StorageFirmwareHead (const char *part_name, uint8_t *data);
eErrCode FM_VerifyFirmware (const char *part_name, uint32_t crc32, uint8_t is_auto_fill);
eErrCode FM_EraseFirmware (const char *part_name);
eErrCode FM_WriteFirmwareDone (const char *part_name);
eErrCode FM_WriteFirmwareSubPackage (const char *part_name, uint8_t *data, uint16_t pkg_size);
eErrCode FM_CheckFirmwareIntegrity (uint32_t addr);
#if (CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION)
uint8_t FM_IsNeedAutoUpdate (void);
char * FM_GetPartName (void);
char * FM_GetOldFirmwareVersion (void);
uint32_t FM_GetPackageCRC32 (void);
eErrCode FM_ReadFirmwareHead (const char *part_name);
eErrCode FM_UpdateToAPP (const char *from_part_name);
#if (CONFIG_AUTO_UPDATE_MODE == MODE_UPDATE_DOWNLOAD_HEAD || \
CONFIG_AUTO_UPDATE_MODE == MODE_APPEND_TO_APP)
eErrCode FM_UpdateFirmwareVersion (const char *part_name);
#endif
#endif
#endif
+36
View File
@@ -0,0 +1,36 @@
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32f4xx_hal.h"
#if defined(STM32F405xx)
#define KEY0_Pin GPIO_PIN_8
#define KEY0_GPIO_Port GPIOC
#define LED0_Pin GPIO_PIN_8
#define LED0_GPIO_Port GPIOA
#elif defined(STM32F411xE)||defined(STM32F401xC)
#define KEY0_Pin GPIO_PIN_0
#define KEY0_GPIO_Port GPIOA
#define LED0_Pin GPIO_PIN_13
#define LED0_GPIO_Port GPIOC
#endif
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */
+490
View File
@@ -0,0 +1,490 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f4xx_hal_conf_template.h
* @author MCD Application Team
* @brief HAL configuration template file.
* This file should be copied to the application folder and renamed
* to stm32f4xx_hal_conf.h.
******************************************************************************
* @attention
*
* Copyright (c) 2017 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F4xx_HAL_CONF_H
#define __STM32F4xx_HAL_CONF_H
#ifdef __cplusplus
extern "C" {
#endif
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* ########################## Module Selection ############################## */
/**
* @brief This is the list of modules to be used in the HAL driver
*/
#define HAL_MODULE_ENABLED
/* #define HAL_CRYP_MODULE_ENABLED */
/* #define HAL_ADC_MODULE_ENABLED */
/* #define HAL_CAN_MODULE_ENABLED */
/* #define HAL_CRC_MODULE_ENABLED */
/* #define HAL_CAN_LEGACY_MODULE_ENABLED */
/* #define HAL_DAC_MODULE_ENABLED */
/* #define HAL_DCMI_MODULE_ENABLED */
/* #define HAL_DMA2D_MODULE_ENABLED */
/* #define HAL_ETH_MODULE_ENABLED */
/* #define HAL_NAND_MODULE_ENABLED */
/* #define HAL_NOR_MODULE_ENABLED */
/* #define HAL_PCCARD_MODULE_ENABLED */
/* #define HAL_SRAM_MODULE_ENABLED */
/* #define HAL_SDRAM_MODULE_ENABLED */
/* #define HAL_HASH_MODULE_ENABLED */
/* #define HAL_I2C_MODULE_ENABLED */
/* #define HAL_I2S_MODULE_ENABLED */
/* #define HAL_IWDG_MODULE_ENABLED */
/* #define HAL_LTDC_MODULE_ENABLED */
/* #define HAL_RNG_MODULE_ENABLED */
/* #define HAL_RTC_MODULE_ENABLED */
/* #define HAL_SAI_MODULE_ENABLED */
/* #define HAL_SD_MODULE_ENABLED */
/* #define HAL_MMC_MODULE_ENABLED */
/* #define HAL_SPI_MODULE_ENABLED */
/* #define HAL_TIM_MODULE_ENABLED */
#define HAL_UART_MODULE_ENABLED
/* #define HAL_USART_MODULE_ENABLED */
/* #define HAL_IRDA_MODULE_ENABLED */
/* #define HAL_SMARTCARD_MODULE_ENABLED */
/* #define HAL_SMBUS_MODULE_ENABLED */
/* #define HAL_WWDG_MODULE_ENABLED */
/* #define HAL_PCD_MODULE_ENABLED */
/* #define HAL_HCD_MODULE_ENABLED */
/* #define HAL_DSI_MODULE_ENABLED */
/* #define HAL_QSPI_MODULE_ENABLED */
/* #define HAL_QSPI_MODULE_ENABLED */
/* #define HAL_CEC_MODULE_ENABLED */
/* #define HAL_FMPI2C_MODULE_ENABLED */
/* #define HAL_FMPSMBUS_MODULE_ENABLED */
/* #define HAL_SPDIFRX_MODULE_ENABLED */
/* #define HAL_DFSDM_MODULE_ENABLED */
/* #define HAL_LPTIM_MODULE_ENABLED */
#define HAL_GPIO_MODULE_ENABLED
#define HAL_EXTI_MODULE_ENABLED
#define HAL_DMA_MODULE_ENABLED
#define HAL_RCC_MODULE_ENABLED
#define HAL_FLASH_MODULE_ENABLED
#define HAL_PWR_MODULE_ENABLED
#define HAL_CORTEX_MODULE_ENABLED
/* ########################## HSE/HSI Values adaptation ##################### */
/**
* @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSE is used as system clock source, directly or through the PLL).
*/
#if !defined (HSE_VALUE)
#define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined (HSE_STARTUP_TIMEOUT)
#define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */
#endif /* HSE_STARTUP_TIMEOUT */
/**
* @brief Internal High Speed oscillator (HSI) value.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSI is used as system clock source, directly or through the PLL).
*/
#if !defined (HSI_VALUE)
#define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */
/**
* @brief Internal Low Speed oscillator (LSI) value.
*/
#if !defined (LSI_VALUE)
#define LSI_VALUE 32000U /*!< LSI Typical Value in Hz*/
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
The real value may vary depending on the variations
in voltage and temperature.*/
/**
* @brief External Low Speed oscillator (LSE) value.
*/
#if !defined (LSE_VALUE)
#define LSE_VALUE 32768U /*!< Value of the External Low Speed oscillator in Hz */
#endif /* LSE_VALUE */
#if !defined (LSE_STARTUP_TIMEOUT)
#define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */
#endif /* LSE_STARTUP_TIMEOUT */
/**
* @brief External clock source for I2S peripheral
* This value is used by the I2S HAL module to compute the I2S clock source
* frequency, this source is inserted directly through I2S_CKIN pad.
*/
#if !defined (EXTERNAL_CLOCK_VALUE)
#define EXTERNAL_CLOCK_VALUE 12288000U /*!< Value of the External audio frequency in Hz*/
#endif /* EXTERNAL_CLOCK_VALUE */
/* Tip: To avoid modifying this file each time you need to use different HSE,
=== you can define the HSE value in your toolchain compiler preprocessor. */
/* ########################### System Configuration ######################### */
/**
* @brief This is the HAL system configuration section
*/
#define VDD_VALUE 3300U /*!< Value of VDD in mv */
#define TICK_INT_PRIORITY 15U /*!< tick interrupt priority */
#define USE_RTOS 0U
#define PREFETCH_ENABLE 1U
#define INSTRUCTION_CACHE_ENABLE 1U
#define DATA_CACHE_ENABLE 1U
#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */
#define USE_HAL_CAN_REGISTER_CALLBACKS 0U /* CAN register callback disabled */
#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */
#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */
#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */
#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */
#define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U /* DFSDM register callback disabled */
#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */
#define USE_HAL_DSI_REGISTER_CALLBACKS 0U /* DSI register callback disabled */
#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */
#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */
#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */
#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */
#define USE_HAL_FMPI2C_REGISTER_CALLBACKS 0U /* FMPI2C register callback disabled */
#define USE_HAL_FMPSMBUS_REGISTER_CALLBACKS 0U /* FMPSMBUS register callback disabled */
#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */
#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */
#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */
#define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */
#define USE_HAL_MMC_REGISTER_CALLBACKS 0U /* MMC register callback disabled */
#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */
#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */
#define USE_HAL_PCCARD_REGISTER_CALLBACKS 0U /* PCCARD register callback disabled */
#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */
#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */
#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */
#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */
#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */
#define USE_HAL_SD_REGISTER_CALLBACKS 0U /* SD register callback disabled */
#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */
#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */
#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */
#define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */
#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */
#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */
#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */
#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */
#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */
#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */
/* ########################## Assert Selection ############################## */
/**
* @brief Uncomment the line below to expanse the "assert_param" macro in the
* HAL drivers code
*/
/* #define USE_FULL_ASSERT 1U */
/* ################## Ethernet peripheral configuration ##################### */
/* Section 1 : Ethernet peripheral configuration */
/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */
#define MAC_ADDR0 2U
#define MAC_ADDR1 0U
#define MAC_ADDR2 0U
#define MAC_ADDR3 0U
#define MAC_ADDR4 0U
#define MAC_ADDR5 0U
/* Definition of the Ethernet driver buffers size and count */
#define ETH_RX_BUF_SIZE /* buffer size for receive */
#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */
#define ETH_RXBUFNB 4U /* 4 Rx buffers of size ETH_RX_BUF_SIZE */
#define ETH_TXBUFNB 4U /* 4 Tx buffers of size ETH_TX_BUF_SIZE */
/* Section 2: PHY configuration section */
/* DP83848_PHY_ADDRESS Address*/
#define DP83848_PHY_ADDRESS 0x01U
/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/
#define PHY_RESET_DELAY 0x000000FFU
/* PHY Configuration delay */
#define PHY_CONFIG_DELAY 0x00000FFFU
#define PHY_READ_TO 0x0000FFFFU
#define PHY_WRITE_TO 0x0000FFFFU
/* Section 3: Common PHY Registers */
#define PHY_BCR ((uint16_t)0x0000U) /*!< Transceiver Basic Control Register */
#define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */
#define PHY_RESET ((uint16_t)0x8000U) /*!< PHY Reset */
#define PHY_LOOPBACK ((uint16_t)0x4000U) /*!< Select loop-back mode */
#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U) /*!< Set the full-duplex mode at 100 Mb/s */
#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000U) /*!< Set the half-duplex mode at 100 Mb/s */
#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100U) /*!< Set the full-duplex mode at 10 Mb/s */
#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000U) /*!< Set the half-duplex mode at 10 Mb/s */
#define PHY_AUTONEGOTIATION ((uint16_t)0x1000U) /*!< Enable auto-negotiation function */
#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*!< Restart auto-negotiation function */
#define PHY_POWERDOWN ((uint16_t)0x0800U) /*!< Select the power down mode */
#define PHY_ISOLATE ((uint16_t)0x0400U) /*!< Isolate PHY from MII */
#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*!< Auto-Negotiation process completed */
#define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */
#define PHY_JABBER_DETECTION ((uint16_t)0x0002U) /*!< Jabber condition detected */
/* Section 4: Extended PHY Registers */
#define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */
#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */
#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */
/* ################## SPI peripheral configuration ########################## */
/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver
* Activated: CRC code is present inside driver
* Deactivated: CRC code cleaned from driver
*/
#define USE_SPI_CRC 0U
/* Includes ------------------------------------------------------------------*/
/**
* @brief Include module's header file
*/
#ifdef HAL_RCC_MODULE_ENABLED
#include "stm32f4xx_hal_rcc.h"
#endif /* HAL_RCC_MODULE_ENABLED */
#ifdef HAL_GPIO_MODULE_ENABLED
#include "stm32f4xx_hal_gpio.h"
#endif /* HAL_GPIO_MODULE_ENABLED */
#ifdef HAL_EXTI_MODULE_ENABLED
#include "stm32f4xx_hal_exti.h"
#endif /* HAL_EXTI_MODULE_ENABLED */
#ifdef HAL_DMA_MODULE_ENABLED
#include "stm32f4xx_hal_dma.h"
#endif /* HAL_DMA_MODULE_ENABLED */
#ifdef HAL_CORTEX_MODULE_ENABLED
#include "stm32f4xx_hal_cortex.h"
#endif /* HAL_CORTEX_MODULE_ENABLED */
#ifdef HAL_ADC_MODULE_ENABLED
#include "stm32f4xx_hal_adc.h"
#endif /* HAL_ADC_MODULE_ENABLED */
#ifdef HAL_CAN_MODULE_ENABLED
#include "stm32f4xx_hal_can.h"
#endif /* HAL_CAN_MODULE_ENABLED */
#ifdef HAL_CAN_LEGACY_MODULE_ENABLED
#include "stm32f4xx_hal_can_legacy.h"
#endif /* HAL_CAN_LEGACY_MODULE_ENABLED */
#ifdef HAL_CRC_MODULE_ENABLED
#include "stm32f4xx_hal_crc.h"
#endif /* HAL_CRC_MODULE_ENABLED */
#ifdef HAL_CRYP_MODULE_ENABLED
#include "stm32f4xx_hal_cryp.h"
#endif /* HAL_CRYP_MODULE_ENABLED */
#ifdef HAL_DMA2D_MODULE_ENABLED
#include "stm32f4xx_hal_dma2d.h"
#endif /* HAL_DMA2D_MODULE_ENABLED */
#ifdef HAL_DAC_MODULE_ENABLED
#include "stm32f4xx_hal_dac.h"
#endif /* HAL_DAC_MODULE_ENABLED */
#ifdef HAL_DCMI_MODULE_ENABLED
#include "stm32f4xx_hal_dcmi.h"
#endif /* HAL_DCMI_MODULE_ENABLED */
#ifdef HAL_ETH_MODULE_ENABLED
#include "stm32f4xx_hal_eth.h"
#endif /* HAL_ETH_MODULE_ENABLED */
#ifdef HAL_FLASH_MODULE_ENABLED
#include "stm32f4xx_hal_flash.h"
#endif /* HAL_FLASH_MODULE_ENABLED */
#ifdef HAL_SRAM_MODULE_ENABLED
#include "stm32f4xx_hal_sram.h"
#endif /* HAL_SRAM_MODULE_ENABLED */
#ifdef HAL_NOR_MODULE_ENABLED
#include "stm32f4xx_hal_nor.h"
#endif /* HAL_NOR_MODULE_ENABLED */
#ifdef HAL_NAND_MODULE_ENABLED
#include "stm32f4xx_hal_nand.h"
#endif /* HAL_NAND_MODULE_ENABLED */
#ifdef HAL_PCCARD_MODULE_ENABLED
#include "stm32f4xx_hal_pccard.h"
#endif /* HAL_PCCARD_MODULE_ENABLED */
#ifdef HAL_SDRAM_MODULE_ENABLED
#include "stm32f4xx_hal_sdram.h"
#endif /* HAL_SDRAM_MODULE_ENABLED */
#ifdef HAL_HASH_MODULE_ENABLED
#include "stm32f4xx_hal_hash.h"
#endif /* HAL_HASH_MODULE_ENABLED */
#ifdef HAL_I2C_MODULE_ENABLED
#include "stm32f4xx_hal_i2c.h"
#endif /* HAL_I2C_MODULE_ENABLED */
#ifdef HAL_SMBUS_MODULE_ENABLED
#include "stm32f4xx_hal_smbus.h"
#endif /* HAL_SMBUS_MODULE_ENABLED */
#ifdef HAL_I2S_MODULE_ENABLED
#include "stm32f4xx_hal_i2s.h"
#endif /* HAL_I2S_MODULE_ENABLED */
#ifdef HAL_IWDG_MODULE_ENABLED
#include "stm32f4xx_hal_iwdg.h"
#endif /* HAL_IWDG_MODULE_ENABLED */
#ifdef HAL_LTDC_MODULE_ENABLED
#include "stm32f4xx_hal_ltdc.h"
#endif /* HAL_LTDC_MODULE_ENABLED */
#ifdef HAL_PWR_MODULE_ENABLED
#include "stm32f4xx_hal_pwr.h"
#endif /* HAL_PWR_MODULE_ENABLED */
#ifdef HAL_RNG_MODULE_ENABLED
#include "stm32f4xx_hal_rng.h"
#endif /* HAL_RNG_MODULE_ENABLED */
#ifdef HAL_RTC_MODULE_ENABLED
#include "stm32f4xx_hal_rtc.h"
#endif /* HAL_RTC_MODULE_ENABLED */
#ifdef HAL_SAI_MODULE_ENABLED
#include "stm32f4xx_hal_sai.h"
#endif /* HAL_SAI_MODULE_ENABLED */
#ifdef HAL_SD_MODULE_ENABLED
#include "stm32f4xx_hal_sd.h"
#endif /* HAL_SD_MODULE_ENABLED */
#ifdef HAL_SPI_MODULE_ENABLED
#include "stm32f4xx_hal_spi.h"
#endif /* HAL_SPI_MODULE_ENABLED */
#ifdef HAL_TIM_MODULE_ENABLED
#include "stm32f4xx_hal_tim.h"
#endif /* HAL_TIM_MODULE_ENABLED */
#ifdef HAL_UART_MODULE_ENABLED
#include "stm32f4xx_hal_uart.h"
#endif /* HAL_UART_MODULE_ENABLED */
#ifdef HAL_USART_MODULE_ENABLED
#include "stm32f4xx_hal_usart.h"
#endif /* HAL_USART_MODULE_ENABLED */
#ifdef HAL_IRDA_MODULE_ENABLED
#include "stm32f4xx_hal_irda.h"
#endif /* HAL_IRDA_MODULE_ENABLED */
#ifdef HAL_SMARTCARD_MODULE_ENABLED
#include "stm32f4xx_hal_smartcard.h"
#endif /* HAL_SMARTCARD_MODULE_ENABLED */
#ifdef HAL_WWDG_MODULE_ENABLED
#include "stm32f4xx_hal_wwdg.h"
#endif /* HAL_WWDG_MODULE_ENABLED */
#ifdef HAL_PCD_MODULE_ENABLED
#include "stm32f4xx_hal_pcd.h"
#endif /* HAL_PCD_MODULE_ENABLED */
#ifdef HAL_HCD_MODULE_ENABLED
#include "stm32f4xx_hal_hcd.h"
#endif /* HAL_HCD_MODULE_ENABLED */
#ifdef HAL_DSI_MODULE_ENABLED
#include "stm32f4xx_hal_dsi.h"
#endif /* HAL_DSI_MODULE_ENABLED */
#ifdef HAL_QSPI_MODULE_ENABLED
#include "stm32f4xx_hal_qspi.h"
#endif /* HAL_QSPI_MODULE_ENABLED */
#ifdef HAL_CEC_MODULE_ENABLED
#include "stm32f4xx_hal_cec.h"
#endif /* HAL_CEC_MODULE_ENABLED */
#ifdef HAL_FMPI2C_MODULE_ENABLED
#include "stm32f4xx_hal_fmpi2c.h"
#endif /* HAL_FMPI2C_MODULE_ENABLED */
#ifdef HAL_FMPSMBUS_MODULE_ENABLED
#include "stm32f4xx_hal_fmpsmbus.h"
#endif /* HAL_FMPSMBUS_MODULE_ENABLED */
#ifdef HAL_SPDIFRX_MODULE_ENABLED
#include "stm32f4xx_hal_spdifrx.h"
#endif /* HAL_SPDIFRX_MODULE_ENABLED */
#ifdef HAL_DFSDM_MODULE_ENABLED
#include "stm32f4xx_hal_dfsdm.h"
#endif /* HAL_DFSDM_MODULE_ENABLED */
#ifdef HAL_LPTIM_MODULE_ENABLED
#include "stm32f4xx_hal_lptim.h"
#endif /* HAL_LPTIM_MODULE_ENABLED */
#ifdef HAL_MMC_MODULE_ENABLED
#include "stm32f4xx_hal_mmc.h"
#endif /* HAL_MMC_MODULE_ENABLED */
/* Exported macro ------------------------------------------------------------*/
#ifdef USE_FULL_ASSERT
/**
* @brief The assert_param macro is used for function's parameters check.
* @param expr If expr is false, it calls assert_failed function
* which reports the name of the source file and the source
* line number of the call that failed.
* If expr is true, it returns no value.
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t* file, uint32_t line);
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */
#ifdef __cplusplus
}
#endif
#endif /* __STM32F4xx_HAL_CONF_H */
+66
View File
@@ -0,0 +1,66 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f4xx_it.h
* @brief This file contains the headers of the interrupt handlers.
******************************************************************************
* @attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F4xx_IT_H
#define __STM32F4xx_IT_H
#ifdef __cplusplus
extern "C" {
#endif
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void SVC_Handler(void);
void DebugMon_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
#ifdef __cplusplus
}
#endif
#endif /* __STM32F4xx_IT_H */
+36
View File
@@ -0,0 +1,36 @@
#ifndef __TRANSFER_H__
#define __TRANSFER_H__
#include "bsp_common.h"
/* 是否使能断帧检测 */
#define DT_ENABLE_BROKEN_FRAME_DETECT 0
#define BROKEN_FRAME_INTERVAL_TIME 100 /* 断帧间隔时间判断,单位 ms */
typedef enum {
X_RESULT_RECV_FRAME = 0x00, /* 收到了一帧数据 */
X_RESULT_NO_DATA = 0x01, /* 未收到数据 */
X_RESULT_JUST_RECV = 0x02, /* 刚收到一帧数据(可能是断帧) */
X_RESULT_WAIT_DECTECT = 0x03 /* 等待断帧判断 */
} exRESULT;
struct transfer_t {
uint8_t if_id;
uint8_t *rx_buff;
uint16_t *rx_len;
uint32_t rx_buff_size;
};
extern void DT_Init (struct transfer_t *xfer, uint8_t if_id, uint8_t *buff, uint16_t *len, uint32_t buff_size);
extern void DT_Send (struct transfer_t *xfer, uint8_t *data, uint32_t len);
extern exRESULT DT_PollingReceive (struct transfer_t *xfer);
#endif /* __TRANSFER_H__ */
+13
View File
@@ -0,0 +1,13 @@
#ifndef __UTILS_H__
#define __UTILS_H__
#include <stdint.h>
extern int hex_printf (const uint8_t *buff, int count);
extern uint16_t crc16_xmodem (uint8_t *data, uint16_t length);
extern uint32_t crc32_step (uint32_t in_crc, const void *buf, uint32_t size);
#endif
+99
View File
@@ -0,0 +1,99 @@
#ifndef __YMODEM_H__
#define __YMODEM_H__
#include "bsp_common.h"
#include "firmware.h"
/* YModem 协议 */
#define YMODEM_SOH 0x01
#define YMODEM_STX 0x02
#define YMODEM_EOT 0x04
#define YMODEM_ACK 0x06
#define YMODEM_NAK 0x15
#define YMODEM_CAN 0x18 // graceful abort: two CAN (0x18)
#define YMODEM_FRAME_FIXED_LEN (5)
#define YMODEM_SOH_DATA_LEN (128)
#define YMODEM_STX_DATA_LEN (1024)
#define YMODEM_SOH_FRAME_LEN (YMODEM_FRAME_FIXED_LEN + YMODEM_SOH_DATA_LEN)
#define YMODEM_STX_FRAME_LEN (YMODEM_FRAME_FIXED_LEN + YMODEM_STX_DATA_LEN)
#define YMODEM_C 'C'
/* 协议包数据最大长度定义,因以下两个宏定义在 app.c 中也使用,因此不建议修改宏定义名称,更改宏定义内容即可 */
#define YM_BODY_SIZE_MAX YMODEM_STX_DATA_LEN
#define YM_MSG_SIZE_MAX YMODEM_STX_FRAME_LEN
typedef enum {
YMODEM_FLOW_NONE = 0x00,
YMODEM_FLOW_START,
YMODEM_FLOW_FIRST_EOT,
YMODEM_FLOW_SECOND_EOT,
YMODEM_FLOW_ASK,
YMODEM_FLOW_SUCCESS,
YMODEM_FLOW_FAILED,
YMODEM_FLOW_CANCEL
} eYmFLOW;
#pragma pack(1)
union message_raw_t {
uint8_t raw_data[YM_MSG_SIZE_MAX]; /* 数据缓存池,接收到来自上位机的原始数据 */
struct {
uint8_t header; /* start of header */
uint8_t pkt_num; /* packet number */
uint8_t not_pkt_num; /* the invert of packet number's bit */
uint8_t data[]; /* packet data */
} pkg;
};
#pragma pack()
/* 协议包含的指令 */
typedef enum {
YM_CMD_NONE = 0x00,
YM_CMD_SOH = YMODEM_SOH,
YM_CMD_STX = YMODEM_STX,
YM_CMD_EOT = YMODEM_EOT,
YM_CMD_CAN = YMODEM_CAN
} eYmCMD;
/* 协议指令的执行结果 */
typedef enum {
YM_RESULT_OK = 0x00, /* 执行成功 */
YM_RESULT_PROCESS = 0x01, /* 执行中 */
YM_RESULT_FAILED = 0x02, /* 执行失败,重试 */
YM_RESULT_CANCEL = 0x03 /* 执行失败,取消传输 */
} eRESULT;
/* 对协议析构层的配置选项 */
typedef enum {
YM_MODE_NONE = 0x00,
YM_MODE_RESET = 0x01,
YM_MODE_RECV = 0x02
} eYmMODE;
/* 需要打包发送至上位机的数据 */
struct tx_raw_t {
uint8_t response;
};
/* typedef of function */
typedef void (*ymSend)(uint8_t *data, uint16_t len, uint32_t timeout);
typedef void (*ymPrepareCallback)(eYmCMD cmd, uint8_t *data, uint16_t data_len);
typedef void (*ymReplyCallback)(eYmCMD cmd, eRESULT *result, uint8_t *data, uint16_t *data_len);
/* 函数定义 */
extern void ymodem_init (ymSend Send,
ymPrepareCallback PrepareCallback,
ymReplyCallback Set_ResponseInfo);
extern eErrCode ymodemHandler (uint8_t *data, uint16_t len);
extern void ymodemConfig (eYmMODE para, void *value);
#endif /* __YMODEM_H__ */
+202
View File
@@ -0,0 +1,202 @@
#include <stdio.h>
#include "app_config.h"
#include "main.h"
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
DMA_HandleTypeDef hdma_usart1_rx;
DMA_HandleTypeDef hdma_usart2_rx;
extern void System_Init(void);
extern void APP_Init(void);
extern void APP_Running(void);
#if defined(STM32F405xx)
void SystemClock_Config (void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 4;
RCC_OscInitStruct.PLL.PLLN = 168;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
}
#elif defined(STM32F411xE)||defined(STM32F401xC)
void SystemClock_Config (void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 100;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3);
}
#endif
static void MX_GPIO_Init (void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
#if (ENABLE_FACTORY_FIRMWARE_BUTTON)
__HAL_RCC_GPIOE_CLK_ENABLE();
GPIO_InitStruct.Pin = KEY0_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(KEY0_GPIO_Port, &GPIO_InitStruct);
#endif
GPIO_InitStruct.Pin = LED0_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(LED0_GPIO_Port, &GPIO_InitStruct);
HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_SET);
}
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
// usart1 rx
HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
// usart2 rx
HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn);
}
void MX_DMA_DeInit (void)
{
HAL_DMA_DeInit(&hdma_usart1_rx);
HAL_DMA_DeInit(&hdma_usart2_rx);
}
static void MX_USART_Init (void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart1);
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart2);
}
void MX_USART_DeInit (void)
{
HAL_UART_DeInit(&huart1);
HAL_UART_DeInit(&huart2);
}
int main (void)
{
HAL_Init();
SystemClock_Config();
System_Init();
MX_GPIO_Init();
MX_DMA_Init();
MX_USART_Init();
printf("\r\n\r\n========================================\r\n");
printf("\t%s boot V%d.%d.%d\r\n", NAME_CHIP,
VERSION_MAIN, VERSION_SUB, VERSION_FIX);
printf("\tbuilt @ %s\r\n", BUILD_TIMESTAMP);
printf("Chip UID: %08X - %08X - %08X\r\n",
HAL_GetUIDw0(), HAL_GetUIDw1(), HAL_GetUIDw2());
printf("========================================\r\n");
APP_Init();
while (1) {
APP_Running();
}
return -1;
}
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
int fgetc(FILE * f)
{
uint8_t ch = 0;
HAL_UART_Receive(&huart1,&ch, 1, 0xffff);
return ch;
}
+95
View File
@@ -0,0 +1,95 @@
#include "main.h"
extern DMA_HandleTypeDef hdma_usart1_rx;
extern DMA_HandleTypeDef hdma_usart2_rx;
void HAL_MspInit (void)
{
__HAL_RCC_SYSCFG_CLK_ENABLE();
__HAL_RCC_PWR_CLK_ENABLE();
}
void HAL_UART_MspInit (UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if (huart->Instance == USART1) {
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
// PA9 ------> USART1_TX
// PA10 ------> USART1_RX
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
hdma_usart1_rx.Instance = DMA2_Stream2;
hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4;
hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart1_rx.Init.Mode = DMA_CIRCULAR;
hdma_usart1_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&hdma_usart1_rx);
__HAL_LINKDMA(huart, hdmarx, hdma_usart1_rx);
HAL_NVIC_SetPriority(USART1_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
} else if (huart->Instance == USART2) {
__HAL_RCC_USART2_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
// PA2 ------> USART2_TX
// PA3 ------> USART2_RX
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
hdma_usart2_rx.Instance = DMA1_Stream5;
hdma_usart2_rx.Init.Channel = DMA_CHANNEL_4;
hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart2_rx.Init.Mode = DMA_CIRCULAR;
hdma_usart2_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
hdma_usart2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&hdma_usart2_rx);
__HAL_LINKDMA(huart, hdmarx, hdma_usart2_rx);
HAL_NVIC_SetPriority(USART2_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(USART2_IRQn);
}
}
void HAL_UART_MspDeInit (UART_HandleTypeDef* huart)
{
if (huart->Instance == USART1) {
__HAL_RCC_USART1_CLK_DISABLE();
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
HAL_DMA_DeInit(huart->hdmarx);
HAL_NVIC_DisableIRQ(USART1_IRQn);
} else if (huart->Instance == USART2) {
__HAL_RCC_USART2_CLK_DISABLE();
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);
HAL_DMA_DeInit(huart->hdmarx);
HAL_NVIC_DisableIRQ(USART2_IRQn);
}
}
+204
View File
@@ -0,0 +1,204 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f4xx_it.c
* @brief Interrupt Service Routines.
******************************************************************************
* @attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/* External variables --------------------------------------------------------*/
/* USER CODE BEGIN EV */
/* USER CODE END EV */
/******************************************************************************/
/* Cortex-M4 Processor Interruption and Exception Handlers */
/******************************************************************************/
/**
* @brief This function handles Non maskable interrupt.
*/
void NMI_Handler(void)
{
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
/* USER CODE END NonMaskableInt_IRQn 0 */
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
while (1)
{
}
/* USER CODE END NonMaskableInt_IRQn 1 */
}
/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
}
/**
* @brief This function handles Memory management fault.
*/
void MemManage_Handler(void)
{
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
/* USER CODE END MemoryManagement_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
/* USER CODE END W1_MemoryManagement_IRQn 0 */
}
}
/**
* @brief This function handles Pre-fetch fault, memory access fault.
*/
void BusFault_Handler(void)
{
/* USER CODE BEGIN BusFault_IRQn 0 */
/* USER CODE END BusFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_BusFault_IRQn 0 */
/* USER CODE END W1_BusFault_IRQn 0 */
}
}
/**
* @brief This function handles Undefined instruction or illegal state.
*/
void UsageFault_Handler(void)
{
/* USER CODE BEGIN UsageFault_IRQn 0 */
/* USER CODE END UsageFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_UsageFault_IRQn 0 */
/* USER CODE END W1_UsageFault_IRQn 0 */
}
}
/**
* @brief This function handles System service call via SWI instruction.
*/
void SVC_Handler(void)
{
/* USER CODE BEGIN SVCall_IRQn 0 */
/* USER CODE END SVCall_IRQn 0 */
/* USER CODE BEGIN SVCall_IRQn 1 */
/* USER CODE END SVCall_IRQn 1 */
}
/**
* @brief This function handles Debug monitor.
*/
void DebugMon_Handler(void)
{
/* USER CODE BEGIN DebugMonitor_IRQn 0 */
/* USER CODE END DebugMonitor_IRQn 0 */
/* USER CODE BEGIN DebugMonitor_IRQn 1 */
/* USER CODE END DebugMonitor_IRQn 1 */
}
/**
* @brief This function handles Pendable request for system service.
*/
void PendSV_Handler(void)
{
/* USER CODE BEGIN PendSV_IRQn 0 */
/* USER CODE END PendSV_IRQn 0 */
/* USER CODE BEGIN PendSV_IRQn 1 */
/* USER CODE END PendSV_IRQn 1 */
}
/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
extern void drv_timer_handler (uint8_t ms);
drv_timer_handler(1);
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
/* USER CODE END SysTick_IRQn 1 */
}
/******************************************************************************/
/* STM32F4xx Peripheral Interrupt Handlers */
/* Add here the Interrupt Handlers for the used peripherals. */
/* For the available peripheral interrupt handler names, */
/* please refer to the startup file (startup_stm32f4xx.s). */
/******************************************************************************/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
+747
View File
@@ -0,0 +1,747 @@
/**
******************************************************************************
* @file system_stm32f4xx.c
* @author MCD Application Team
* @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File.
*
* This file provides two functions and one global variable to be called from
* user application:
* - SystemInit(): This function is called at startup just after reset and
* before branch to main program. This call is made inside
* the "startup_stm32f4xx.s" file.
*
* - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
* by the user application to setup the SysTick
* timer or configure other parameters.
*
* - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
* be called whenever the core clock is changed
* during program execution.
*
*
******************************************************************************
* @attention
*
* Copyright (c) 2017 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/** @addtogroup CMSIS
* @{
*/
/** @addtogroup stm32f4xx_system
* @{
*/
/** @addtogroup STM32F4xx_System_Private_Includes
* @{
*/
#include "stm32f4xx.h"
#if !defined (HSE_VALUE)
#define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined (HSI_VALUE)
#define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Private_Defines
* @{
*/
/************************* Miscellaneous Configuration ************************/
/*!< Uncomment the following line if you need to use external SRAM or SDRAM as data memory */
#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\
|| defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|| defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx)
/* #define DATA_IN_ExtSRAM */
#endif /* STM32F40xxx || STM32F41xxx || STM32F42xxx || STM32F43xxx || STM32F469xx || STM32F479xx ||\
STM32F412Zx || STM32F412Vx */
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|| defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx)
/* #define DATA_IN_ExtSDRAM */
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx ||\
STM32F479xx */
/* Note: Following vector table addresses must be defined in line with linker
configuration. */
/*!< Uncomment the following line if you need to relocate the vector table
anywhere in Flash or Sram, else the vector table is kept at the automatic
remap of boot address selected */
/* #define USER_VECT_TAB_ADDRESS */
#if defined(USER_VECT_TAB_ADDRESS)
/*!< Uncomment the following line if you need to relocate your vector Table
in Sram else user remap will be done in Flash. */
/* #define VECT_TAB_SRAM */
#if defined(VECT_TAB_SRAM)
#define VECT_TAB_BASE_ADDRESS SRAM_BASE /*!< Vector Table base address field.
This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
#else
#define VECT_TAB_BASE_ADDRESS FLASH_BASE /*!< Vector Table base address field.
This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
#endif /* VECT_TAB_SRAM */
#endif /* USER_VECT_TAB_ADDRESS */
/******************************************************************************/
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Private_Macros
* @{
*/
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Private_Variables
* @{
*/
/* This variable is updated in three ways:
1) by calling CMSIS function SystemCoreClockUpdate()
2) by calling HAL API function HAL_RCC_GetHCLKFreq()
3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
Note: If you use this function to configure the system clock; then there
is no need to call the 2 first functions listed above, since SystemCoreClock
variable is updated automatically.
*/
uint32_t SystemCoreClock = 16000000;
const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Private_FunctionPrototypes
* @{
*/
#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
static void SystemInit_ExtMemCtl(void);
#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Private_Functions
* @{
*/
/**
* @brief Setup the microcontroller system
* Initialize the FPU setting, vector table location and External memory
* configuration.
* @param None
* @retval None
*/
void SystemInit(void)
{
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
/* Configure the Vector Table location -------------------------------------*/
#if defined(USER_VECT_TAB_ADDRESS)
SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#endif /* USER_VECT_TAB_ADDRESS */
}
/**
* @brief Update SystemCoreClock variable according to Clock Register Values.
* The SystemCoreClock variable contains the core clock (HCLK), it can
* be used by the user application to setup the SysTick timer or configure
* other parameters.
*
* @note Each time the core clock (HCLK) changes, this function must be called
* to update SystemCoreClock variable value. Otherwise, any configuration
* based on this variable will be incorrect.
*
* @note - The system frequency computed by this function is not the real
* frequency in the chip. It is calculated based on the predefined
* constant and the selected clock source:
*
* - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
*
* - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
*
* - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
* or HSI_VALUE(*) multiplied/divided by the PLL factors.
*
* (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value
* 16 MHz) but the real value may vary depending on the variations
* in voltage and temperature.
*
* (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file (its value
* depends on the application requirements), user has to ensure that HSE_VALUE
* is same as the real frequency of the crystal used. Otherwise, this function
* may have wrong result.
*
* - The result of this function could be not correct when using fractional
* value for HSE crystal.
*
* @param None
* @retval None
*/
void SystemCoreClockUpdate(void)
{
uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2;
/* Get SYSCLK source -------------------------------------------------------*/
tmp = RCC->CFGR & RCC_CFGR_SWS;
switch (tmp)
{
case 0x00: /* HSI used as system clock source */
SystemCoreClock = HSI_VALUE;
break;
case 0x04: /* HSE used as system clock source */
SystemCoreClock = HSE_VALUE;
break;
case 0x08: /* PLL used as system clock source */
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N
SYSCLK = PLL_VCO / PLL_P
*/
pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22;
pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
if (pllsource != 0)
{
/* HSE used as PLL clock source */
pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
}
else
{
/* HSI used as PLL clock source */
pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
}
pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2;
SystemCoreClock = pllvco/pllp;
break;
default:
SystemCoreClock = HSI_VALUE;
break;
}
/* Compute HCLK frequency --------------------------------------------------*/
/* Get HCLK prescaler */
tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
/* HCLK frequency */
SystemCoreClock >>= tmp;
}
#if defined (DATA_IN_ExtSRAM) && defined (DATA_IN_ExtSDRAM)
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|| defined(STM32F469xx) || defined(STM32F479xx)
/**
* @brief Setup the external memory controller.
* Called in startup_stm32f4xx.s before jump to main.
* This function configures the external memories (SRAM/SDRAM)
* This SRAM/SDRAM will be used as program data memory (including heap and stack).
* @param None
* @retval None
*/
void SystemInit_ExtMemCtl(void)
{
__IO uint32_t tmp = 0x00;
register uint32_t tmpreg = 0, timeout = 0xFFFF;
register __IO uint32_t index;
/* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface clock */
RCC->AHB1ENR |= 0x000001F8;
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);
/* Connect PDx pins to FMC Alternate function */
GPIOD->AFR[0] = 0x00CCC0CC;
GPIOD->AFR[1] = 0xCCCCCCCC;
/* Configure PDx pins in Alternate function mode */
GPIOD->MODER = 0xAAAA0A8A;
/* Configure PDx pins speed to 100 MHz */
GPIOD->OSPEEDR = 0xFFFF0FCF;
/* Configure PDx pins Output type to push-pull */
GPIOD->OTYPER = 0x00000000;
/* No pull-up, pull-down for PDx pins */
GPIOD->PUPDR = 0x00000000;
/* Connect PEx pins to FMC Alternate function */
GPIOE->AFR[0] = 0xC00CC0CC;
GPIOE->AFR[1] = 0xCCCCCCCC;
/* Configure PEx pins in Alternate function mode */
GPIOE->MODER = 0xAAAA828A;
/* Configure PEx pins speed to 100 MHz */
GPIOE->OSPEEDR = 0xFFFFC3CF;
/* Configure PEx pins Output type to push-pull */
GPIOE->OTYPER = 0x00000000;
/* No pull-up, pull-down for PEx pins */
GPIOE->PUPDR = 0x00000000;
/* Connect PFx pins to FMC Alternate function */
GPIOF->AFR[0] = 0xCCCCCCCC;
GPIOF->AFR[1] = 0xCCCCCCCC;
/* Configure PFx pins in Alternate function mode */
GPIOF->MODER = 0xAA800AAA;
/* Configure PFx pins speed to 50 MHz */
GPIOF->OSPEEDR = 0xAA800AAA;
/* Configure PFx pins Output type to push-pull */
GPIOF->OTYPER = 0x00000000;
/* No pull-up, pull-down for PFx pins */
GPIOF->PUPDR = 0x00000000;
/* Connect PGx pins to FMC Alternate function */
GPIOG->AFR[0] = 0xCCCCCCCC;
GPIOG->AFR[1] = 0xCCCCCCCC;
/* Configure PGx pins in Alternate function mode */
GPIOG->MODER = 0xAAAAAAAA;
/* Configure PGx pins speed to 50 MHz */
GPIOG->OSPEEDR = 0xAAAAAAAA;
/* Configure PGx pins Output type to push-pull */
GPIOG->OTYPER = 0x00000000;
/* No pull-up, pull-down for PGx pins */
GPIOG->PUPDR = 0x00000000;
/* Connect PHx pins to FMC Alternate function */
GPIOH->AFR[0] = 0x00C0CC00;
GPIOH->AFR[1] = 0xCCCCCCCC;
/* Configure PHx pins in Alternate function mode */
GPIOH->MODER = 0xAAAA08A0;
/* Configure PHx pins speed to 50 MHz */
GPIOH->OSPEEDR = 0xAAAA08A0;
/* Configure PHx pins Output type to push-pull */
GPIOH->OTYPER = 0x00000000;
/* No pull-up, pull-down for PHx pins */
GPIOH->PUPDR = 0x00000000;
/* Connect PIx pins to FMC Alternate function */
GPIOI->AFR[0] = 0xCCCCCCCC;
GPIOI->AFR[1] = 0x00000CC0;
/* Configure PIx pins in Alternate function mode */
GPIOI->MODER = 0x0028AAAA;
/* Configure PIx pins speed to 50 MHz */
GPIOI->OSPEEDR = 0x0028AAAA;
/* Configure PIx pins Output type to push-pull */
GPIOI->OTYPER = 0x00000000;
/* No pull-up, pull-down for PIx pins */
GPIOI->PUPDR = 0x00000000;
/*-- FMC Configuration -------------------------------------------------------*/
/* Enable the FMC interface clock */
RCC->AHB3ENR |= 0x00000001;
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
FMC_Bank5_6->SDCR[0] = 0x000019E4;
FMC_Bank5_6->SDTR[0] = 0x01115351;
/* SDRAM initialization sequence */
/* Clock enable command */
FMC_Bank5_6->SDCMR = 0x00000011;
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* Delay */
for (index = 0; index<1000; index++);
/* PALL command */
FMC_Bank5_6->SDCMR = 0x00000012;
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
timeout = 0xFFFF;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* Auto refresh command */
FMC_Bank5_6->SDCMR = 0x00000073;
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
timeout = 0xFFFF;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* MRD register program */
FMC_Bank5_6->SDCMR = 0x00046014;
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
timeout = 0xFFFF;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* Set refresh count */
tmpreg = FMC_Bank5_6->SDRTR;
FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1));
/* Disable write protection */
tmpreg = FMC_Bank5_6->SDCR[0];
FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF);
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
/* Configure and enable Bank1_SRAM2 */
FMC_Bank1->BTCR[2] = 0x00001011;
FMC_Bank1->BTCR[3] = 0x00000201;
FMC_Bank1E->BWTR[2] = 0x0fffffff;
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */
#if defined(STM32F469xx) || defined(STM32F479xx)
/* Configure and enable Bank1_SRAM2 */
FMC_Bank1->BTCR[2] = 0x00001091;
FMC_Bank1->BTCR[3] = 0x00110212;
FMC_Bank1E->BWTR[2] = 0x0fffffff;
#endif /* STM32F469xx || STM32F479xx */
(void)(tmp);
}
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */
#elif defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
/**
* @brief Setup the external memory controller.
* Called in startup_stm32f4xx.s before jump to main.
* This function configures the external memories (SRAM/SDRAM)
* This SRAM/SDRAM will be used as program data memory (including heap and stack).
* @param None
* @retval None
*/
void SystemInit_ExtMemCtl(void)
{
__IO uint32_t tmp = 0x00;
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|| defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx)
#if defined (DATA_IN_ExtSDRAM)
register uint32_t tmpreg = 0, timeout = 0xFFFF;
register __IO uint32_t index;
#if defined(STM32F446xx)
/* Enable GPIOA, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG interface
clock */
RCC->AHB1ENR |= 0x0000007D;
#else
/* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface
clock */
RCC->AHB1ENR |= 0x000001F8;
#endif /* STM32F446xx */
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);
#if defined(STM32F446xx)
/* Connect PAx pins to FMC Alternate function */
GPIOA->AFR[0] |= 0xC0000000;
GPIOA->AFR[1] |= 0x00000000;
/* Configure PDx pins in Alternate function mode */
GPIOA->MODER |= 0x00008000;
/* Configure PDx pins speed to 50 MHz */
GPIOA->OSPEEDR |= 0x00008000;
/* Configure PDx pins Output type to push-pull */
GPIOA->OTYPER |= 0x00000000;
/* No pull-up, pull-down for PDx pins */
GPIOA->PUPDR |= 0x00000000;
/* Connect PCx pins to FMC Alternate function */
GPIOC->AFR[0] |= 0x00CC0000;
GPIOC->AFR[1] |= 0x00000000;
/* Configure PDx pins in Alternate function mode */
GPIOC->MODER |= 0x00000A00;
/* Configure PDx pins speed to 50 MHz */
GPIOC->OSPEEDR |= 0x00000A00;
/* Configure PDx pins Output type to push-pull */
GPIOC->OTYPER |= 0x00000000;
/* No pull-up, pull-down for PDx pins */
GPIOC->PUPDR |= 0x00000000;
#endif /* STM32F446xx */
/* Connect PDx pins to FMC Alternate function */
GPIOD->AFR[0] = 0x000000CC;
GPIOD->AFR[1] = 0xCC000CCC;
/* Configure PDx pins in Alternate function mode */
GPIOD->MODER = 0xA02A000A;
/* Configure PDx pins speed to 50 MHz */
GPIOD->OSPEEDR = 0xA02A000A;
/* Configure PDx pins Output type to push-pull */
GPIOD->OTYPER = 0x00000000;
/* No pull-up, pull-down for PDx pins */
GPIOD->PUPDR = 0x00000000;
/* Connect PEx pins to FMC Alternate function */
GPIOE->AFR[0] = 0xC00000CC;
GPIOE->AFR[1] = 0xCCCCCCCC;
/* Configure PEx pins in Alternate function mode */
GPIOE->MODER = 0xAAAA800A;
/* Configure PEx pins speed to 50 MHz */
GPIOE->OSPEEDR = 0xAAAA800A;
/* Configure PEx pins Output type to push-pull */
GPIOE->OTYPER = 0x00000000;
/* No pull-up, pull-down for PEx pins */
GPIOE->PUPDR = 0x00000000;
/* Connect PFx pins to FMC Alternate function */
GPIOF->AFR[0] = 0xCCCCCCCC;
GPIOF->AFR[1] = 0xCCCCCCCC;
/* Configure PFx pins in Alternate function mode */
GPIOF->MODER = 0xAA800AAA;
/* Configure PFx pins speed to 50 MHz */
GPIOF->OSPEEDR = 0xAA800AAA;
/* Configure PFx pins Output type to push-pull */
GPIOF->OTYPER = 0x00000000;
/* No pull-up, pull-down for PFx pins */
GPIOF->PUPDR = 0x00000000;
/* Connect PGx pins to FMC Alternate function */
GPIOG->AFR[0] = 0xCCCCCCCC;
GPIOG->AFR[1] = 0xCCCCCCCC;
/* Configure PGx pins in Alternate function mode */
GPIOG->MODER = 0xAAAAAAAA;
/* Configure PGx pins speed to 50 MHz */
GPIOG->OSPEEDR = 0xAAAAAAAA;
/* Configure PGx pins Output type to push-pull */
GPIOG->OTYPER = 0x00000000;
/* No pull-up, pull-down for PGx pins */
GPIOG->PUPDR = 0x00000000;
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|| defined(STM32F469xx) || defined(STM32F479xx)
/* Connect PHx pins to FMC Alternate function */
GPIOH->AFR[0] = 0x00C0CC00;
GPIOH->AFR[1] = 0xCCCCCCCC;
/* Configure PHx pins in Alternate function mode */
GPIOH->MODER = 0xAAAA08A0;
/* Configure PHx pins speed to 50 MHz */
GPIOH->OSPEEDR = 0xAAAA08A0;
/* Configure PHx pins Output type to push-pull */
GPIOH->OTYPER = 0x00000000;
/* No pull-up, pull-down for PHx pins */
GPIOH->PUPDR = 0x00000000;
/* Connect PIx pins to FMC Alternate function */
GPIOI->AFR[0] = 0xCCCCCCCC;
GPIOI->AFR[1] = 0x00000CC0;
/* Configure PIx pins in Alternate function mode */
GPIOI->MODER = 0x0028AAAA;
/* Configure PIx pins speed to 50 MHz */
GPIOI->OSPEEDR = 0x0028AAAA;
/* Configure PIx pins Output type to push-pull */
GPIOI->OTYPER = 0x00000000;
/* No pull-up, pull-down for PIx pins */
GPIOI->PUPDR = 0x00000000;
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */
/*-- FMC Configuration -------------------------------------------------------*/
/* Enable the FMC interface clock */
RCC->AHB3ENR |= 0x00000001;
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
/* Configure and enable SDRAM bank1 */
#if defined(STM32F446xx)
FMC_Bank5_6->SDCR[0] = 0x00001954;
#else
FMC_Bank5_6->SDCR[0] = 0x000019E4;
#endif /* STM32F446xx */
FMC_Bank5_6->SDTR[0] = 0x01115351;
/* SDRAM initialization sequence */
/* Clock enable command */
FMC_Bank5_6->SDCMR = 0x00000011;
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* Delay */
for (index = 0; index<1000; index++);
/* PALL command */
FMC_Bank5_6->SDCMR = 0x00000012;
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
timeout = 0xFFFF;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* Auto refresh command */
#if defined(STM32F446xx)
FMC_Bank5_6->SDCMR = 0x000000F3;
#else
FMC_Bank5_6->SDCMR = 0x00000073;
#endif /* STM32F446xx */
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
timeout = 0xFFFF;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* MRD register program */
#if defined(STM32F446xx)
FMC_Bank5_6->SDCMR = 0x00044014;
#else
FMC_Bank5_6->SDCMR = 0x00046014;
#endif /* STM32F446xx */
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
timeout = 0xFFFF;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* Set refresh count */
tmpreg = FMC_Bank5_6->SDRTR;
#if defined(STM32F446xx)
FMC_Bank5_6->SDRTR = (tmpreg | (0x0000050C<<1));
#else
FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1));
#endif /* STM32F446xx */
/* Disable write protection */
tmpreg = FMC_Bank5_6->SDCR[0];
FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF);
#endif /* DATA_IN_ExtSDRAM */
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */
#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\
|| defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|| defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx)
#if defined(DATA_IN_ExtSRAM)
/*-- GPIOs Configuration -----------------------------------------------------*/
/* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */
RCC->AHB1ENR |= 0x00000078;
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN);
/* Connect PDx pins to FMC Alternate function */
GPIOD->AFR[0] = 0x00CCC0CC;
GPIOD->AFR[1] = 0xCCCCCCCC;
/* Configure PDx pins in Alternate function mode */
GPIOD->MODER = 0xAAAA0A8A;
/* Configure PDx pins speed to 100 MHz */
GPIOD->OSPEEDR = 0xFFFF0FCF;
/* Configure PDx pins Output type to push-pull */
GPIOD->OTYPER = 0x00000000;
/* No pull-up, pull-down for PDx pins */
GPIOD->PUPDR = 0x00000000;
/* Connect PEx pins to FMC Alternate function */
GPIOE->AFR[0] = 0xC00CC0CC;
GPIOE->AFR[1] = 0xCCCCCCCC;
/* Configure PEx pins in Alternate function mode */
GPIOE->MODER = 0xAAAA828A;
/* Configure PEx pins speed to 100 MHz */
GPIOE->OSPEEDR = 0xFFFFC3CF;
/* Configure PEx pins Output type to push-pull */
GPIOE->OTYPER = 0x00000000;
/* No pull-up, pull-down for PEx pins */
GPIOE->PUPDR = 0x00000000;
/* Connect PFx pins to FMC Alternate function */
GPIOF->AFR[0] = 0x00CCCCCC;
GPIOF->AFR[1] = 0xCCCC0000;
/* Configure PFx pins in Alternate function mode */
GPIOF->MODER = 0xAA000AAA;
/* Configure PFx pins speed to 100 MHz */
GPIOF->OSPEEDR = 0xFF000FFF;
/* Configure PFx pins Output type to push-pull */
GPIOF->OTYPER = 0x00000000;
/* No pull-up, pull-down for PFx pins */
GPIOF->PUPDR = 0x00000000;
/* Connect PGx pins to FMC Alternate function */
GPIOG->AFR[0] = 0x00CCCCCC;
GPIOG->AFR[1] = 0x000000C0;
/* Configure PGx pins in Alternate function mode */
GPIOG->MODER = 0x00085AAA;
/* Configure PGx pins speed to 100 MHz */
GPIOG->OSPEEDR = 0x000CAFFF;
/* Configure PGx pins Output type to push-pull */
GPIOG->OTYPER = 0x00000000;
/* No pull-up, pull-down for PGx pins */
GPIOG->PUPDR = 0x00000000;
/*-- FMC/FSMC Configuration --------------------------------------------------*/
/* Enable the FMC/FSMC interface clock */
RCC->AHB3ENR |= 0x00000001;
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
/* Configure and enable Bank1_SRAM2 */
FMC_Bank1->BTCR[2] = 0x00001011;
FMC_Bank1->BTCR[3] = 0x00000201;
FMC_Bank1E->BWTR[2] = 0x0fffffff;
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */
#if defined(STM32F469xx) || defined(STM32F479xx)
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
/* Configure and enable Bank1_SRAM2 */
FMC_Bank1->BTCR[2] = 0x00001091;
FMC_Bank1->BTCR[3] = 0x00110212;
FMC_Bank1E->BWTR[2] = 0x0fffffff;
#endif /* STM32F469xx || STM32F479xx */
#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx)\
|| defined(STM32F412Zx) || defined(STM32F412Vx)
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FSMCEN);
/* Configure and enable Bank1_SRAM2 */
FSMC_Bank1->BTCR[2] = 0x00001011;
FSMC_Bank1->BTCR[3] = 0x00000201;
FSMC_Bank1E->BWTR[2] = 0x0FFFFFFF;
#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F412Zx || STM32F412Vx */
#endif /* DATA_IN_ExtSRAM */
#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx ||\
STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx */
(void)(tmp);
}
#endif /* DATA_IN_ExtSRAM && DATA_IN_ExtSDRAM */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
+1507
View File
File diff suppressed because it is too large Load Diff
+22
View File
@@ -0,0 +1,22 @@
mainmenu "RT-Thread Configuration"
BSP_DIR := .
RTT_DIR := ../../rt-thread
PKGS_DIR := packages
config SOC_STM32F405RG
bool
select SOC_SERIES_STM32F4
select RT_USING_COMPONENTS_INIT
select RT_USING_USER_MAIN
default y
source "$(RTT_DIR)/Kconfig"
osource "$PKGS_DIR/Kconfig"
rsource "$(RTT_DIR)/bsp/stm32/libraries/Kconfig"
if !RT_USING_NANO
rsource "board/Kconfig"
endif
+20
View File
@@ -0,0 +1,20 @@
# for module compiling
import os
Import('RTT_ROOT')
Import('env')
from building import *
cwd = GetCurrentDir()
objs = []
list = os.listdir(cwd)
env.Append(CPPDEFINES = ['STM32F405xx'])
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(d, 'SConscript'))
objs = objs + SConscript(os.path.join(cwd, '../../lib/SConscript'))
Return('objs')
+60
View File
@@ -0,0 +1,60 @@
import os
import sys
import rtconfig
if os.getenv('RTT_ROOT'):
RTT_ROOT = os.getenv('RTT_ROOT')
else:
RTT_ROOT = os.path.normpath(os.getcwd() + '/../../rt-thread')
print("RTT_ROOT : " + RTT_ROOT)
sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
try:
from building import *
except:
print('Cannot found RT-Thread root directory, please check RTT_ROOT')
print(RTT_ROOT)
exit(-1)
TARGET = 'chrg.' + rtconfig.TARGET_EXT
DefaultEnvironment(tools=[])
env = Environment(tools = ['mingw'],
AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS,
AR = rtconfig.AR, ARFLAGS = '-rc',
CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS,
LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
if rtconfig.PLATFORM in ['iccarm']:
env.Replace(CCCOM = ['$CC $CFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES'])
env.Replace(ARFLAGS = [''])
env.Replace(LINKCOM = env["LINKCOM"] + ' --map chrg.map')
Export('env')
Export('RTT_ROOT')
Export('rtconfig')
SDK_ROOT = os.path.abspath('./')
print("SDK_ROOT : " + SDK_ROOT)
if os.path.exists(SDK_ROOT + '/libraries'):
libraries_path_prefix = SDK_ROOT + '/libraries'
else:
libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/../rt-thread/bsp/stm32/libraries'
print("libraries_path_prefix : " + libraries_path_prefix)
# prepare building environment
objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False)
rtconfig.BSP_LIBRARY_TYPE = None
# include drivers
objs.extend(SConscript(os.path.join(libraries_path_prefix, 'HAL_Drivers', 'SConscript'),variant_dir='build/libraries/'+'HAL_Drivers', duplicate=0))
# make a building
DoBuilding(TARGET, objs)
+15
View File
@@ -0,0 +1,15 @@
from building import *
import os
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
list = os.listdir(cwd)
for item in list:
if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
group = group + SConscript(os.path.join(item, 'SConscript'))
Return('group')
+41
View File
@@ -0,0 +1,41 @@
#include "shell.h"
#include <board.h>
#include <rtthread.h>
#include <drv_gpio.h>
#ifndef RT_USING_NANO
#include <rtdevice.h>
#endif /* RT_USING_NANO */
/* defined the LED0 pin: PC4 */
/* LEDs: PC4, PA8, PC5, PA10 */
#define LED0_PIN GET_PIN(A, 8)
void show_app_version (void)
{
rt_kprintf("\r\n\r\n============================================\r\n");
rt_kprintf("\tcharger control via RT-Thread v%d.%d.%d\r\n",
RT_VERSION_MAJOR, RT_VERSION_MINOR, RT_VERSION_PATCH);
rt_kprintf("\tbuilt @ %s, %s\r\n", __DATE__, __TIME__);
rt_kprintf("Chip UID: %08X - %08X - %08X\r\n",
HAL_GetUIDw0(), HAL_GetUIDw1(), HAL_GetUIDw2());
rt_kprintf("============================================\r\n");
}
int main(void)
{
#if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH)
finsh_set_prompt("chrg ");
#endif
/* set LED0 pin mode to output */
rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
while (1)
{
rt_pin_write(LED0_PIN, PIN_HIGH);
rt_thread_mdelay(500);
rt_pin_write(LED0_PIN, PIN_LOW);
rt_thread_mdelay(500);
}
}
+6
View File
@@ -0,0 +1,6 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config
+17
View File
@@ -0,0 +1,17 @@
[PreviousGenFiles]
HeaderPath=D:/mywork/stm32f405/board/CubeMX_Config/Inc
HeaderFiles=stm32f4xx_it.h;stm32f4xx_hal_conf.h;main.h;
SourcePath=D:/mywork/stm32f405/board/CubeMX_Config/Src
SourceFiles=stm32f4xx_it.c;stm32f4xx_hal_msp.c;main.c;
[PreviousLibFiles]
LibFiles=Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h;Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h;Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h;Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h;Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f405xx.h;Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h;Drivers/CMSIS/Device/ST/STM32F4xx/Include/system_stm32f4xx.h;Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c;Drivers/CMSIS/Include/arm_common_tables.h;Drivers/CMSIS/Include/arm_const_structs.h;Drivers/CMSIS/Include/arm_math.h;Drivers/CMSIS/Include/cmsis_armcc.h;Drivers/CMSIS/Include/cmsis_armcc_V6.h;Drivers/CMSIS/Include/cmsis_gcc.h;Drivers/CMSIS/Include/core_cm0.h;Drivers/CMSIS/Include/core_cm0plus.h;Drivers/CMSIS/Include/core_cm3.h;Drivers/CMSIS/Include/core_cm4.h;Drivers/CMSIS/Include/core_cm7.h;Drivers/CMSIS/Include/core_cmFunc.h;Drivers/CMSIS/Include/core_cmInstr.h;Drivers/CMSIS/Include/core_cmSimd.h;Drivers/CMSIS/Include/core_sc000.h;Drivers/CMSIS/Include/core_sc300.h;
[PreviousUsedIarFiles]
SourceFiles=..\Src\main.c;..\Src\stm32f4xx_it.c;..\Src\stm32f4xx_hal_msp.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;../\Src/system_stm32f4xx.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;../\Src/system_stm32f4xx.c;../Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c;null;
HeaderPath=..\Drivers\STM32F4xx_HAL_Driver\Inc;..\Drivers\STM32F4xx_HAL_Driver\Inc\Legacy;..\Drivers\CMSIS\Device\ST\STM32F4xx\Include;..\Drivers\CMSIS\Include;..\Inc;
[PreviousUsedKeilFiles]
SourceFiles=..\Src\main.c;..\Src\stm32f4xx_it.c;..\Src\stm32f4xx_hal_msp.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;../\Src/system_stm32f4xx.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c;../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c;../\Src/system_stm32f4xx.c;../Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c;null;
HeaderPath=..\Drivers\STM32F4xx_HAL_Driver\Inc;..\Drivers\STM32F4xx_HAL_Driver\Inc\Legacy;..\Drivers\CMSIS\Device\ST\STM32F4xx\Include;..\Drivers\CMSIS\Include;..\Inc;
@@ -0,0 +1,110 @@
#MicroXplorer Configuration settings - do not modify
File.Version=6
KeepUserPlacement=false
Mcu.Family=STM32F4
Mcu.IP0=NVIC
Mcu.IP1=RCC
Mcu.IP2=SYS
Mcu.IP3=USART2
Mcu.IPNb=4
Mcu.Name=STM32F405RGTx
Mcu.Package=LQFP64
Mcu.Pin0=PC14-OSC32_IN
Mcu.Pin1=PC15-OSC32_OUT
Mcu.Pin2=PH0-OSC_IN
Mcu.Pin3=PH1-OSC_OUT
Mcu.Pin4=PA2
Mcu.Pin5=PA3
Mcu.Pin6=VP_SYS_VS_Systick
Mcu.PinsNb=7
Mcu.ThirdPartyNb=0
Mcu.UserConstants=
Mcu.UserName=STM32F405RGTx
MxCube.Version=5.0.0
MxDb.Version=DB.5.0.0
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false
PA2.GPIOParameters=GPIO_PuPd
PA2.GPIO_PuPd=GPIO_PULLUP
PA2.Mode=Asynchronous
PA2.Signal=USART2_TX
PA3.GPIOParameters=GPIO_PuPd
PA3.GPIO_PuPd=GPIO_PULLUP
PA3.Mode=Asynchronous
PA3.Signal=USART2_RX
PC14-OSC32_IN.Mode=LSE-External-Oscillator
PC14-OSC32_IN.Signal=RCC_OSC32_IN
PC15-OSC32_OUT.Mode=LSE-External-Oscillator
PC15-OSC32_OUT.Signal=RCC_OSC32_OUT
PCC.Checker=false
PCC.Line=STM32F405/415
PCC.MCU=STM32F405RGTx
PCC.PartNumber=STM32F405RGTx
PCC.Seq0=0
PCC.Series=STM32F4
PCC.Temperature=25
PCC.Vdd=3.3
PH0-OSC_IN.Mode=HSE-External-Oscillator
PH0-OSC_IN.Signal=RCC_OSC_IN
PH1-OSC_OUT.Mode=HSE-External-Oscillator
PH1-OSC_OUT.Signal=RCC_OSC_OUT
PinOutPanel.RotationAngle=0
ProjectManager.AskForMigrate=true
ProjectManager.BackupPrevious=false
ProjectManager.CompilerOptimize=6
ProjectManager.ComputerToolchain=false
ProjectManager.CoupleFile=false
ProjectManager.CustomerFirmwarePackage=
ProjectManager.DefaultFWLocation=true
ProjectManager.DeletePrevious=true
ProjectManager.DeviceId=STM32F405RGTx
ProjectManager.FirmwarePackage=STM32Cube FW_F4 V1.23.0
ProjectManager.FreePins=false
ProjectManager.HalAssertFull=false
ProjectManager.HeapSize=0x200
ProjectManager.KeepUserCode=true
ProjectManager.LastFirmware=true
ProjectManager.LibraryCopy=0
ProjectManager.MainLocation=Src
ProjectManager.NoMain=false
ProjectManager.PreviousToolchain=
ProjectManager.ProjectBuild=false
ProjectManager.ProjectFileName=CubeMX_Config.ioc
ProjectManager.ProjectName=CubeMX_Config
ProjectManager.StackSize=0x400
ProjectManager.TargetToolchain=EWARM V8
ProjectManager.ToolChainLocation=
ProjectManager.UnderRoot=false
ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false,3-MX_USART2_UART_Init-USART2-false-HAL-true
RCC.AHBFreq_Value=16000000
RCC.APB1Freq_Value=16000000
RCC.APB2Freq_Value=16000000
RCC.CortexFreq_Value=16000000
RCC.FamilyName=M
RCC.HSE_VALUE=8000000
RCC.HSI_VALUE=16000000
RCC.I2SClocksFreq_Value=96000000
RCC.IPParameters=AHBFreq_Value,APB1Freq_Value,APB2Freq_Value,CortexFreq_Value,FamilyName,HSE_VALUE,HSI_VALUE,I2SClocksFreq_Value,LSI_VALUE,PLLCLKFreq_Value,PLLQCLKFreq_Value,RTCFreq_Value,RTCHSEDivFreq_Value,SYSCLKFreq_VALUE,VCOI2SOutputFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VcooutputI2S
RCC.LSI_VALUE=32000
RCC.PLLCLKFreq_Value=96000000
RCC.PLLQCLKFreq_Value=48000000
RCC.RTCFreq_Value=32000
RCC.RTCHSEDivFreq_Value=4000000
RCC.SYSCLKFreq_VALUE=16000000
RCC.VCOI2SOutputFreq_Value=192000000
RCC.VCOInputFreq_Value=1000000
RCC.VCOOutputFreq_Value=192000000
RCC.VcooutputI2S=96000000
USART2.IPParameters=VirtualMode
USART2.VirtualMode=VM_ASYNC
VP_SYS_VS_Systick.Mode=SysTick
VP_SYS_VS_Systick.Signal=SYS_VS_Systick
board=custom
+91
View File
@@ -0,0 +1,91 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.h
* @brief : Header for main.c file.
* This file contains the common defines of the application.
******************************************************************************
** This notice applies to any and all portions of this file
* that are not between comment pairs USER CODE BEGIN and
* USER CODE END. Other portions of this file, whether
* inserted by the user or by software development tools
* are owned by their respective copyright owners.
*
* COPYRIGHT(c) 2018 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,451 @@
/**
******************************************************************************
* @file stm32f4xx_hal_conf.h
* @brief HAL configuration file.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2019 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F4xx_HAL_CONF_H
#define __STM32F4xx_HAL_CONF_H
#ifdef __cplusplus
extern "C" {
#endif
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* ########################## Module Selection ############################## */
/**
* @brief This is the list of modules to be used in the HAL driver
*/
#define HAL_MODULE_ENABLED
/* #define HAL_ADC_MODULE_ENABLED */
/* #define HAL_CRYP_MODULE_ENABLED */
/* #define HAL_CAN_MODULE_ENABLED */
/* #define HAL_CRC_MODULE_ENABLED */
/* #define HAL_CRYP_MODULE_ENABLED */
/* #define HAL_DAC_MODULE_ENABLED */
/* #define HAL_DCMI_MODULE_ENABLED */
/* #define HAL_DMA2D_MODULE_ENABLED */
/* #define HAL_ETH_MODULE_ENABLED */
/* #define HAL_NAND_MODULE_ENABLED */
/* #define HAL_NOR_MODULE_ENABLED */
/* #define HAL_PCCARD_MODULE_ENABLED */
/* #define HAL_SRAM_MODULE_ENABLED */
/* #define HAL_SDRAM_MODULE_ENABLED */
/* #define HAL_HASH_MODULE_ENABLED */
/* #define HAL_I2C_MODULE_ENABLED */
/* #define HAL_I2S_MODULE_ENABLED */
/* #define HAL_IWDG_MODULE_ENABLED */
/* #define HAL_LTDC_MODULE_ENABLED */
/* #define HAL_RNG_MODULE_ENABLED */
/* #define HAL_RTC_MODULE_ENABLED */
/* #define HAL_SAI_MODULE_ENABLED */
/* #define HAL_SD_MODULE_ENABLED */
/* #define HAL_MMC_MODULE_ENABLED */
/* #define HAL_SPI_MODULE_ENABLED */
/* #define HAL_TIM_MODULE_ENABLED */
#define HAL_UART_MODULE_ENABLED
/* #define HAL_USART_MODULE_ENABLED */
/* #define HAL_IRDA_MODULE_ENABLED */
/* #define HAL_SMARTCARD_MODULE_ENABLED */
/* #define HAL_WWDG_MODULE_ENABLED */
/* #define HAL_PCD_MODULE_ENABLED */
/* #define HAL_HCD_MODULE_ENABLED */
/* #define HAL_DSI_MODULE_ENABLED */
/* #define HAL_QSPI_MODULE_ENABLED */
/* #define HAL_QSPI_MODULE_ENABLED */
/* #define HAL_CEC_MODULE_ENABLED */
/* #define HAL_FMPI2C_MODULE_ENABLED */
/* #define HAL_SPDIFRX_MODULE_ENABLED */
/* #define HAL_DFSDM_MODULE_ENABLED */
/* #define HAL_LPTIM_MODULE_ENABLED */
/* #define HAL_EXTI_MODULE_ENABLED */
#define HAL_GPIO_MODULE_ENABLED
#define HAL_DMA_MODULE_ENABLED
#define HAL_RCC_MODULE_ENABLED
#define HAL_FLASH_MODULE_ENABLED
#define HAL_PWR_MODULE_ENABLED
#define HAL_CORTEX_MODULE_ENABLED
/* ########################## HSE/HSI Values adaptation ##################### */
/**
* @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSE is used as system clock source, directly or through the PLL).
*/
#if !defined (HSE_VALUE)
#define HSE_VALUE ((uint32_t)8000000U) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined (HSE_STARTUP_TIMEOUT)
#define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */
#endif /* HSE_STARTUP_TIMEOUT */
/**
* @brief Internal High Speed oscillator (HSI) value.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSI is used as system clock source, directly or through the PLL).
*/
#if !defined (HSI_VALUE)
#define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */
/**
* @brief Internal Low Speed oscillator (LSI) value.
*/
#if !defined (LSI_VALUE)
#define LSI_VALUE ((uint32_t)32000U) /*!< LSI Typical Value in Hz*/
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
The real value may vary depending on the variations
in voltage and temperature.*/
/**
* @brief External Low Speed oscillator (LSE) value.
*/
#if !defined (LSE_VALUE)
#define LSE_VALUE ((uint32_t)32768U) /*!< Value of the External Low Speed oscillator in Hz */
#endif /* LSE_VALUE */
#if !defined (LSE_STARTUP_TIMEOUT)
#define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */
#endif /* LSE_STARTUP_TIMEOUT */
/**
* @brief External clock source for I2S peripheral
* This value is used by the I2S HAL module to compute the I2S clock source
* frequency, this source is inserted directly through I2S_CKIN pad.
*/
#if !defined (EXTERNAL_CLOCK_VALUE)
#define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000U) /*!< Value of the External audio frequency in Hz*/
#endif /* EXTERNAL_CLOCK_VALUE */
/* Tip: To avoid modifying this file each time you need to use different HSE,
=== you can define the HSE value in your toolchain compiler preprocessor. */
/* ########################### System Configuration ######################### */
/**
* @brief This is the HAL system configuration section
*/
#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */
#define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */
#define USE_RTOS 0U
#define PREFETCH_ENABLE 1U
#define INSTRUCTION_CACHE_ENABLE 1U
#define DATA_CACHE_ENABLE 1U
/* ########################## Assert Selection ############################## */
/**
* @brief Uncomment the line below to expanse the "assert_param" macro in the
* HAL drivers code
*/
/* #define USE_FULL_ASSERT 1U */
/* ################## Ethernet peripheral configuration ##################### */
/* Section 1 : Ethernet peripheral configuration */
/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */
#define MAC_ADDR0 2U
#define MAC_ADDR1 0U
#define MAC_ADDR2 0U
#define MAC_ADDR3 0U
#define MAC_ADDR4 0U
#define MAC_ADDR5 0U
/* Definition of the Ethernet driver buffers size and count */
#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */
#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */
#define ETH_RXBUFNB ((uint32_t)4U) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */
#define ETH_TXBUFNB ((uint32_t)4U) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */
/* Section 2: PHY configuration section */
/* DP83848_PHY_ADDRESS Address*/
#define DP83848_PHY_ADDRESS 0x01U
/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/
#define PHY_RESET_DELAY ((uint32_t)0x000000FFU)
/* PHY Configuration delay */
#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFFU)
#define PHY_READ_TO ((uint32_t)0x0000FFFFU)
#define PHY_WRITE_TO ((uint32_t)0x0000FFFFU)
/* Section 3: Common PHY Registers */
#define PHY_BCR ((uint16_t)0x0000U) /*!< Transceiver Basic Control Register */
#define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */
#define PHY_RESET ((uint16_t)0x8000U) /*!< PHY Reset */
#define PHY_LOOPBACK ((uint16_t)0x4000U) /*!< Select loop-back mode */
#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U) /*!< Set the full-duplex mode at 100 Mb/s */
#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000U) /*!< Set the half-duplex mode at 100 Mb/s */
#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100U) /*!< Set the full-duplex mode at 10 Mb/s */
#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000U) /*!< Set the half-duplex mode at 10 Mb/s */
#define PHY_AUTONEGOTIATION ((uint16_t)0x1000U) /*!< Enable auto-negotiation function */
#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*!< Restart auto-negotiation function */
#define PHY_POWERDOWN ((uint16_t)0x0800U) /*!< Select the power down mode */
#define PHY_ISOLATE ((uint16_t)0x0400U) /*!< Isolate PHY from MII */
#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*!< Auto-Negotiation process completed */
#define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */
#define PHY_JABBER_DETECTION ((uint16_t)0x0002U) /*!< Jabber condition detected */
/* Section 4: Extended PHY Registers */
#define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */
#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */
#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */
/* ################## SPI peripheral configuration ########################## */
/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver
* Activated: CRC code is present inside driver
* Deactivated: CRC code cleaned from driver
*/
#define USE_SPI_CRC 0U
/* Includes ------------------------------------------------------------------*/
/**
* @brief Include module's header file
*/
#ifdef HAL_RCC_MODULE_ENABLED
#include "stm32f4xx_hal_rcc.h"
#endif /* HAL_RCC_MODULE_ENABLED */
#ifdef HAL_EXTI_MODULE_ENABLED
#include "stm32f4xx_hal_exti.h"
#endif /* HAL_EXTI_MODULE_ENABLED */
#ifdef HAL_GPIO_MODULE_ENABLED
#include "stm32f4xx_hal_gpio.h"
#endif /* HAL_GPIO_MODULE_ENABLED */
#ifdef HAL_DMA_MODULE_ENABLED
#include "stm32f4xx_hal_dma.h"
#endif /* HAL_DMA_MODULE_ENABLED */
#ifdef HAL_CORTEX_MODULE_ENABLED
#include "stm32f4xx_hal_cortex.h"
#endif /* HAL_CORTEX_MODULE_ENABLED */
#ifdef HAL_ADC_MODULE_ENABLED
#include "stm32f4xx_hal_adc.h"
#endif /* HAL_ADC_MODULE_ENABLED */
#ifdef HAL_CAN_MODULE_ENABLED
#include "stm32f4xx_hal_can.h"
#endif /* HAL_CAN_MODULE_ENABLED */
#ifdef HAL_CRC_MODULE_ENABLED
#include "stm32f4xx_hal_crc.h"
#endif /* HAL_CRC_MODULE_ENABLED */
#ifdef HAL_CRYP_MODULE_ENABLED
#include "stm32f4xx_hal_cryp.h"
#endif /* HAL_CRYP_MODULE_ENABLED */
#ifdef HAL_DMA2D_MODULE_ENABLED
#include "stm32f4xx_hal_dma2d.h"
#endif /* HAL_DMA2D_MODULE_ENABLED */
#ifdef HAL_DAC_MODULE_ENABLED
#include "stm32f4xx_hal_dac.h"
#endif /* HAL_DAC_MODULE_ENABLED */
#ifdef HAL_DCMI_MODULE_ENABLED
#include "stm32f4xx_hal_dcmi.h"
#endif /* HAL_DCMI_MODULE_ENABLED */
#ifdef HAL_ETH_MODULE_ENABLED
#include "stm32f4xx_hal_eth.h"
#endif /* HAL_ETH_MODULE_ENABLED */
#ifdef HAL_FLASH_MODULE_ENABLED
#include "stm32f4xx_hal_flash.h"
#endif /* HAL_FLASH_MODULE_ENABLED */
#ifdef HAL_SRAM_MODULE_ENABLED
#include "stm32f4xx_hal_sram.h"
#endif /* HAL_SRAM_MODULE_ENABLED */
#ifdef HAL_NOR_MODULE_ENABLED
#include "stm32f4xx_hal_nor.h"
#endif /* HAL_NOR_MODULE_ENABLED */
#ifdef HAL_NAND_MODULE_ENABLED
#include "stm32f4xx_hal_nand.h"
#endif /* HAL_NAND_MODULE_ENABLED */
#ifdef HAL_PCCARD_MODULE_ENABLED
#include "stm32f4xx_hal_pccard.h"
#endif /* HAL_PCCARD_MODULE_ENABLED */
#ifdef HAL_SDRAM_MODULE_ENABLED
#include "stm32f4xx_hal_sdram.h"
#endif /* HAL_SDRAM_MODULE_ENABLED */
#ifdef HAL_HASH_MODULE_ENABLED
#include "stm32f4xx_hal_hash.h"
#endif /* HAL_HASH_MODULE_ENABLED */
#ifdef HAL_I2C_MODULE_ENABLED
#include "stm32f4xx_hal_i2c.h"
#endif /* HAL_I2C_MODULE_ENABLED */
#ifdef HAL_I2S_MODULE_ENABLED
#include "stm32f4xx_hal_i2s.h"
#endif /* HAL_I2S_MODULE_ENABLED */
#ifdef HAL_IWDG_MODULE_ENABLED
#include "stm32f4xx_hal_iwdg.h"
#endif /* HAL_IWDG_MODULE_ENABLED */
#ifdef HAL_LTDC_MODULE_ENABLED
#include "stm32f4xx_hal_ltdc.h"
#endif /* HAL_LTDC_MODULE_ENABLED */
#ifdef HAL_PWR_MODULE_ENABLED
#include "stm32f4xx_hal_pwr.h"
#endif /* HAL_PWR_MODULE_ENABLED */
#ifdef HAL_RNG_MODULE_ENABLED
#include "stm32f4xx_hal_rng.h"
#endif /* HAL_RNG_MODULE_ENABLED */
#ifdef HAL_RTC_MODULE_ENABLED
#include "stm32f4xx_hal_rtc.h"
#endif /* HAL_RTC_MODULE_ENABLED */
#ifdef HAL_SAI_MODULE_ENABLED
#include "stm32f4xx_hal_sai.h"
#endif /* HAL_SAI_MODULE_ENABLED */
#ifdef HAL_SD_MODULE_ENABLED
#include "stm32f4xx_hal_sd.h"
#endif /* HAL_SD_MODULE_ENABLED */
#ifdef HAL_MMC_MODULE_ENABLED
#include "stm32f4xx_hal_mmc.h"
#endif /* HAL_MMC_MODULE_ENABLED */
#ifdef HAL_SPI_MODULE_ENABLED
#include "stm32f4xx_hal_spi.h"
#endif /* HAL_SPI_MODULE_ENABLED */
#ifdef HAL_TIM_MODULE_ENABLED
#include "stm32f4xx_hal_tim.h"
#endif /* HAL_TIM_MODULE_ENABLED */
#ifdef HAL_UART_MODULE_ENABLED
#include "stm32f4xx_hal_uart.h"
#endif /* HAL_UART_MODULE_ENABLED */
#ifdef HAL_USART_MODULE_ENABLED
#include "stm32f4xx_hal_usart.h"
#endif /* HAL_USART_MODULE_ENABLED */
#ifdef HAL_IRDA_MODULE_ENABLED
#include "stm32f4xx_hal_irda.h"
#endif /* HAL_IRDA_MODULE_ENABLED */
#ifdef HAL_SMARTCARD_MODULE_ENABLED
#include "stm32f4xx_hal_smartcard.h"
#endif /* HAL_SMARTCARD_MODULE_ENABLED */
#ifdef HAL_WWDG_MODULE_ENABLED
#include "stm32f4xx_hal_wwdg.h"
#endif /* HAL_WWDG_MODULE_ENABLED */
#ifdef HAL_PCD_MODULE_ENABLED
#include "stm32f4xx_hal_pcd.h"
#endif /* HAL_PCD_MODULE_ENABLED */
#ifdef HAL_HCD_MODULE_ENABLED
#include "stm32f4xx_hal_hcd.h"
#endif /* HAL_HCD_MODULE_ENABLED */
#ifdef HAL_DSI_MODULE_ENABLED
#include "stm32f4xx_hal_dsi.h"
#endif /* HAL_DSI_MODULE_ENABLED */
#ifdef HAL_QSPI_MODULE_ENABLED
#include "stm32f4xx_hal_qspi.h"
#endif /* HAL_QSPI_MODULE_ENABLED */
#ifdef HAL_CEC_MODULE_ENABLED
#include "stm32f4xx_hal_cec.h"
#endif /* HAL_CEC_MODULE_ENABLED */
#ifdef HAL_FMPI2C_MODULE_ENABLED
#include "stm32f4xx_hal_fmpi2c.h"
#endif /* HAL_FMPI2C_MODULE_ENABLED */
#ifdef HAL_SPDIFRX_MODULE_ENABLED
#include "stm32f4xx_hal_spdifrx.h"
#endif /* HAL_SPDIFRX_MODULE_ENABLED */
#ifdef HAL_DFSDM_MODULE_ENABLED
#include "stm32f4xx_hal_dfsdm.h"
#endif /* HAL_DFSDM_MODULE_ENABLED */
#ifdef HAL_LPTIM_MODULE_ENABLED
#include "stm32f4xx_hal_lptim.h"
#endif /* HAL_LPTIM_MODULE_ENABLED */
/* Exported macro ------------------------------------------------------------*/
#ifdef USE_FULL_ASSERT
/**
* @brief The assert_param macro is used for function's parameters check.
* @param expr: If expr is false, it calls assert_failed function
* which reports the name of the source file and the source
* line number of the call that failed.
* If expr is true, it returns no value.
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t* file, uint32_t line);
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */
#ifdef __cplusplus
}
#endif
#endif /* __STM32F4xx_HAL_CONF_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,84 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f4xx_it.h
* @brief This file contains the headers of the interrupt handlers.
******************************************************************************
*
* COPYRIGHT(c) 2018 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F4xx_IT_H
#define __STM32F4xx_IT_H
#ifdef __cplusplus
extern "C" {
#endif
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void SVC_Handler(void);
void DebugMon_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
#ifdef __cplusplus
}
#endif
#endif /* __STM32F4xx_IT_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,208 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : stm32f4xx_hal_msp.c
* Description : This file provides code for the MSP Initialization
* and de-Initialization codes.
******************************************************************************
** This notice applies to any and all portions of this file
* that are not between comment pairs USER CODE BEGIN and
* USER CODE END. Other portions of this file, whether
* inserted by the user or by software development tools
* are owned by their respective copyright owners.
*
* COPYRIGHT(c) 2018 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
#include <drv_common.h>
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN Define */
/* USER CODE END Define */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN Macro */
/* USER CODE END Macro */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* External functions --------------------------------------------------------*/
/* USER CODE BEGIN ExternalFunctions */
/* USER CODE END ExternalFunctions */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* Initializes the Global MSP.
*/
void HAL_MspInit(void)
{
/* USER CODE BEGIN MspInit 0 */
/* USER CODE END MspInit 0 */
__HAL_RCC_SYSCFG_CLK_ENABLE();
__HAL_RCC_PWR_CLK_ENABLE();
/* System interrupt init*/
/* USER CODE BEGIN MspInit 1 */
/* USER CODE END MspInit 1 */
}
/**
* @brief UART MSP Initialization
* This function configures the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(huart->Instance==USART1) {
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART2 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
} else if(huart->Instance==USART2) {
/* USER CODE BEGIN USART2_MspInit 0 */
/* USER CODE END USART2_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_USART2_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART2 GPIO Configuration
PA2 ------> USART2_TX
PA3 ------> USART2_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN USART2_MspInit 1 */
/* USER CODE END USART2_MspInit 1 */
}
}
/**
* @brief UART MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
{
if(huart->Instance==USART1) {
/* USER CODE BEGIN USART1_MspDeInit 0 */
/* USER CODE END USART1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA3 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
/* USER CODE BEGIN USART1_MspDeInit 1 */
/* USER CODE END USART1_MspDeInit 1 */
} else if(huart->Instance==USART2) {
/* USER CODE BEGIN USART2_MspDeInit 0 */
/* USER CODE END USART2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART2_CLK_DISABLE();
/**USART2 GPIO Configuration
PA2 ------> USART2_TX
PA3 ------> USART2_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);
/* USER CODE BEGIN USART2_MspDeInit 1 */
/* USER CODE END USART2_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,217 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f4xx_it.c
* @brief Interrupt Service Routines.
******************************************************************************
*
* COPYRIGHT(c) 2018 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/* External variables --------------------------------------------------------*/
/* USER CODE BEGIN EV */
/* USER CODE END EV */
/******************************************************************************/
/* Cortex-M4 Processor Interruption and Exception Handlers */
/******************************************************************************/
/**
* @brief This function handles Non maskable interrupt.
*/
void NMI_Handler(void)
{
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
/* USER CODE END NonMaskableInt_IRQn 0 */
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
/* USER CODE END NonMaskableInt_IRQn 1 */
}
/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
}
/**
* @brief This function handles Memory management fault.
*/
void MemManage_Handler(void)
{
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
/* USER CODE END MemoryManagement_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
/* USER CODE END W1_MemoryManagement_IRQn 0 */
}
}
/**
* @brief This function handles Pre-fetch fault, memory access fault.
*/
void BusFault_Handler(void)
{
/* USER CODE BEGIN BusFault_IRQn 0 */
/* USER CODE END BusFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_BusFault_IRQn 0 */
/* USER CODE END W1_BusFault_IRQn 0 */
}
}
/**
* @brief This function handles Undefined instruction or illegal state.
*/
void UsageFault_Handler(void)
{
/* USER CODE BEGIN UsageFault_IRQn 0 */
/* USER CODE END UsageFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_UsageFault_IRQn 0 */
/* USER CODE END W1_UsageFault_IRQn 0 */
}
}
/**
* @brief This function handles System service call via SWI instruction.
*/
void SVC_Handler(void)
{
/* USER CODE BEGIN SVCall_IRQn 0 */
/* USER CODE END SVCall_IRQn 0 */
/* USER CODE BEGIN SVCall_IRQn 1 */
/* USER CODE END SVCall_IRQn 1 */
}
/**
* @brief This function handles Debug monitor.
*/
void DebugMon_Handler(void)
{
/* USER CODE BEGIN DebugMonitor_IRQn 0 */
/* USER CODE END DebugMonitor_IRQn 0 */
/* USER CODE BEGIN DebugMonitor_IRQn 1 */
/* USER CODE END DebugMonitor_IRQn 1 */
}
/**
* @brief This function handles Pendable request for system service.
*/
void PendSV_Handler(void)
{
/* USER CODE BEGIN PendSV_IRQn 0 */
/* USER CODE END PendSV_IRQn 0 */
/* USER CODE BEGIN PendSV_IRQn 1 */
/* USER CODE END PendSV_IRQn 1 */
}
/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
/* USER CODE END SysTick_IRQn 1 */
}
/******************************************************************************/
/* STM32F4xx Peripheral Interrupt Handlers */
/* Add here the Interrupt Handlers for the used peripherals. */
/* For the available peripheral interrupt handler names, */
/* please refer to the startup file (startup_stm32f4xx.s). */
/******************************************************************************/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+100
View File
@@ -0,0 +1,100 @@
menu "Hardware Drivers Config"
menu "Onboard Peripheral Drivers"
endmenu
menu "On-chip Peripheral Drivers"
config BSP_USING_GPIO
bool "Enable GPIO"
select RT_USING_PIN
default y
menuconfig BSP_USING_UART
bool "Enable UART"
default y
select RT_USING_SERIAL
if BSP_USING_UART
config BSP_STM32_UART_V1_TX_TIMEOUT
int "UART TX timeout"
default 2000
depends on RT_USING_SERIAL_V1
config BSP_USING_UART1
bool "Enable UART1"
default y
config BSP_UART1_RX_USING_DMA
bool "Enable UART1 RX DMA"
depends on BSP_USING_UART1
select RT_SERIAL_USING_DMA
default n
config BSP_UART1_TX_USING_DMA
bool "Enable UART1 TX DMA"
depends on BSP_USING_UART1
select RT_SERIAL_USING_DMA
default n
config BSP_UART1_RX_BUFSIZE
int "Set UART1 RX buffer size"
range 64 65535
depends on BSP_USING_UART1 && RT_USING_SERIAL_V2
default 64
config BSP_UART1_TX_BUFSIZE
int "Set UART1 TX buffer size"
range 0 65535
depends on BSP_USING_UART1 && RT_USING_SERIAL_V2
default 0
config BSP_UART1_DMA_PING_BUFSIZE
int "Set UART1 RX DMA ping-pong buffer size"
range 32 65535
depends on RT_USING_SERIAL_V2 && BSP_UART1_RX_USING_DMA
default 32
config BSP_USING_UART2
bool "Enable UART2"
default y
config BSP_UART2_RX_USING_DMA
bool "Enable UART2 RX DMA"
depends on BSP_USING_UART2
select RT_SERIAL_USING_DMA
default n
config BSP_UART2_TX_USING_DMA
bool "Enable UART2 TX DMA"
depends on BSP_USING_UART2
select RT_SERIAL_USING_DMA
default n
config BSP_UART2_RX_BUFSIZE
int "Set UART2 RX buffer size"
range 64 65535
depends on BSP_USING_UART2 && RT_USING_SERIAL_V2
default 64
config BSP_UART2_TX_BUFSIZE
int "Set UART2 TX buffer size"
range 0 65535
depends on BSP_USING_UART2 && RT_USING_SERIAL_V2
default 0
config BSP_UART2_DMA_PING_BUFSIZE
int "Set UART2 RX DMA ping-pong buffer size"
range 32 65535
depends on RT_USING_SERIAL_V2 && BSP_UART2_RX_USING_DMA
default 32
endif
source "$(RTT_DIR)/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig"
endmenu
menu "Board extended module Drivers"
endmenu
endmenu
+27
View File
@@ -0,0 +1,27 @@
import os
from building import *
cwd = GetCurrentDir()
# add general drivers
src = Split('''
board.c
CubeMX_Config/Src/stm32f4xx_hal_msp.c
''')
path = [cwd]
path += [os.path.join(cwd, 'CubeMX_Config', 'Inc')]
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path)
# if os.path.isfile(os.path.join(cwd, "ports", 'SConscript')):
# group = group + SConscript(os.path.join("ports", 'SConscript'))
list = os.listdir(cwd)
for item in list:
if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
group = group + SConscript(os.path.join(item, 'SConscript'))
Return('group')
+50
View File
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-06 SummerGift first version
*/
#include <board.h>
#include <drv_common.h>
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/**Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 4;
RCC_OscInitStruct.PLL.PLLN = 168;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
}
+47
View File
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-5 SummerGift first version
*/
#ifndef __BOARD_H__
#define __BOARD_H__
#include <stm32f4xx.h>
#ifdef __cplusplus
extern "C" {
#endif
#define STM32_FLASH_START_ADRESS ((uint32_t)0x08000000)
#define STM32_FLASH_SIZE (1024 * 1024)
#define STM32_FLASH_END_ADDRESS ((uint32_t)(STM32_FLASH_START_ADRESS + STM32_FLASH_SIZE))
#define STM32_SRAM_SIZE (128)
#define STM32_SRAM_END (0x20000000 + STM32_SRAM_SIZE * 1024)
#if defined(__ARMCC_VERSION)
extern int Image$$RW_IRAM1$$ZI$$Limit;
#define HEAP_BEGIN (&Image$$RW_IRAM1$$ZI$$Limit)
#elif __ICCARM__
#pragma section="CSTACK"
#define HEAP_BEGIN (__segment_end("CSTACK"))
#else
extern int __bss_end;
#define HEAP_BEGIN (&__bss_end)
#endif
#define HEAP_END STM32_SRAM_END
void SystemClock_Config(void);
#ifdef __cplusplus
}
#endif
#endif
+30
View File
@@ -0,0 +1,30 @@
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
define symbol __ICFEDIT_region_ROM_end__ = 0x080FFFFF;
define symbol __ICFEDIT_region_RAM1_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM1_end__ = 0x2001FFFF;
define symbol __ICFEDIT_region_RAM2_start__ = 0x10000000;
define symbol __ICFEDIT_region_RAM2_end__ = 0x1000FFFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x0400;
define symbol __ICFEDIT_size_heap__ = 0x000;
/**** End of ICF editor section. ###ICF###*/
define memory mem with size = 4G;
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
define region RAM1_region = mem:[from __ICFEDIT_region_RAM1_start__ to __ICFEDIT_region_RAM1_end__];
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
initialize by copy { readwrite };
do not initialize { section .noinit };
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
place in ROM_region { readonly };
place in RAM1_region { readwrite, last block CSTACK };
+159
View File
@@ -0,0 +1,159 @@
/*
* linker script for STM32F4xx with GNU ld
* bernard.xiong 2009-10-14
* flybreak 2018-11-19 Add support for RAM2
*/
/* Program Entry, set to mark it as "used" and avoid gc */
MEMORY
{
CODE (rx) : ORIGIN = 0x08000000, LENGTH = 1024k /* 1024KB flash */
RAM1 (rw) : ORIGIN = 0x20000000, LENGTH = 128k /* 128K sram */
RAM2 (rw) : ORIGIN = 0x10000000, LENGTH = 64k /* 64K sram */
}
ENTRY(Reset_Handler)
_system_stack_size = 0x400;
SECTIONS
{
.text :
{
. = ALIGN(4);
_stext = .;
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
*(.text) /* remaining code */
*(.text.*) /* remaining code */
*(.rodata) /* read-only data (constants) */
*(.rodata*)
*(.glue_7)
*(.glue_7t)
*(.gnu.linkonce.t*)
/* section information for finsh shell */
. = ALIGN(4);
__fsymtab_start = .;
KEEP(*(FSymTab))
__fsymtab_end = .;
. = ALIGN(4);
__vsymtab_start = .;
KEEP(*(VSymTab))
__vsymtab_end = .;
/* section information for initial. */
. = ALIGN(4);
__rt_init_start = .;
KEEP(*(SORT(.rti_fn*)))
__rt_init_end = .;
. = ALIGN(4);
PROVIDE(__ctors_start__ = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
PROVIDE(__ctors_end__ = .);
. = ALIGN(4);
_etext = .;
} > CODE = 0
/* .ARM.exidx is sorted, so has to go in its own output section. */
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
/* This is used by the startup in order to initialize the .data secion */
_sidata = .;
} > CODE
__exidx_end = .;
/* .data section which is used for initialized data */
.data : AT (_sidata)
{
. = ALIGN(4);
/* This is used by the startup in order to initialize the .data secion */
_sdata = . ;
*(.data)
*(.data.*)
*(.gnu.linkonce.d*)
PROVIDE(__dtors_start__ = .);
KEEP(*(SORT(.dtors.*)))
KEEP(*(.dtors))
PROVIDE(__dtors_end__ = .);
. = ALIGN(4);
/* This is used by the startup in order to initialize the .data secion */
_edata = . ;
} >RAM1
.stack :
{
. = ALIGN(4);
_sstack = .;
. = . + _system_stack_size;
. = ALIGN(4);
_estack = .;
} >RAM1
__bss_start = .;
.bss :
{
. = ALIGN(4);
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .;
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
/* This is used by the startup in order to initialize the .bss secion */
_ebss = . ;
*(.bss.init)
} > RAM1
__bss_end = .;
_end = .;
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
* Symbols in the DWARF debugging sections are relative to the beginning
* of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
}
File diff suppressed because it is too large Load Diff
+483
View File
@@ -0,0 +1,483 @@
#ifndef RT_CONFIG_H__
#define RT_CONFIG_H__
#define SOC_STM32F405RG
/* RT-Thread Kernel */
/* klibc options */
/* rt_vsnprintf options */
/* end of rt_vsnprintf options */
/* rt_vsscanf options */
/* end of rt_vsscanf options */
/* rt_memset options */
/* end of rt_memset options */
/* rt_memcpy options */
/* end of rt_memcpy options */
/* rt_memmove options */
/* end of rt_memmove options */
/* rt_memcmp options */
/* end of rt_memcmp options */
/* rt_strstr options */
/* end of rt_strstr options */
/* rt_strcasecmp options */
/* end of rt_strcasecmp options */
/* rt_strncpy options */
/* end of rt_strncpy options */
/* rt_strcpy options */
/* end of rt_strcpy options */
/* rt_strncmp options */
/* end of rt_strncmp options */
/* rt_strcmp options */
/* end of rt_strcmp options */
/* rt_strlen options */
/* end of rt_strlen options */
/* rt_strnlen options */
/* end of rt_strnlen options */
/* end of klibc options */
#define RT_NAME_MAX 16
#define RT_CPUS_NR 1
#define RT_ALIGN_SIZE 8
#define RT_THREAD_PRIORITY_32
#define RT_THREAD_PRIORITY_MAX 32
#define RT_TICK_PER_SECOND 1000
#define RT_USING_OVERFLOW_CHECK
#define RT_USING_HOOK
#define RT_HOOK_USING_FUNC_PTR
#define RT_USING_IDLE_HOOK
#define RT_IDLE_HOOK_LIST_SIZE 4
#define IDLE_THREAD_STACK_SIZE 256
/* kservice options */
/* end of kservice options */
#define RT_USING_DEBUG
#define RT_DEBUGING_ASSERT
#define RT_DEBUGING_COLOR
#define RT_DEBUGING_CONTEXT
/* Inter-Thread communication */
#define RT_USING_SEMAPHORE
#define RT_USING_MUTEX
#define RT_USING_EVENT
#define RT_USING_MAILBOX
#define RT_USING_MESSAGEQUEUE
/* end of Inter-Thread communication */
/* Memory Management */
#define RT_USING_MEMPOOL
#define RT_USING_SMALL_MEM
#define RT_USING_SMALL_MEM_AS_HEAP
#define RT_USING_HEAP
/* end of Memory Management */
#define RT_USING_DEVICE
#define RT_USING_CONSOLE
#define RT_CONSOLEBUF_SIZE 128
#define RT_CONSOLE_DEVICE_NAME "uart1"
#define RT_VER_NUM 0x50201
#define RT_BACKTRACE_LEVEL_MAX_NR 32
/* end of RT-Thread Kernel */
#define RT_USING_HW_ATOMIC
#define RT_USING_CPU_FFS
#define ARCH_ARM
#define ARCH_ARM_CORTEX_M
#define ARCH_ARM_CORTEX_M4
/* RT-Thread Components */
#define RT_USING_COMPONENTS_INIT
#define RT_USING_USER_MAIN
#define RT_MAIN_THREAD_STACK_SIZE 2048
#define RT_MAIN_THREAD_PRIORITY 10
#define RT_USING_MSH
#define RT_USING_FINSH
#define FINSH_USING_MSH
#define FINSH_THREAD_NAME "tshell"
#define FINSH_THREAD_PRIORITY 20
#define FINSH_THREAD_STACK_SIZE 4096
#define FINSH_USING_HISTORY
#define FINSH_HISTORY_LINES 5
#define FINSH_USING_SYMTAB
#define FINSH_CMD_SIZE 80
#define MSH_USING_BUILT_IN_COMMANDS
#define FINSH_USING_DESCRIPTION
#define FINSH_ARG_MAX 10
#define FINSH_USING_OPTION_COMPLETION
/* DFS: device virtual file system */
/* end of DFS: device virtual file system */
/* Device Drivers */
#define RT_USING_DEVICE_IPC
#define RT_UNAMED_PIPE_NUMBER 64
#define RT_USING_SYSTEM_WORKQUEUE
#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048
#define RT_SYSTEM_WORKQUEUE_PRIORITY 23
#define RT_USING_SERIAL
#define RT_USING_SERIAL_V1
#define RT_SERIAL_USING_DMA
#define RT_SERIAL_RB_BUFSZ 64
#define RT_USING_PIN
/* end of Device Drivers */
/* C/C++ and POSIX layer */
/* ISO-ANSI C layer */
/* Timezone and Daylight Saving Time */
#define RT_LIBC_USING_LIGHT_TZ_DST
#define RT_LIBC_TZ_DEFAULT_HOUR 8
#define RT_LIBC_TZ_DEFAULT_MIN 0
#define RT_LIBC_TZ_DEFAULT_SEC 0
/* end of Timezone and Daylight Saving Time */
/* end of ISO-ANSI C layer */
/* POSIX (Portable Operating System Interface) layer */
/* Interprocess Communication (IPC) */
/* Socket is in the 'Network' category */
/* end of Interprocess Communication (IPC) */
/* end of POSIX (Portable Operating System Interface) layer */
/* end of C/C++ and POSIX layer */
/* Network */
#define RT_USING_SAL
#define SAL_INTERNET_CHECK
/* Docking with protocol stacks */
/* end of Docking with protocol stacks */
#define SAL_SOCKETS_NUM 16
#define RT_USING_NETDEV
#define NETDEV_USING_IFCONFIG
#define NETDEV_USING_PING
#define NETDEV_USING_NETSTAT
#define NETDEV_USING_AUTO_DEFAULT
#define NETDEV_IPV4 1
#define NETDEV_IPV6 0
/* end of Network */
/* Memory protection */
/* end of Memory protection */
/* Utilities */
/* end of Utilities */
/* Using USB legacy version */
/* end of Using USB legacy version */
/* end of RT-Thread Components */
/* RT-Thread online packages */
/* IoT - internet of things */
#define PKG_USING_FREEMODBUS
#define PKG_MODBUS_MASTER
/* advanced configuration */
#define RT_M_DISCRETE_INPUT_START 0
#define RT_M_DISCRETE_INPUT_NDISCRETES 16
#define RT_M_COIL_START 0
#define RT_M_COIL_NCOILS 64
#define RT_M_REG_INPUT_START 0
#define RT_M_REG_INPUT_NREGS 100
#define RT_M_REG_HOLDING_START 0
#define RT_M_REG_HOLDING_NREGS 100
#define RT_M_HD_RESERVE 0
#define RT_M_IN_RESERVE 0
#define RT_M_CO_RESERVE 0
#define RT_M_DI_RESERVE 0
/* end of advanced configuration */
#define PKG_MODBUS_MASTER_RTU
#define PKG_MODBUS_MASTER_SAMPLE
#define MB_SAMPLE_TEST_SLAVE_ADDR 1
#define MB_MASTER_USING_PORT_NUM 1
#define MB_MASTER_USING_PORT_BAUDRATE 115200
#define PKG_MODBUS_SLAVE
/* advanced configuration */
#define RT_S_DISCRETE_INPUT_START 0
#define RT_S_DISCRETE_INPUT_NDISCRETES 16
#define RT_S_COIL_START 0
#define RT_S_COIL_NCOILS 64
#define RT_S_REG_INPUT_START 0
#define RT_S_REG_INPUT_NREGS 100
#define RT_S_REG_HOLDING_START 0
#define RT_S_REG_HOLDING_NREGS 100
#define RT_S_HD_RESERVE 0
#define RT_S_IN_RESERVE 0
#define RT_S_CO_RESERVE 0
#define RT_S_DI_RESERVE 0
/* end of advanced configuration */
#define PKG_MODBUS_SLAVE_RTU
#define PKG_MODBUS_SLAVE_SAMPLE
#define MB_SAMPLE_SLAVE_ADDR 1
#define MB_SLAVE_USING_PORT_NUM 2
#define MB_SLAVE_USING_PORT_BAUDRATE 115200
#define PKG_USING_FREEMODBUS_LATEST_VERSION
/* Wi-Fi */
/* Marvell WiFi */
/* end of Marvell WiFi */
/* Wiced WiFi */
/* end of Wiced WiFi */
/* CYW43012 WiFi */
/* end of CYW43012 WiFi */
/* BL808 WiFi */
/* end of BL808 WiFi */
/* CYW43439 WiFi */
/* end of CYW43439 WiFi */
/* end of Wi-Fi */
/* IoT Cloud */
/* end of IoT Cloud */
/* end of IoT - internet of things */
/* security packages */
/* end of security packages */
/* language packages */
/* JSON: JavaScript Object Notation, a lightweight data-interchange format */
/* end of JSON: JavaScript Object Notation, a lightweight data-interchange format */
/* XML: Extensible Markup Language */
/* end of XML: Extensible Markup Language */
/* end of language packages */
/* multimedia packages */
/* LVGL: powerful and easy-to-use embedded GUI library */
/* end of LVGL: powerful and easy-to-use embedded GUI library */
/* u8g2: a monochrome graphic library */
/* end of u8g2: a monochrome graphic library */
/* end of multimedia packages */
/* tools packages */
/* end of tools packages */
/* system packages */
/* enhanced kernel services */
/* end of enhanced kernel services */
/* acceleration: Assembly language or algorithmic acceleration packages */
/* end of acceleration: Assembly language or algorithmic acceleration packages */
/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */
#define PKG_USING_CMSIS_CORE
#define PKG_USING_CMSIS_CORE_LATEST_VERSION
/* end of CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */
/* Micrium: Micrium software products porting for RT-Thread */
/* end of Micrium: Micrium software products porting for RT-Thread */
/* end of system packages */
/* peripheral libraries and drivers */
/* HAL & SDK Drivers */
/* STM32 HAL & SDK Drivers */
#define PKG_USING_STM32F4_HAL_DRIVER
#define PKG_USING_STM32F4_HAL_DRIVER_LATEST_VERSION
#define PKG_USING_STM32F4_CMSIS_DRIVER
#define PKG_USING_STM32F4_CMSIS_DRIVER_LATEST_VERSION
/* end of STM32 HAL & SDK Drivers */
/* Infineon HAL Packages */
/* end of Infineon HAL Packages */
/* Kendryte SDK */
/* end of Kendryte SDK */
/* WCH HAL & SDK Drivers */
/* end of WCH HAL & SDK Drivers */
/* AT32 HAL & SDK Drivers */
/* end of AT32 HAL & SDK Drivers */
/* HC32 DDL Drivers */
/* end of HC32 DDL Drivers */
/* NXP HAL & SDK Drivers */
/* end of NXP HAL & SDK Drivers */
/* NUVOTON Drivers */
/* end of NUVOTON Drivers */
/* GD32 Drivers */
/* end of GD32 Drivers */
/* end of HAL & SDK Drivers */
/* sensors drivers */
/* end of sensors drivers */
/* touch drivers */
/* end of touch drivers */
/* end of peripheral libraries and drivers */
/* AI packages */
/* end of AI packages */
/* Signal Processing and Control Algorithm Packages */
/* end of Signal Processing and Control Algorithm Packages */
/* miscellaneous packages */
/* project laboratory */
/* end of project laboratory */
/* samples: kernel and components samples */
/* end of samples: kernel and components samples */
/* entertainment: terminal games and other interesting software packages */
/* end of entertainment: terminal games and other interesting software packages */
/* end of miscellaneous packages */
/* Arduino libraries */
/* Projects and Demos */
/* end of Projects and Demos */
/* Sensors */
/* end of Sensors */
/* Display */
/* end of Display */
/* Timing */
/* end of Timing */
/* Data Processing */
/* end of Data Processing */
/* Data Storage */
/* Communication */
/* end of Communication */
/* Device Control */
/* end of Device Control */
/* Other */
/* end of Other */
/* Signal IO */
/* end of Signal IO */
/* Uncategorized */
/* end of Arduino libraries */
/* end of RT-Thread online packages */
#define SOC_FAMILY_STM32
#define SOC_SERIES_STM32F4
/* Hardware Drivers Config */
/* Onboard Peripheral Drivers */
/* On-chip Peripheral Drivers */
#define BSP_USING_GPIO
#define BSP_USING_UART
#define BSP_STM32_UART_V1_TX_TIMEOUT 2000
#define BSP_USING_UART1
#define BSP_USING_UART2
/* end of On-chip Peripheral Drivers */
/* Board extended module Drivers */
/* end of Hardware Drivers Config */
#endif
+184
View File
@@ -0,0 +1,184 @@
import os
# toolchains options
ARCH='arm'
CPU='cortex-m4'
CROSS_TOOL='gcc'
# bsp lib config
BSP_LIBRARY_TYPE = None
if os.getenv('RTT_CC'):
CROSS_TOOL = os.getenv('RTT_CC')
if os.getenv('RTT_ROOT'):
RTT_ROOT = os.getenv('RTT_ROOT')
# cross_tool provides the cross compiler
# EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR
if CROSS_TOOL == 'gcc':
PLATFORM = 'gcc'
EXEC_PATH = r'/usr/bin'
elif CROSS_TOOL == 'keil':
PLATFORM = 'armcc'
EXEC_PATH = r'C:/Keil_v5'
elif CROSS_TOOL == 'iar':
PLATFORM = 'iccarm'
EXEC_PATH = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.3'
if os.getenv('RTT_EXEC_PATH'):
EXEC_PATH = os.getenv('RTT_EXEC_PATH')
BUILD = 'debug'
if PLATFORM == 'gcc':
# toolchains
PREFIX = 'arm-none-eabi-'
CC = PREFIX + 'gcc'
AS = PREFIX + 'gcc'
AR = PREFIX + 'ar'
CXX = PREFIX + 'g++'
LINK = PREFIX + 'gcc'
TARGET_EXT = 'elf'
SIZE = PREFIX + 'size'
OBJDUMP = PREFIX + 'objdump'
OBJCPY = PREFIX + 'objcopy'
DEVICE = ' -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections'
CFLAGS = DEVICE + ' -Dgcc'
AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb '
LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.lds'
CPATH = ''
LPATH = ''
if BUILD == 'debug':
CFLAGS += ' -O0 -gdwarf-2 -g'
AFLAGS += ' -gdwarf-2'
else:
CFLAGS += ' -O2'
CXXFLAGS = CFLAGS
POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n'
elif PLATFORM == 'armcc':
# toolchains
CC = 'armcc'
CXX = 'armcc'
AS = 'armasm'
AR = 'armar'
LINK = 'armlink'
TARGET_EXT = 'axf'
DEVICE = ' --cpu Cortex-M4.fp '
CFLAGS = '-c ' + DEVICE + ' --apcs=interwork --c99'
AFLAGS = DEVICE + ' --apcs=interwork '
LFLAGS = DEVICE + ' --scatter "board\linker_scripts\link.sct" --info sizes --info totals --info unused --info veneers --list rt-thread.map --strict'
CFLAGS += ' -I' + EXEC_PATH + '/ARM/ARMCC/include'
LFLAGS += ' --libpath=' + EXEC_PATH + '/ARM/ARMCC/lib'
CFLAGS += ' -D__MICROLIB '
AFLAGS += ' --pd "__MICROLIB SETA 1" '
LFLAGS += ' --library_type=microlib '
EXEC_PATH += '/ARM/ARMCC/bin/'
if BUILD == 'debug':
CFLAGS += ' -g -O0'
AFLAGS += ' -g'
else:
CFLAGS += ' -O2'
CXXFLAGS = CFLAGS
CFLAGS += ' -std=c99'
POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET'
elif PLATFORM == 'armclang':
# toolchains
CC = 'armclang'
CXX = 'armclang'
AS = 'armasm'
AR = 'armar'
LINK = 'armlink'
TARGET_EXT = 'axf'
DEVICE = ' --cpu Cortex-M4.fp '
CFLAGS = ' --target=arm-arm-none-eabi -mcpu=cortex-m4 '
CFLAGS += ' -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 '
CFLAGS += ' -mfloat-abi=hard -c -fno-rtti -funsigned-char -fshort-enums -fshort-wchar '
CFLAGS += ' -gdwarf-3 -ffunction-sections '
AFLAGS = DEVICE + ' --apcs=interwork '
LFLAGS = DEVICE + ' --info sizes --info totals --info unused --info veneers '
LFLAGS += ' --list rt-thread.map '
LFLAGS += r' --strict --scatter "board\linker_scripts\link.sct" '
CFLAGS += ' -I' + EXEC_PATH + '/ARM/ARMCLANG/include'
LFLAGS += ' --libpath=' + EXEC_PATH + '/ARM/ARMCLANG/lib'
EXEC_PATH += '/ARM/ARMCLANG/bin/'
if BUILD == 'debug':
CFLAGS += ' -g -O1' # armclang recommend
AFLAGS += ' -g'
else:
CFLAGS += ' -O2'
CXXFLAGS = CFLAGS
CFLAGS += ' -std=c99'
POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET'
elif PLATFORM == 'iccarm':
# toolchains
CC = 'iccarm'
CXX = 'iccarm'
AS = 'iasmarm'
AR = 'iarchive'
LINK = 'ilinkarm'
TARGET_EXT = 'out'
DEVICE = '-Dewarm'
CFLAGS = DEVICE
CFLAGS += ' --diag_suppress Pa050'
CFLAGS += ' --no_cse'
CFLAGS += ' --no_unroll'
CFLAGS += ' --no_inline'
CFLAGS += ' --no_code_motion'
CFLAGS += ' --no_tbaa'
CFLAGS += ' --no_clustering'
CFLAGS += ' --no_scheduling'
CFLAGS += ' --endian=little'
CFLAGS += ' --cpu=Cortex-M4'
CFLAGS += ' -e'
CFLAGS += ' --fpu=VFPv4_sp'
CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"'
CFLAGS += ' --silent'
AFLAGS = DEVICE
AFLAGS += ' -s+'
AFLAGS += ' -w+'
AFLAGS += ' -r'
AFLAGS += ' --cpu Cortex-M4'
AFLAGS += ' --fpu VFPv4_sp'
AFLAGS += ' -S'
if BUILD == 'debug':
CFLAGS += ' --debug'
CFLAGS += ' -On'
else:
CFLAGS += ' -Oh'
LFLAGS = ' --config "board/linker_scripts/link.icf"'
LFLAGS += ' --entry __iar_program_start'
CXXFLAGS = CFLAGS
EXEC_PATH = EXEC_PATH + '/arm/bin/'
POST_ACTION = 'ielftool --bin $TARGET rtthread.bin'
def dist_handle(BSP_ROOT, dist_dir):
import sys
cwd_path = os.getcwd()
sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools'))
from sdk_dist import dist_do_building
dist_do_building(BSP_ROOT, dist_dir)
+390
View File
@@ -0,0 +1,390 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_projx.xsd">
<SchemaVersion>2.1</SchemaVersion>
<Header>### uVision Project, (C) Keil Software</Header>
<Targets>
<Target>
<TargetName>rt-thread</TargetName>
<ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName>
<uAC6>0</uAC6>
<TargetOption>
<TargetCommonOption>
<Device>STM32F405RG</Device>
<Vendor>STMicroelectronics</Vendor>
<PackID>Keil.STM32F4xx_DFP.3.1.0</PackID>
<PackURL>https://www.keil.com/pack/</PackURL>
<Cpu>IRAM(0x20000000-0x2001FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) CPUTYPE("Cortex-M4") FPU2</Cpu>
<FlashUtilSpec></FlashUtilSpec>
<StartupFile>"Startup\ST\STM32F4xx\startup_stm32f40_41xxx.s" ("STM32F40/41xxx Startup Code")</StartupFile>
<FlashDriverDll>UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0STM32F4xx_1024 -FS08000000 -FL0100000)</FlashDriverDll>
<DeviceId>6100</DeviceId>
<RegisterFile>stm32f4xx.h</RegisterFile>
<MemoryEnv></MemoryEnv>
<Cmp></Cmp>
<Asm></Asm>
<Linker></Linker>
<OHString></OHString>
<InfinionOptionDll></InfinionOptionDll>
<SLE66CMisc>-DSTM32F40_41xxx</SLE66CMisc>
<SLE66AMisc></SLE66AMisc>
<SLE66LinkerMisc></SLE66LinkerMisc>
<SFDFile>SFD\ST\STM32F4xx\STM32F40x.sfr</SFDFile>
<bCustSvd>0</bCustSvd>
<UseEnv>0</UseEnv>
<BinPath></BinPath>
<IncludePath></IncludePath>
<LibPath></LibPath>
<RegisterFilePath>ST\STM32F4xx\</RegisterFilePath>
<DBRegisterFilePath>ST\STM32F4xx\</DBRegisterFilePath>
<TargetStatus>
<Error>0</Error>
<ExitCodeStop>0</ExitCodeStop>
<ButtonStop>0</ButtonStop>
<NotGenerated>0</NotGenerated>
<InvalidFlash>1</InvalidFlash>
</TargetStatus>
<OutputDirectory>.\build\keil\Obj\</OutputDirectory>
<OutputName>rt-thread</OutputName>
<CreateExecutable>1</CreateExecutable>
<CreateLib>0</CreateLib>
<CreateHexFile>1</CreateHexFile>
<DebugInformation>1</DebugInformation>
<BrowseInformation>0</BrowseInformation>
<ListingPath>.\build\keil\List\</ListingPath>
<HexFormatSelection>1</HexFormatSelection>
<Merge32K>0</Merge32K>
<CreateBatchFile>0</CreateBatchFile>
<BeforeCompile>
<RunUserProg1>0</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name></UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopU1X>0</nStopU1X>
<nStopU2X>0</nStopU2X>
</BeforeCompile>
<BeforeMake>
<RunUserProg1>0</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name></UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopB1X>0</nStopB1X>
<nStopB2X>0</nStopB2X>
</BeforeMake>
<AfterMake>
<RunUserProg1>1</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name>fromelf --bin !L -o @L.bin</UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopA1X>0</nStopA1X>
<nStopA2X>0</nStopA2X>
</AfterMake>
<SelectedForBatchBuild>0</SelectedForBatchBuild>
<SVCSIdString></SVCSIdString>
</TargetCommonOption>
<CommonProperty>
<UseCPPCompiler>0</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>0</AlwaysBuild>
<GenerateAssemblyFile>0</GenerateAssemblyFile>
<AssembleAssemblyFile>0</AssembleAssemblyFile>
<PublicsOnly>0</PublicsOnly>
<StopOnExitCode>3</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<DllOption>
<SimDllName>SARMCM3.DLL</SimDllName>
<SimDllArguments>-MPU -REMAP</SimDllArguments>
<SimDlgDll>DCM.DLL</SimDlgDll>
<SimDlgDllArguments>-pCM4</SimDlgDllArguments>
<TargetDllName>SARMCM3.DLL</TargetDllName>
<TargetDllArguments>-MPU</TargetDllArguments>
<TargetDlgDll>TCM.DLL</TargetDlgDll>
<TargetDlgDllArguments>-pCM4</TargetDlgDllArguments>
</DllOption>
<DebugOption>
<OPTHX>
<HexSelection>1</HexSelection>
<HexRangeLowAddress>0</HexRangeLowAddress>
<HexRangeHighAddress>0</HexRangeHighAddress>
<HexOffset>0</HexOffset>
<Oh166RecLen>16</Oh166RecLen>
</OPTHX>
</DebugOption>
<Utilities>
<Flash1>
<UseTargetDll>1</UseTargetDll>
<UseExternalTool>0</UseExternalTool>
<RunIndependent>0</RunIndependent>
<UpdateFlashBeforeDebugging>1</UpdateFlashBeforeDebugging>
<Capability>1</Capability>
<DriverSelection>4096</DriverSelection>
</Flash1>
<bUseTDR>1</bUseTDR>
<Flash2>BIN\UL2CM3.DLL</Flash2>
<Flash3>"" ()</Flash3>
<Flash4></Flash4>
<pFcarmOut></pFcarmOut>
<pFcarmGrp></pFcarmGrp>
<pFcArmRoot></pFcArmRoot>
<FcArmLst>0</FcArmLst>
</Utilities>
<TargetArmAds>
<ArmAdsMisc>
<GenerateListings>0</GenerateListings>
<asHll>1</asHll>
<asAsm>1</asAsm>
<asMacX>1</asMacX>
<asSyms>1</asSyms>
<asFals>1</asFals>
<asDbgD>1</asDbgD>
<asForm>1</asForm>
<ldLst>0</ldLst>
<ldmm>1</ldmm>
<ldXref>1</ldXref>
<BigEnd>0</BigEnd>
<AdsALst>1</AdsALst>
<AdsACrf>1</AdsACrf>
<AdsANop>0</AdsANop>
<AdsANot>0</AdsANot>
<AdsLLst>1</AdsLLst>
<AdsLmap>1</AdsLmap>
<AdsLcgr>1</AdsLcgr>
<AdsLsym>1</AdsLsym>
<AdsLszi>1</AdsLszi>
<AdsLtoi>1</AdsLtoi>
<AdsLsun>1</AdsLsun>
<AdsLven>1</AdsLven>
<AdsLsxf>1</AdsLsxf>
<RvctClst>0</RvctClst>
<GenPPlst>0</GenPPlst>
<AdsCpuType>"Cortex-M4"</AdsCpuType>
<RvctDeviceName></RvctDeviceName>
<mOS>0</mOS>
<uocRom>0</uocRom>
<uocRam>0</uocRam>
<hadIROM>1</hadIROM>
<hadIRAM>1</hadIRAM>
<hadXRAM>0</hadXRAM>
<uocXRam>0</uocXRam>
<RvdsVP>1</RvdsVP>
<RvdsMve>0</RvdsMve>
<RvdsCdeCp>0</RvdsCdeCp>
<hadIRAM2>1</hadIRAM2>
<hadIROM2>0</hadIROM2>
<StupSel>8</StupSel>
<useUlib>0</useUlib>
<EndSel>0</EndSel>
<uLtcg>0</uLtcg>
<nSecure>0</nSecure>
<RoSelD>3</RoSelD>
<RwSelD>3</RwSelD>
<CodeSel>0</CodeSel>
<OptFeed>0</OptFeed>
<NoZi1>0</NoZi1>
<NoZi2>0</NoZi2>
<NoZi3>0</NoZi3>
<NoZi4>0</NoZi4>
<NoZi5>0</NoZi5>
<Ro1Chk>0</Ro1Chk>
<Ro2Chk>0</Ro2Chk>
<Ro3Chk>0</Ro3Chk>
<Ir1Chk>1</Ir1Chk>
<Ir2Chk>0</Ir2Chk>
<Ra1Chk>0</Ra1Chk>
<Ra2Chk>0</Ra2Chk>
<Ra3Chk>0</Ra3Chk>
<Im1Chk>1</Im1Chk>
<Im2Chk>0</Im2Chk>
<OnChipMemories>
<Ocm1>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm1>
<Ocm2>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm2>
<Ocm3>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm3>
<Ocm4>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm4>
<Ocm5>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm5>
<Ocm6>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm6>
<IRAM>
<Type>0</Type>
<StartAddress>0x20000000</StartAddress>
<Size>0x20000</Size>
</IRAM>
<IROM>
<Type>1</Type>
<StartAddress>0x8000000</StartAddress>
<Size>0x100000</Size>
</IROM>
<XRAM>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</XRAM>
<OCR_RVCT1>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT1>
<OCR_RVCT2>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT2>
<OCR_RVCT3>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT3>
<OCR_RVCT4>
<Type>1</Type>
<StartAddress>0x8000000</StartAddress>
<Size>0x100000</Size>
</OCR_RVCT4>
<OCR_RVCT5>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT5>
<OCR_RVCT6>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT6>
<OCR_RVCT7>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT7>
<OCR_RVCT8>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT8>
<OCR_RVCT9>
<Type>0</Type>
<StartAddress>0x20000000</StartAddress>
<Size>0x20000</Size>
</OCR_RVCT9>
<OCR_RVCT10>
<Type>0</Type>
<StartAddress>0x10000000</StartAddress>
<Size>0x10000</Size>
</OCR_RVCT10>
</OnChipMemories>
<RvctStartVector></RvctStartVector>
</ArmAdsMisc>
<Cads>
<interw>1</interw>
<Optim>1</Optim>
<oTime>0</oTime>
<SplitLS>0</SplitLS>
<OneElfS>1</OneElfS>
<Strict>0</Strict>
<EnumInt>0</EnumInt>
<PlainCh>0</PlainCh>
<Ropi>0</Ropi>
<Rwpi>0</Rwpi>
<wLevel>2</wLevel>
<uThumb>0</uThumb>
<uSurpInc>0</uSurpInc>
<uC99>1</uC99>
<uGnu>0</uGnu>
<useXO>0</useXO>
<v6Lang>1</v6Lang>
<v6LangP>1</v6LangP>
<vShortEn>1</vShortEn>
<vShortWch>1</vShortWch>
<v6Lto>0</v6Lto>
<v6WtE>0</v6WtE>
<v6Rtti>0</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define>STM32F405xx, USE_HAL_DRIVER</Define>
<Undefine></Undefine>
<IncludePath>.;..\..\..\include;applications;.;board;board\CubeMX_Config\Inc;..\libraries\HAL_Drivers;..\libraries\HAL_Drivers\config;packages\led;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\finsh;..\libraries\STM32F4xx_HAL\STM32F4xx_HAL_Driver\Inc;..\libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Include;..\libraries\STM32F4xx_HAL\CMSIS\Include</IncludePath>
</VariousControls>
</Cads>
<Aads>
<interw>1</interw>
<Ropi>0</Ropi>
<Rwpi>0</Rwpi>
<thumb>0</thumb>
<SplitLS>0</SplitLS>
<SwStkChk>0</SwStkChk>
<NoWarn>0</NoWarn>
<uSurpInc>0</uSurpInc>
<useXO>0</useXO>
<ClangAsOpt>1</ClangAsOpt>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Aads>
<LDads>
<umfTarg>0</umfTarg>
<Ropi>0</Ropi>
<Rwpi>0</Rwpi>
<noStLib>0</noStLib>
<RepFail>1</RepFail>
<useFile>0</useFile>
<TextAddressRange>0x08000000</TextAddressRange>
<DataAddressRange>0x20000000</DataAddressRange>
<pXoBase></pXoBase>
<ScatterFile>.\board\linker_scripts\link.sct</ScatterFile>
<IncludeLibs></IncludeLibs>
<IncludeLibsPath></IncludeLibsPath>
<Misc>--keep *.o(.rti_fn.*) --keep *.o(FSymTab)</Misc>
<LinkerInputFile></LinkerInputFile>
<DisabledWarnings></DisabledWarnings>
</LDads>
</TargetArmAds>
</TargetOption>
</Target>
</Targets>
<RTE>
<apis/>
<components/>
<files/>
</RTE>
</Project>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

+32
View File
@@ -0,0 +1,32 @@
del *.bak /s
del *.ddk /s
del *.edk /s
del *.lst /s
del *.lnp /s
del *.mpf /s
del *.mpj /s
del *.obj /s
del *.omf /s
::del *.opt /s ::不允许删除JLINK的设置
del *.plg /s
del *.rpt /s
del *.tmp /s
del *.__i /s
del *.crf /s
del *.o /s
del *.d /s
del *.axf /s
del *.tra /s
del *.dep /s
del JLinkLog.txt /s
del *.iex /s
del *.htm /s
del *.sct /s
del *.map /s
del *.dbgconf /s
del *.uvoptx /s
del *.uvguix.* /s
exit
+12
View File
@@ -0,0 +1,12 @@
import os
from building import *
objs = []
cwd = GetCurrentDir()
list = os.listdir(cwd)
for item in list:
if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
objs = objs + SConscript(os.path.join(item, 'SConscript'))
Return('objs')
+894
View File
@@ -0,0 +1,894 @@
/**************************************************************************//**
* @file cmsis_armcc.h
* @brief CMSIS compiler ARMCC (Arm Compiler 5) header file
* @version V5.4.0
* @date 20. January 2023
******************************************************************************/
/*
* Copyright (c) 2009-2023 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CMSIS_ARMCC_H
#define __CMSIS_ARMCC_H
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677)
#error "Please use Arm Compiler Toolchain V4.0.677 or later!"
#endif
/* CMSIS compiler control architecture macros */
#if ((defined (__TARGET_ARCH_6_M ) && (__TARGET_ARCH_6_M == 1)) || \
(defined (__TARGET_ARCH_6S_M ) && (__TARGET_ARCH_6S_M == 1)) )
#define __ARM_ARCH_6M__ 1
#endif
#if (defined (__TARGET_ARCH_7_M ) && (__TARGET_ARCH_7_M == 1))
#define __ARM_ARCH_7M__ 1
#endif
#if (defined (__TARGET_ARCH_7E_M) && (__TARGET_ARCH_7E_M == 1))
#define __ARM_ARCH_7EM__ 1
#endif
/* __ARM_ARCH_8M_BASE__ not applicable */
/* __ARM_ARCH_8M_MAIN__ not applicable */
/* __ARM_ARCH_8_1M_MAIN__ not applicable */
/* CMSIS compiler control DSP macros */
#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
#define __ARM_FEATURE_DSP 1
#endif
/* CMSIS compiler specific defines */
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE __inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static __inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE static __forceinline
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __declspec(noreturn)
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __attribute__((packed))
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT __packed struct
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION __packed union
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
#define __UNALIGNED_UINT32(x) (*((__packed uint32_t *)(x)))
#endif
#ifndef __UNALIGNED_UINT16_WRITE
#define __UNALIGNED_UINT16_WRITE(addr, val) ((*((__packed uint16_t *)(addr))) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
#define __UNALIGNED_UINT16_READ(addr) (*((const __packed uint16_t *)(addr)))
#endif
#ifndef __UNALIGNED_UINT32_WRITE
#define __UNALIGNED_UINT32_WRITE(addr, val) ((*((__packed uint32_t *)(addr))) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
#define __UNALIGNED_UINT32_READ(addr) (*((const __packed uint32_t *)(addr)))
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x)))
#endif
#ifndef __RESTRICT
#define __RESTRICT __restrict
#endif
#ifndef __COMPILER_BARRIER
#define __COMPILER_BARRIER() __memory_changed()
#endif
#ifndef __NO_INIT
#define __NO_INIT __attribute__ ((section (".bss.noinit"), zero_init))
#endif
#ifndef __ALIAS
#define __ALIAS(x) __attribute__ ((alias(x)))
#endif
/* ######################### Startup and Lowlevel Init ######################## */
#ifndef __PROGRAM_START
#define __PROGRAM_START __main
#endif
#ifndef __INITIAL_SP
#define __INITIAL_SP Image$$ARM_LIB_STACK$$ZI$$Limit
#endif
#ifndef __STACK_LIMIT
#define __STACK_LIMIT Image$$ARM_LIB_STACK$$ZI$$Base
#endif
#ifndef __VECTOR_TABLE
#define __VECTOR_TABLE __Vectors
#endif
#ifndef __VECTOR_TABLE_ATTRIBUTE
#define __VECTOR_TABLE_ATTRIBUTE __attribute__((used, section("RESET")))
#endif
/* ########################## Core Instruction Access ######################### */
/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
Access to dedicated instructions
@{
*/
/**
\brief No Operation
\details No Operation does nothing. This instruction can be used for code alignment purposes.
*/
#define __NOP __nop
/**
\brief Wait For Interrupt
\details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs.
*/
#define __WFI __wfi
/**
\brief Wait For Event
\details Wait For Event is a hint instruction that permits the processor to enter
a low-power state until one of a number of events occurs.
*/
#define __WFE __wfe
/**
\brief Send Event
\details Send Event is a hint instruction. It causes an event to be signaled to the CPU.
*/
#define __SEV __sev
/**
\brief Instruction Synchronization Barrier
\details Instruction Synchronization Barrier flushes the pipeline in the processor,
so that all instructions following the ISB are fetched from cache or memory,
after the instruction has been completed.
*/
#define __ISB() __isb(0xF)
/**
\brief Data Synchronization Barrier
\details Acts as a special kind of Data Memory Barrier.
It completes when all explicit memory accesses before this instruction complete.
*/
#define __DSB() __dsb(0xF)
/**
\brief Data Memory Barrier
\details Ensures the apparent order of the explicit memory operations before
and after the instruction, without ensuring their completion.
*/
#define __DMB() __dmb(0xF)
/**
\brief Reverse byte order (32 bit)
\details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412.
\param [in] value Value to reverse
\return Reversed value
*/
#define __REV __rev
/**
\brief Reverse byte order (16 bit)
\details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
\param [in] value Value to reverse
\return Reversed value
*/
#ifndef __NO_EMBEDDED_ASM
__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
{
rev16 r0, r0
bx lr
}
#endif
/**
\brief Reverse byte order (16 bit)
\details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
\param [in] value Value to reverse
\return Reversed value
*/
#ifndef __NO_EMBEDDED_ASM
__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int16_t __REVSH(int16_t value)
{
revsh r0, r0
bx lr
}
#endif
/**
\brief Rotate Right in unsigned value (32 bit)
\details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
\param [in] op1 Value to rotate
\param [in] op2 Number of Bits to rotate
\return Rotated value
*/
#define __ROR __ror
/**
\brief Breakpoint
\details Causes the processor to enter Debug state.
Debug tools can use this to investigate system state when the instruction at a particular address is reached.
\param [in] value is ignored by the processor.
If required, a debugger can use it to store additional information about the breakpoint.
*/
#define __BKPT(value) __breakpoint(value)
/**
\brief Reverse bit order of value
\details Reverses the bit order of the given value.
\param [in] value Value to reverse
\return Reversed value
*/
#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
#define __RBIT __rbit
#else
__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
{
uint32_t result;
uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */
result = value; /* r will be reversed bits of v; first get LSB of v */
for (value >>= 1U; value != 0U; value >>= 1U)
{
result <<= 1U;
result |= value & 1U;
s--;
}
result <<= s; /* shift when v's highest bits are zero */
return result;
}
#endif
/**
\brief Count leading zeros
\details Counts the number of leading zeros of a data value.
\param [in] value Value to count the leading zeros
\return number of leading zeros in value
*/
#define __CLZ __clz
#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
/**
\brief LDR Exclusive (8 bit)
\details Executes a exclusive LDR instruction for 8 bit value.
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr))
#else
#define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop")
#endif
/**
\brief LDR Exclusive (16 bit)
\details Executes a exclusive LDR instruction for 16 bit values.
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr))
#else
#define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop")
#endif
/**
\brief LDR Exclusive (32 bit)
\details Executes a exclusive LDR instruction for 32 bit values.
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr))
#else
#define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop")
#endif
/**
\brief STR Exclusive (8 bit)
\details Executes a exclusive STR instruction for 8 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
#define __STREXB(value, ptr) __strex(value, ptr)
#else
#define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
#endif
/**
\brief STR Exclusive (16 bit)
\details Executes a exclusive STR instruction for 16 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
#define __STREXH(value, ptr) __strex(value, ptr)
#else
#define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
#endif
/**
\brief STR Exclusive (32 bit)
\details Executes a exclusive STR instruction for 32 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
#define __STREXW(value, ptr) __strex(value, ptr)
#else
#define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
#endif
/**
\brief Remove the exclusive lock
\details Removes the exclusive lock which is created by LDREX.
*/
#define __CLREX __clrex
/**
\brief Signed Saturate
\details Saturates a signed value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (1..32)
\return Saturated value
*/
#define __SSAT __ssat
/**
\brief Unsigned Saturate
\details Saturates an unsigned value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (0..31)
\return Saturated value
*/
#define __USAT __usat
/**
\brief Rotate Right with Extend (32 bit)
\details Moves each bit of a bitstring right by one bit.
The carry input is shifted in at the left end of the bitstring.
\param [in] value Value to rotate
\return Rotated value
*/
#ifndef __NO_EMBEDDED_ASM
__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value)
{
rrx r0, r0
bx lr
}
#endif
/**
\brief LDRT Unprivileged (8 bit)
\details Executes a Unprivileged LDRT instruction for 8 bit value.
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr))
/**
\brief LDRT Unprivileged (16 bit)
\details Executes a Unprivileged LDRT instruction for 16 bit values.
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr))
/**
\brief LDRT Unprivileged (32 bit)
\details Executes a Unprivileged LDRT instruction for 32 bit values.
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr))
/**
\brief STRT Unprivileged (8 bit)
\details Executes a Unprivileged STRT instruction for 8 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
*/
#define __STRBT(value, ptr) __strt(value, ptr)
/**
\brief STRT Unprivileged (16 bit)
\details Executes a Unprivileged STRT instruction for 16 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
*/
#define __STRHT(value, ptr) __strt(value, ptr)
/**
\brief STRT Unprivileged (32 bit)
\details Executes a Unprivileged STRT instruction for 32 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
*/
#define __STRT(value, ptr) __strt(value, ptr)
#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
/**
\brief Signed Saturate
\details Saturates a signed value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (1..32)
\return Saturated value
*/
__attribute__((always_inline)) __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat)
{
if ((sat >= 1U) && (sat <= 32U))
{
const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
const int32_t min = -1 - max ;
if (val > max)
{
return max;
}
else if (val < min)
{
return min;
}
}
return val;
}
/**
\brief Unsigned Saturate
\details Saturates an unsigned value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (0..31)
\return Saturated value
*/
__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat)
{
if (sat <= 31U)
{
const uint32_t max = ((1U << sat) - 1U);
if (val > (int32_t)max)
{
return max;
}
else if (val < 0)
{
return 0U;
}
}
return (uint32_t)val;
}
#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
/* ########################### Core Function Access ########################### */
/** \ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
@{
*/
/**
\brief Enable IRQ Interrupts
\details Enables IRQ interrupts by clearing special-purpose register PRIMASK.
Can only be executed in Privileged modes.
*/
/* intrinsic void __enable_irq(); */
/**
\brief Disable IRQ Interrupts
\details Disables IRQ interrupts by setting special-purpose register PRIMASK.
Can only be executed in Privileged modes.
*/
/* intrinsic void __disable_irq(); */
/**
\brief Get Control Register
\details Returns the content of the Control Register.
\return Control Register value
*/
__STATIC_INLINE uint32_t __get_CONTROL(void)
{
register uint32_t __regControl __ASM("control");
return(__regControl);
}
/**
\brief Set Control Register
\details Writes the given value to the Control Register.
\param [in] control Control Register value to set
*/
__STATIC_INLINE void __set_CONTROL(uint32_t control)
{
register uint32_t __regControl __ASM("control");
__regControl = control;
__ISB();
}
/**
\brief Get IPSR Register
\details Returns the content of the IPSR Register.
\return IPSR Register value
*/
__STATIC_INLINE uint32_t __get_IPSR(void)
{
register uint32_t __regIPSR __ASM("ipsr");
return(__regIPSR);
}
/**
\brief Get APSR Register
\details Returns the content of the APSR Register.
\return APSR Register value
*/
__STATIC_INLINE uint32_t __get_APSR(void)
{
register uint32_t __regAPSR __ASM("apsr");
return(__regAPSR);
}
/**
\brief Get xPSR Register
\details Returns the content of the xPSR Register.
\return xPSR Register value
*/
__STATIC_INLINE uint32_t __get_xPSR(void)
{
register uint32_t __regXPSR __ASM("xpsr");
return(__regXPSR);
}
/**
\brief Get Process Stack Pointer
\details Returns the current value of the Process Stack Pointer (PSP).
\return PSP Register value
*/
__STATIC_INLINE uint32_t __get_PSP(void)
{
register uint32_t __regProcessStackPointer __ASM("psp");
return(__regProcessStackPointer);
}
/**
\brief Set Process Stack Pointer
\details Assigns the given value to the Process Stack Pointer (PSP).
\param [in] topOfProcStack Process Stack Pointer value to set
*/
__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
{
register uint32_t __regProcessStackPointer __ASM("psp");
__regProcessStackPointer = topOfProcStack;
}
/**
\brief Get Main Stack Pointer
\details Returns the current value of the Main Stack Pointer (MSP).
\return MSP Register value
*/
__STATIC_INLINE uint32_t __get_MSP(void)
{
register uint32_t __regMainStackPointer __ASM("msp");
return(__regMainStackPointer);
}
/**
\brief Set Main Stack Pointer
\details Assigns the given value to the Main Stack Pointer (MSP).
\param [in] topOfMainStack Main Stack Pointer value to set
*/
__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
{
register uint32_t __regMainStackPointer __ASM("msp");
__regMainStackPointer = topOfMainStack;
}
/**
\brief Get Priority Mask
\details Returns the current state of the priority mask bit from the Priority Mask Register.
\return Priority Mask value
*/
__STATIC_INLINE uint32_t __get_PRIMASK(void)
{
register uint32_t __regPriMask __ASM("primask");
return(__regPriMask);
}
/**
\brief Set Priority Mask
\details Assigns the given value to the Priority Mask Register.
\param [in] priMask Priority Mask
*/
__STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
{
register uint32_t __regPriMask __ASM("primask");
__regPriMask = (priMask);
}
#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
/**
\brief Enable FIQ
\details Enables FIQ interrupts by clearing special-purpose register FAULTMASK.
Can only be executed in Privileged modes.
*/
#define __enable_fault_irq __enable_fiq
/**
\brief Disable FIQ
\details Disables FIQ interrupts by setting special-purpose register FAULTMASK.
Can only be executed in Privileged modes.
*/
#define __disable_fault_irq __disable_fiq
/**
\brief Get Base Priority
\details Returns the current value of the Base Priority register.
\return Base Priority register value
*/
__STATIC_INLINE uint32_t __get_BASEPRI(void)
{
register uint32_t __regBasePri __ASM("basepri");
return(__regBasePri);
}
/**
\brief Set Base Priority
\details Assigns the given value to the Base Priority register.
\param [in] basePri Base Priority value to set
*/
__STATIC_INLINE void __set_BASEPRI(uint32_t basePri)
{
register uint32_t __regBasePri __ASM("basepri");
__regBasePri = (basePri & 0xFFU);
}
/**
\brief Set Base Priority with condition
\details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled,
or the new value increases the BASEPRI priority level.
\param [in] basePri Base Priority value to set
*/
__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri)
{
register uint32_t __regBasePriMax __ASM("basepri_max");
__regBasePriMax = (basePri & 0xFFU);
}
/**
\brief Get Fault Mask
\details Returns the current value of the Fault Mask register.
\return Fault Mask register value
*/
__STATIC_INLINE uint32_t __get_FAULTMASK(void)
{
register uint32_t __regFaultMask __ASM("faultmask");
return(__regFaultMask);
}
/**
\brief Set Fault Mask
\details Assigns the given value to the Fault Mask register.
\param [in] faultMask Fault Mask value to set
*/
__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
{
register uint32_t __regFaultMask __ASM("faultmask");
__regFaultMask = (faultMask & (uint32_t)1U);
}
#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
/**
\brief Get FPSCR
\details Returns the current value of the Floating Point Status/Control register.
\return Floating Point Status/Control register value
*/
__STATIC_INLINE uint32_t __get_FPSCR(void)
{
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
(defined (__FPU_USED ) && (__FPU_USED == 1U)) )
register uint32_t __regfpscr __ASM("fpscr");
return(__regfpscr);
#else
return(0U);
#endif
}
/**
\brief Set FPSCR
\details Assigns the given value to the Floating Point Status/Control register.
\param [in] fpscr Floating Point Status/Control value to set
*/
__STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
{
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
(defined (__FPU_USED ) && (__FPU_USED == 1U)) )
register uint32_t __regfpscr __ASM("fpscr");
__regfpscr = (fpscr);
#else
(void)fpscr;
#endif
}
/*@} end of CMSIS_Core_RegAccFunctions */
/* ################### Compiler specific Intrinsics ########################### */
/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
Access to dedicated SIMD instructions
@{
*/
#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
#define __SADD8 __sadd8
#define __QADD8 __qadd8
#define __SHADD8 __shadd8
#define __UADD8 __uadd8
#define __UQADD8 __uqadd8
#define __UHADD8 __uhadd8
#define __SSUB8 __ssub8
#define __QSUB8 __qsub8
#define __SHSUB8 __shsub8
#define __USUB8 __usub8
#define __UQSUB8 __uqsub8
#define __UHSUB8 __uhsub8
#define __SADD16 __sadd16
#define __QADD16 __qadd16
#define __SHADD16 __shadd16
#define __UADD16 __uadd16
#define __UQADD16 __uqadd16
#define __UHADD16 __uhadd16
#define __SSUB16 __ssub16
#define __QSUB16 __qsub16
#define __SHSUB16 __shsub16
#define __USUB16 __usub16
#define __UQSUB16 __uqsub16
#define __UHSUB16 __uhsub16
#define __SASX __sasx
#define __QASX __qasx
#define __SHASX __shasx
#define __UASX __uasx
#define __UQASX __uqasx
#define __UHASX __uhasx
#define __SSAX __ssax
#define __QSAX __qsax
#define __SHSAX __shsax
#define __USAX __usax
#define __UQSAX __uqsax
#define __UHSAX __uhsax
#define __USAD8 __usad8
#define __USADA8 __usada8
#define __SSAT16 __ssat16
#define __USAT16 __usat16
#define __UXTB16 __uxtb16
#define __UXTAB16 __uxtab16
#define __SXTB16 __sxtb16
#define __SXTAB16 __sxtab16
#define __SMUAD __smuad
#define __SMUADX __smuadx
#define __SMLAD __smlad
#define __SMLADX __smladx
#define __SMLALD __smlald
#define __SMLALDX __smlaldx
#define __SMUSD __smusd
#define __SMUSDX __smusdx
#define __SMLSD __smlsd
#define __SMLSDX __smlsdx
#define __SMLSLD __smlsld
#define __SMLSLDX __smlsldx
#define __SEL __sel
#define __QADD __qadd
#define __QSUB __qsub
#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \
((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) )
#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \
((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) )
#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \
((int64_t)(ARG3) << 32U) ) >> 32U))
#define __SXTB16_RORn(ARG1, ARG2) __SXTB16(__ROR(ARG1, ARG2))
#define __SXTAB16_RORn(ARG1, ARG2, ARG3) __SXTAB16(ARG1, __ROR(ARG2, ARG3))
#endif /* ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
/*@} end of group CMSIS_SIMD_intrinsics */
#endif /* __CMSIS_ARMCC_H */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+303
View File
@@ -0,0 +1,303 @@
/**************************************************************************//**
* @file cmsis_compiler.h
* @brief CMSIS compiler generic header file
* @version V5.3.0
* @date 04. April 2023
******************************************************************************/
/*
* Copyright (c) 2009-2023 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CMSIS_COMPILER_H
#define __CMSIS_COMPILER_H
#include <stdint.h>
/*
* Arm Compiler 4/5
*/
#if defined ( __CC_ARM )
#include "cmsis_armcc.h"
/*
* Arm Compiler 6.6 LTM (armclang)
*/
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) && (__ARMCC_VERSION < 6100100)
#include "cmsis_armclang_ltm.h"
/*
* Arm Compiler above 6.10.1 (armclang)
*/
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100)
#include "cmsis_armclang.h"
/*
* TI Arm Clang Compiler (tiarmclang)
*/
#elif defined (__ti__)
#include "cmsis_tiarmclang.h"
/*
* GNU Compiler
*/
#elif defined ( __GNUC__ )
#include "cmsis_gcc.h"
/*
* IAR Compiler
*/
#elif defined ( __ICCARM__ )
#include <cmsis_iccarm.h>
/*
* TI Arm Compiler (armcl)
*/
#elif defined ( __TI_ARM__ )
#include <cmsis_ccs.h>
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((noreturn))
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __attribute__((packed))
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __attribute__((packed))
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION union __attribute__((packed))
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
struct __attribute__((packed)) T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x)))
#endif
#ifndef __RESTRICT
#define __RESTRICT __restrict
#endif
#ifndef __COMPILER_BARRIER
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
#define __COMPILER_BARRIER() (void)0
#endif
#ifndef __NO_INIT
#define __NO_INIT __attribute__ ((section (".bss.noinit")))
#endif
#ifndef __ALIAS
#define __ALIAS(x) __attribute__ ((alias(x)))
#endif
/*
* TASKING Compiler
*/
#elif defined ( __TASKING__ )
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all intrinsics,
* Including the CMSIS ones.
*/
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((noreturn))
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __packed__
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __packed__
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION union __packed__
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
struct __packed__ T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __align(x)
#endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
#ifndef __COMPILER_BARRIER
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
#define __COMPILER_BARRIER() (void)0
#endif
#ifndef __NO_INIT
#define __NO_INIT __attribute__ ((section (".bss.noinit")))
#endif
#ifndef __ALIAS
#define __ALIAS(x) __attribute__ ((alias(x)))
#endif
/*
* COSMIC Compiler
*/
#elif defined ( __CSMC__ )
#include <cmsis_csm.h>
#ifndef __ASM
#define __ASM _asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
// NO RETURN is automatically detected hence no warning here
#define __NO_RETURN
#endif
#ifndef __USED
#warning No compiler specific solution for __USED. __USED is ignored.
#define __USED
#endif
#ifndef __WEAK
#define __WEAK __weak
#endif
#ifndef __PACKED
#define __PACKED @packed
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT @packed struct
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION @packed union
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
@packed struct T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored.
#define __ALIGNED(x)
#endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
#ifndef __COMPILER_BARRIER
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
#define __COMPILER_BARRIER() (void)0
#endif
#ifndef __NO_INIT
#define __NO_INIT __attribute__ ((section (".bss.noinit")))
#endif
#ifndef __ALIAS
#define __ALIAS(x) __attribute__ ((alias(x)))
#endif
#else
#error Unknown compiler.
#endif
#endif /* __CMSIS_COMPILER_H */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+39
View File
@@ -0,0 +1,39 @@
/**************************************************************************//**
* @file cmsis_version.h
* @brief CMSIS Core(M) Version definitions
* @version V5.0.5
* @date 02. February 2022
******************************************************************************/
/*
* Copyright (c) 2009-2022 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
#ifndef __CMSIS_VERSION_H
#define __CMSIS_VERSION_H
/* CMSIS Version definitions */
#define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */
#define __CM_CMSIS_VERSION_SUB ( 6U) /*!< [15:0] CMSIS Core(M) sub version */
#define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \
__CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */
#endif
+984
View File
@@ -0,0 +1,984 @@
/**************************************************************************//**
* @file core_cm1.h
* @brief CMSIS Cortex-M1 Core Peripheral Access Layer Header File
* @version V1.1.0
* @date 04. April 2023
******************************************************************************/
/*
* Copyright (c) 2009-2023 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
#ifndef __CORE_CM1_H_GENERIC
#define __CORE_CM1_H_GENERIC
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
\page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
CMSIS violates the following MISRA-C:2004 rules:
\li Required Rule 8.5, object/function definition in header file.<br>
Function definitions in header files are used to allow 'inlining'.
\li Required Rule 18.4, declaration of union type or object of union type: '{...}'.<br>
Unions are used for effective representation of core registers.
\li Advisory Rule 19.7, Function-like macro defined.<br>
Function-like macros are used to allow more efficient code.
*/
/*******************************************************************************
* CMSIS definitions
******************************************************************************/
/**
\ingroup Cortex_M1
@{
*/
#include "cmsis_version.h"
/* CMSIS CM1 definitions */
#define __CM1_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
#define __CM1_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
#define __CM1_CMSIS_VERSION ((__CM1_CMSIS_VERSION_MAIN << 16U) | \
__CM1_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
#define __CORTEX_M (1U) /*!< Cortex-M Core */
/** __FPU_USED indicates whether an FPU is used or not.
This core does not support an FPU at all
*/
#define __FPU_USED 0U
#if defined ( __CC_ARM )
#if defined __TARGET_FPU_VFP
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#if defined __ARM_FP
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined (__ti__)
#if defined __ARM_FP
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __GNUC__ )
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __ICCARM__ )
#if defined __ARMVFP__
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __TI_ARM__ )
#if defined __TI_VFP_SUPPORT__
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __TASKING__ )
#if defined __FPU_VFP__
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __CSMC__ )
#if ( __CSMC__ & 0x400U)
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#endif
#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
#ifdef __cplusplus
}
#endif
#endif /* __CORE_CM1_H_GENERIC */
#ifndef __CMSIS_GENERIC
#ifndef __CORE_CM1_H_DEPENDANT
#define __CORE_CM1_H_DEPENDANT
#ifdef __cplusplus
extern "C" {
#endif
/* check device defines and use defaults */
#if defined __CHECK_DEVICE_DEFINES
#ifndef __CM1_REV
#define __CM1_REV 0x0100U
#warning "__CM1_REV not defined in device header file; using default!"
#endif
#ifndef __NVIC_PRIO_BITS
#define __NVIC_PRIO_BITS 2U
#warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
#endif
#ifndef __Vendor_SysTickConfig
#define __Vendor_SysTickConfig 0U
#warning "__Vendor_SysTickConfig not defined in device header file; using default!"
#endif
#endif
/* IO definitions (access restrictions to peripheral registers) */
/**
\defgroup CMSIS_glob_defs CMSIS Global Defines
<strong>IO Type Qualifiers</strong> are used
\li to specify the access to peripheral variables.
\li for automatic generation of peripheral register debug information.
*/
#ifdef __cplusplus
#define __I volatile /*!< Defines 'read only' permissions */
#else
#define __I volatile const /*!< Defines 'read only' permissions */
#endif
#define __O volatile /*!< Defines 'write only' permissions */
#define __IO volatile /*!< Defines 'read / write' permissions */
/* following defines should be used for structure members */
#define __IM volatile const /*! Defines 'read only' structure member permissions */
#define __OM volatile /*! Defines 'write only' structure member permissions */
#define __IOM volatile /*! Defines 'read / write' structure member permissions */
/*@} end of group Cortex_M1 */
/*******************************************************************************
* Register Abstraction
Core Register contain:
- Core Register
- Core NVIC Register
- Core SCB Register
- Core SysTick Register
******************************************************************************/
/**
\defgroup CMSIS_core_register Defines and Type Definitions
\brief Type definitions and defines for Cortex-M processor based devices.
*/
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_CORE Status and Control Registers
\brief Core Register type definitions.
@{
*/
/**
\brief Union type to access the Application Program Status Register (APSR).
*/
typedef union
{
struct
{
uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
uint32_t N:1; /*!< bit: 31 Negative condition code flag */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} APSR_Type;
/* APSR Register Definitions */
#define APSR_N_Pos 31U /*!< APSR: N Position */
#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
#define APSR_Z_Pos 30U /*!< APSR: Z Position */
#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
#define APSR_C_Pos 29U /*!< APSR: C Position */
#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
#define APSR_V_Pos 28U /*!< APSR: V Position */
#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
/**
\brief Union type to access the Interrupt Program Status Register (IPSR).
*/
typedef union
{
struct
{
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} IPSR_Type;
/* IPSR Register Definitions */
#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
/**
\brief Union type to access the Special-Purpose Program Status Registers (xPSR).
*/
typedef union
{
struct
{
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
uint32_t N:1; /*!< bit: 31 Negative condition code flag */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} xPSR_Type;
/* xPSR Register Definitions */
#define xPSR_N_Pos 31U /*!< xPSR: N Position */
#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
#define xPSR_C_Pos 29U /*!< xPSR: C Position */
#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
#define xPSR_V_Pos 28U /*!< xPSR: V Position */
#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
#define xPSR_T_Pos 24U /*!< xPSR: T Position */
#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
/**
\brief Union type to access the Control Registers (CONTROL).
*/
typedef union
{
struct
{
uint32_t _reserved0:1; /*!< bit: 0 Reserved */
uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */
uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} CONTROL_Type;
/* CONTROL Register Definitions */
#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
/*@} end of group CMSIS_CORE */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
\brief Type definitions for the NVIC Registers
@{
*/
/**
\brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
*/
typedef struct
{
__IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
uint32_t RESERVED0[31U];
__IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
uint32_t RSERVED1[31U];
__IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
uint32_t RESERVED2[31U];
__IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
uint32_t RESERVED3[31U];
uint32_t RESERVED4[64U];
__IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
} NVIC_Type;
/*@} end of group CMSIS_NVIC */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_SCB System Control Block (SCB)
\brief Type definitions for the System Control Block Registers
@{
*/
/**
\brief Structure type to access the System Control Block (SCB).
*/
typedef struct
{
__IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
__IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
uint32_t RESERVED0;
__IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
__IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
__IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
uint32_t RESERVED1;
__IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
__IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
} SCB_Type;
/* SCB CPUID Register Definitions */
#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
/* SCB Interrupt Control State Register Definitions */
#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */
#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
/* SCB Application Interrupt and Reset Control Register Definitions */
#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
/* SCB System Control Register Definitions */
#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
/* SCB Configuration Control Register Definitions */
#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */
#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */
#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
/* SCB System Handler Control and State Register Definitions */
#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
/*@} end of group CMSIS_SCB */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB)
\brief Type definitions for the System Control and ID Register not in the SCB
@{
*/
/**
\brief Structure type to access the System Control and ID Register not in the SCB.
*/
typedef struct
{
uint32_t RESERVED0[2U];
__IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */
} SCnSCB_Type;
/* Auxiliary Control Register Definitions */
#define SCnSCB_ACTLR_ITCMUAEN_Pos 4U /*!< ACTLR: Instruction TCM Upper Alias Enable Position */
#define SCnSCB_ACTLR_ITCMUAEN_Msk (1UL << SCnSCB_ACTLR_ITCMUAEN_Pos) /*!< ACTLR: Instruction TCM Upper Alias Enable Mask */
#define SCnSCB_ACTLR_ITCMLAEN_Pos 3U /*!< ACTLR: Instruction TCM Lower Alias Enable Position */
#define SCnSCB_ACTLR_ITCMLAEN_Msk (1UL << SCnSCB_ACTLR_ITCMLAEN_Pos) /*!< ACTLR: Instruction TCM Lower Alias Enable Mask */
/*@} end of group CMSIS_SCnotSCB */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_SysTick System Tick Timer (SysTick)
\brief Type definitions for the System Timer Registers.
@{
*/
/**
\brief Structure type to access the System Timer (SysTick).
*/
typedef struct
{
__IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
__IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
__IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
__IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
} SysTick_Type;
/* SysTick Control / Status Register Definitions */
#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
/* SysTick Reload Register Definitions */
#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
/* SysTick Current Register Definitions */
#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
/* SysTick Calibration Register Definitions */
#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
/*@} end of group CMSIS_SysTick */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
\brief Cortex-M1 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor.
Therefore they are not covered by the Cortex-M1 header file.
@{
*/
/*@} end of group CMSIS_CoreDebug */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_core_bitfield Core register bit field macros
\brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
@{
*/
/**
\brief Mask and shift a bit field value for use in a register bit range.
\param[in] field Name of the register bit field.
\param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
\return Masked and shifted value.
*/
#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
/**
\brief Mask and shift a register value to extract a bit filed value.
\param[in] field Name of the register bit field.
\param[in] value Value of register. This parameter is interpreted as an uint32_t type.
\return Masked and shifted bit field value.
*/
#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
/*@} end of group CMSIS_core_bitfield */
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_core_base Core Definitions
\brief Definitions for base addresses, unions, and structures.
@{
*/
/* Memory mapping of Core Hardware */
#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */
#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
/*@} */
/*******************************************************************************
* Hardware Abstraction Layer
Core Function Interface contains:
- Core NVIC Functions
- Core SysTick Functions
- Core Register Access Functions
******************************************************************************/
/**
\defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
*/
/* ########################## NVIC functions #################################### */
/**
\ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_NVICFunctions NVIC Functions
\brief Functions that manage interrupts and exceptions via the NVIC.
@{
*/
#ifdef CMSIS_NVIC_VIRTUAL
#ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
#define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
#endif
#include CMSIS_NVIC_VIRTUAL_HEADER_FILE
#else
#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
#define NVIC_EnableIRQ __NVIC_EnableIRQ
#define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
#define NVIC_DisableIRQ __NVIC_DisableIRQ
#define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
#define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
#define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
/*#define NVIC_GetActive __NVIC_GetActive not available for Cortex-M1 */
#define NVIC_SetPriority __NVIC_SetPriority
#define NVIC_GetPriority __NVIC_GetPriority
#define NVIC_SystemReset __NVIC_SystemReset
#endif /* CMSIS_NVIC_VIRTUAL */
#ifdef CMSIS_VECTAB_VIRTUAL
#ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
#define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
#endif
#include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
#else
#define NVIC_SetVector __NVIC_SetVector
#define NVIC_GetVector __NVIC_GetVector
#endif /* (CMSIS_VECTAB_VIRTUAL) */
#define NVIC_USER_IRQ_OFFSET 16
/* The following EXC_RETURN values are saved the LR on exception entry */
#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */
#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */
#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */
/* Interrupt Priorities are WORD accessible only under Armv6-M */
/* The following MACROS handle generation of the register offset and byte masks */
#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL)
#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) )
#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) )
#define __NVIC_SetPriorityGrouping(X) (void)(X)
#define __NVIC_GetPriorityGrouping() (0U)
/**
\brief Enable Interrupt
\details Enables a device specific interrupt in the NVIC interrupt controller.
\param [in] IRQn Device specific interrupt number.
\note IRQn must not be negative.
*/
__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
__COMPILER_BARRIER();
NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
__COMPILER_BARRIER();
}
}
/**
\brief Get Interrupt Enable status
\details Returns a device specific interrupt enable status from the NVIC interrupt controller.
\param [in] IRQn Device specific interrupt number.
\return 0 Interrupt is not enabled.
\return 1 Interrupt is enabled.
\note IRQn must not be negative.
*/
__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
}
else
{
return(0U);
}
}
/**
\brief Disable Interrupt
\details Disables a device specific interrupt in the NVIC interrupt controller.
\param [in] IRQn Device specific interrupt number.
\note IRQn must not be negative.
*/
__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
__DSB();
__ISB();
}
}
/**
\brief Get Pending Interrupt
\details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
\param [in] IRQn Device specific interrupt number.
\return 0 Interrupt status is not pending.
\return 1 Interrupt status is pending.
\note IRQn must not be negative.
*/
__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
}
else
{
return(0U);
}
}
/**
\brief Set Pending Interrupt
\details Sets the pending bit of a device specific interrupt in the NVIC pending register.
\param [in] IRQn Device specific interrupt number.
\note IRQn must not be negative.
*/
__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
}
}
/**
\brief Clear Pending Interrupt
\details Clears the pending bit of a device specific interrupt in the NVIC pending register.
\param [in] IRQn Device specific interrupt number.
\note IRQn must not be negative.
*/
__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
}
}
/**
\brief Set Interrupt Priority
\details Sets the priority of a device specific interrupt or a processor exception.
The interrupt number can be positive to specify a device specific interrupt,
or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\param [in] priority Priority to set.
\note The priority cannot be set for every processor exception.
*/
__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
if ((int32_t)(IRQn) >= 0)
{
NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
(((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
}
else
{
SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
(((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
}
}
/**
\brief Get Interrupt Priority
\details Reads the priority of a device specific interrupt or a processor exception.
The interrupt number can be positive to specify a device specific interrupt,
or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\return Interrupt Priority.
Value is aligned automatically to the implemented priority bits of the microcontroller.
*/
__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
}
else
{
return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
}
}
/**
\brief Encode Priority
\details Encodes the priority for an interrupt with the given priority group,
preemptive priority value, and subpriority value.
In case of a conflict between priority grouping and available
priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
\param [in] PriorityGroup Used priority group.
\param [in] PreemptPriority Preemptive priority value (starting from 0).
\param [in] SubPriority Subpriority value (starting from 0).
\return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
*/
__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
{
uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
uint32_t PreemptPriorityBits;
uint32_t SubPriorityBits;
PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
return (
((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
);
}
/**
\brief Decode Priority
\details Decodes an interrupt priority value with a given priority group to
preemptive priority value and subpriority value.
In case of a conflict between priority grouping and available
priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
\param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
\param [in] PriorityGroup Used priority group.
\param [out] pPreemptPriority Preemptive priority value (starting from 0).
\param [out] pSubPriority Subpriority value (starting from 0).
*/
__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
{
uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
uint32_t PreemptPriorityBits;
uint32_t SubPriorityBits;
PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
*pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
*pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
}
/**
\brief Set Interrupt Vector
\details Sets an interrupt vector in SRAM based interrupt vector table.
The interrupt number can be positive to specify a device specific interrupt,
or negative to specify a processor exception.
Address 0 must be mapped to SRAM.
\param [in] IRQn Interrupt number
\param [in] vector Address of interrupt handler function
*/
__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
{
uint32_t *vectors = (uint32_t *)0x0U;
vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
/* ARM Application Note 321 states that the M1 does not require the architectural barrier */
}
/**
\brief Get Interrupt Vector
\details Reads an interrupt vector from interrupt vector table.
The interrupt number can be positive to specify a device specific interrupt,
or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\return Address of interrupt handler function
*/
__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
{
uint32_t *vectors = (uint32_t *)0x0U;
return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
}
/**
\brief System Reset
\details Initiates a system reset request to reset the MCU.
*/
__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
{
__DSB(); /* Ensure all outstanding memory accesses included
buffered write are completed before reset */
SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
SCB_AIRCR_SYSRESETREQ_Msk);
__DSB(); /* Ensure completion of memory access */
for(;;) /* wait until reset */
{
__NOP();
}
}
/*@} end of CMSIS_Core_NVICFunctions */
/* ########################## FPU functions #################################### */
/**
\ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_FpuFunctions FPU Functions
\brief Function that provides FPU type.
@{
*/
/**
\brief get FPU type
\details returns the FPU type
\returns
- \b 0: No FPU
- \b 1: Single precision FPU
- \b 2: Double + Single precision FPU
*/
__STATIC_INLINE uint32_t SCB_GetFPUType(void)
{
return 0U; /* No FPU */
}
/*@} end of CMSIS_Core_FpuFunctions */
/* ################################## SysTick function ############################################ */
/**
\ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_SysTickFunctions SysTick Functions
\brief Functions that configure the System.
@{
*/
#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
/**
\brief System Tick Configuration
\details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
Counter is in free running mode to generate periodic interrupts.
\param [in] ticks Number of ticks between two interrupts.
\return 0 Function succeeded.
\return 1 Function failed.
\note When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
must contain a vendor-specific implementation of this function.
*/
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
{
return (1UL); /* Reload value impossible */
}
SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
return (0UL); /* Function successful */
}
#endif
/*@} end of CMSIS_Core_SysTickFunctions */
#ifdef __cplusplus
}
#endif
#endif /* __CORE_CM1_H_DEPENDANT */
#endif /* __CMSIS_GENERIC */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+275
View File
@@ -0,0 +1,275 @@
/******************************************************************************
* @file mpu_armv7.h
* @brief CMSIS MPU API for Armv7-M MPU
* @version V5.1.2
* @date 25. May 2020
******************************************************************************/
/*
* Copyright (c) 2017-2020 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
#ifndef ARM_MPU_ARMV7_H
#define ARM_MPU_ARMV7_H
#define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U) ///!< MPU Region Size 32 Bytes
#define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U) ///!< MPU Region Size 64 Bytes
#define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U) ///!< MPU Region Size 128 Bytes
#define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U) ///!< MPU Region Size 256 Bytes
#define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U) ///!< MPU Region Size 512 Bytes
#define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U) ///!< MPU Region Size 1 KByte
#define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU) ///!< MPU Region Size 2 KBytes
#define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU) ///!< MPU Region Size 4 KBytes
#define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU) ///!< MPU Region Size 8 KBytes
#define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU) ///!< MPU Region Size 16 KBytes
#define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU) ///!< MPU Region Size 32 KBytes
#define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU) ///!< MPU Region Size 64 KBytes
#define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U) ///!< MPU Region Size 128 KBytes
#define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U) ///!< MPU Region Size 256 KBytes
#define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U) ///!< MPU Region Size 512 KBytes
#define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U) ///!< MPU Region Size 1 MByte
#define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U) ///!< MPU Region Size 2 MBytes
#define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U) ///!< MPU Region Size 4 MBytes
#define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U) ///!< MPU Region Size 8 MBytes
#define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U) ///!< MPU Region Size 16 MBytes
#define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U) ///!< MPU Region Size 32 MBytes
#define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U) ///!< MPU Region Size 64 MBytes
#define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU) ///!< MPU Region Size 128 MBytes
#define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU) ///!< MPU Region Size 256 MBytes
#define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU) ///!< MPU Region Size 512 MBytes
#define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU) ///!< MPU Region Size 1 GByte
#define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU) ///!< MPU Region Size 2 GBytes
#define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU) ///!< MPU Region Size 4 GBytes
#define ARM_MPU_AP_NONE 0U ///!< MPU Access Permission no access
#define ARM_MPU_AP_PRIV 1U ///!< MPU Access Permission privileged access only
#define ARM_MPU_AP_URO 2U ///!< MPU Access Permission unprivileged access read-only
#define ARM_MPU_AP_FULL 3U ///!< MPU Access Permission full access
#define ARM_MPU_AP_PRO 5U ///!< MPU Access Permission privileged access read-only
#define ARM_MPU_AP_RO 6U ///!< MPU Access Permission read-only access
/** MPU Region Base Address Register Value
*
* \param Region The region to be configured, number 0 to 15.
* \param BaseAddress The base address for the region.
*/
#define ARM_MPU_RBAR(Region, BaseAddress) \
(((BaseAddress) & MPU_RBAR_ADDR_Msk) | \
((Region) & MPU_RBAR_REGION_Msk) | \
(MPU_RBAR_VALID_Msk))
/**
* MPU Memory Access Attributes
*
* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral.
* \param IsShareable Region is shareable between multiple bus masters.
* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache.
* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
*/
#define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \
((((TypeExtField) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \
(((IsShareable) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \
(((IsCacheable) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \
(((IsBufferable) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk))
/**
* MPU Region Attribute and Size Register Value
*
* \param DisableExec Instruction access disable bit, 1= disable instruction fetches.
* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode.
* \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_.
* \param SubRegionDisable Sub-region disable field.
* \param Size Region size of the region to be configured, for example 4K, 8K.
*/
#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \
((((DisableExec) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \
(((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \
(((AccessAttributes) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) | \
(((SubRegionDisable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | \
(((Size) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | \
(((MPU_RASR_ENABLE_Msk))))
/**
* MPU Region Attribute and Size Register Value
*
* \param DisableExec Instruction access disable bit, 1= disable instruction fetches.
* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode.
* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral.
* \param IsShareable Region is shareable between multiple bus masters.
* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache.
* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
* \param SubRegionDisable Sub-region disable field.
* \param Size Region size of the region to be configured, for example 4K, 8K.
*/
#define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \
ARM_MPU_RASR_EX(DisableExec, AccessPermission, ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable), SubRegionDisable, Size)
/**
* MPU Memory Access Attribute for strongly ordered memory.
* - TEX: 000b
* - Shareable
* - Non-cacheable
* - Non-bufferable
*/
#define ARM_MPU_ACCESS_ORDERED ARM_MPU_ACCESS_(0U, 1U, 0U, 0U)
/**
* MPU Memory Access Attribute for device memory.
* - TEX: 000b (if shareable) or 010b (if non-shareable)
* - Shareable or non-shareable
* - Non-cacheable
* - Bufferable (if shareable) or non-bufferable (if non-shareable)
*
* \param IsShareable Configures the device memory as shareable or non-shareable.
*/
#define ARM_MPU_ACCESS_DEVICE(IsShareable) ((IsShareable) ? ARM_MPU_ACCESS_(0U, 1U, 0U, 1U) : ARM_MPU_ACCESS_(2U, 0U, 0U, 0U))
/**
* MPU Memory Access Attribute for normal memory.
* - TEX: 1BBb (reflecting outer cacheability rules)
* - Shareable or non-shareable
* - Cacheable or non-cacheable (reflecting inner cacheability rules)
* - Bufferable or non-bufferable (reflecting inner cacheability rules)
*
* \param OuterCp Configures the outer cache policy.
* \param InnerCp Configures the inner cache policy.
* \param IsShareable Configures the memory as shareable or non-shareable.
*/
#define ARM_MPU_ACCESS_NORMAL(OuterCp, InnerCp, IsShareable) ARM_MPU_ACCESS_((4U | (OuterCp)), IsShareable, ((InnerCp) >> 1U), ((InnerCp) & 1U))
/**
* MPU Memory Access Attribute non-cacheable policy.
*/
#define ARM_MPU_CACHEP_NOCACHE 0U
/**
* MPU Memory Access Attribute write-back, write and read allocate policy.
*/
#define ARM_MPU_CACHEP_WB_WRA 1U
/**
* MPU Memory Access Attribute write-through, no write allocate policy.
*/
#define ARM_MPU_CACHEP_WT_NWA 2U
/**
* MPU Memory Access Attribute write-back, no write allocate policy.
*/
#define ARM_MPU_CACHEP_WB_NWA 3U
/**
* Struct for a single MPU Region
*/
typedef struct {
uint32_t RBAR; //!< The region base address register value (RBAR)
uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR
} ARM_MPU_Region_t;
/** Enable the MPU.
* \param MPU_Control Default access permissions for unconfigured regions.
*/
__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control)
{
__DMB();
MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
#endif
__DSB();
__ISB();
}
/** Disable the MPU.
*/
__STATIC_INLINE void ARM_MPU_Disable(void)
{
__DMB();
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
#endif
MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
__DSB();
__ISB();
}
/** Clear and disable the given MPU region.
* \param rnr Region number to be cleared.
*/
__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr)
{
MPU->RNR = rnr;
MPU->RASR = 0U;
}
/** Configure an MPU region.
* \param rbar Value for RBAR register.
* \param rasr Value for RASR register.
*/
__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr)
{
MPU->RBAR = rbar;
MPU->RASR = rasr;
}
/** Configure the given MPU region.
* \param rnr Region number to be configured.
* \param rbar Value for RBAR register.
* \param rasr Value for RASR register.
*/
__STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr)
{
MPU->RNR = rnr;
MPU->RBAR = rbar;
MPU->RASR = rasr;
}
/** Memcpy with strictly ordered memory access, e.g. used by code in ARM_MPU_Load().
* \param dst Destination data is copied to.
* \param src Source data is copied from.
* \param len Amount of data words to be copied.
*/
__STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len)
{
uint32_t i;
for (i = 0U; i < len; ++i)
{
dst[i] = src[i];
}
}
/** Load the given number of MPU regions from a table.
* \param table Pointer to the MPU configuration table.
* \param cnt Amount of regions to be configured.
*/
__STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt)
{
const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U;
while (cnt > MPU_TYPE_RALIASES) {
ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize);
table += MPU_TYPE_RALIASES;
cnt -= MPU_TYPE_RALIASES;
}
ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize);
}
#endif
+70
View File
@@ -0,0 +1,70 @@
/******************************************************************************
* @file tz_context.h
* @brief Context Management for Armv8-M TrustZone
* @version V1.0.1
* @date 10. January 2018
******************************************************************************/
/*
* Copyright (c) 2017-2018 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
#ifndef TZ_CONTEXT_H
#define TZ_CONTEXT_H
#include <stdint.h>
#ifndef TZ_MODULEID_T
#define TZ_MODULEID_T
/// \details Data type that identifies secure software modules called by a process.
typedef uint32_t TZ_ModuleId_t;
#endif
/// \details TZ Memory ID identifies an allocated memory slot.
typedef uint32_t TZ_MemoryId_t;
/// Initialize secure context memory system
/// \return execution status (1: success, 0: error)
uint32_t TZ_InitContextSystem_S (void);
/// Allocate context memory for calling secure software modules in TrustZone
/// \param[in] module identifies software modules called from non-secure mode
/// \return value != 0 id TrustZone memory slot identifier
/// \return value 0 no memory available or internal error
TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module);
/// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S
/// \param[in] id TrustZone memory slot identifier
/// \return execution status (1: success, 0: error)
uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id);
/// Load secure context (called on RTOS thread context switch)
/// \param[in] id TrustZone memory slot identifier
/// \return execution status (1: success, 0: error)
uint32_t TZ_LoadContext_S (TZ_MemoryId_t id);
/// Store secure context (called on RTOS thread context switch)
/// \param[in] id TrustZone memory slot identifier
/// \return execution status (1: success, 0: error)
uint32_t TZ_StoreContext_S (TZ_MemoryId_t id);
#endif // TZ_CONTEXT_H
+10
View File
@@ -0,0 +1,10 @@
from building import *
import os
src = []
cwd = GetCurrentDir()
path = [os.path.join(cwd, 'Include')]
group = DefineGroup('CMSIS-Core', src, depend = ['PKG_USING_CMSIS_CORE'], CPPPATH = path)
Return('group')
+69
View File
@@ -0,0 +1,69 @@
Import('RTT_ROOT')
from building import *
src = Split("""
modbus/functions/mbfuncdiag.c
modbus/functions/mbutils.c
modbus/functions/mbfuncother.c
modbus/rtu/mbcrc.c
port/port.c
""")
master_rtu_src = Split("""
modbus/functions/mbfunccoils_m.c
modbus/functions/mbfuncdisc_m.c
modbus/functions/mbfuncholding_m.c
modbus/functions/mbfuncinput_m.c
modbus/rtu/mbrtu_m.c
modbus/mb_m.c
port/portevent_m.c
port/portserial_m.c
port/porttimer_m.c
port/user_mb_app_m.c
""")
slave_src = Split("""
modbus/functions/mbfunccoils.c
modbus/functions/mbfuncdisc.c
modbus/functions/mbfuncholding.c
modbus/functions/mbfuncinput.c
modbus/mb.c
port/portevent.c
port/portserial.c
port/porttcp.c
port/porttimer.c
port/user_mb_app.c
""")
# The set of source files associated with this SConscript file.
path = [GetCurrentDir() + '/modbus/include',
GetCurrentDir() + '/modbus/rtu',
GetCurrentDir() + '/modbus/ascii',
GetCurrentDir() + '/modbus/tcp',
GetCurrentDir() + '/port']
if GetDepend(['PKG_MODBUS_MASTER_RTU']):
src += master_rtu_src
if GetDepend(['PKG_MODBUS_SLAVE']):
src += slave_src
if GetDepend(['PKG_MODBUS_SLAVE_RTU']):
src += ['modbus/rtu/mbrtu.c']
if GetDepend(['PKG_MODBUS_SLAVE_ASCII']):
src += ['modbus/ascii/mbascii.c']
src += ['modbus/rtu/mbrtu.c']
if GetDepend(['PKG_MODBUS_SLAVE_TCP']):
src += ['modbus/tcp/mbtcp.c']
if GetDepend(['PKG_MODBUS_MASTER_SAMPLE']):
src += ['samples/sample_mb_master.c']
if GetDepend(['PKG_MODBUS_SLAVE_SAMPLE']):
src += ['samples/sample_mb_slave.c']
group = DefineGroup('FreeModbus', src, depend = ['PKG_USING_FREEMODBUS'], CPPPATH = path)
Return('group')
+486
View File
@@ -0,0 +1,486 @@
/*
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
* Copyright (c) 2006-2018 Christian Walter <cwalter@embedded-solutions.at>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* File: $Id: mbascii.c,v 1.15 2007/02/18 23:46:48 wolti Exp $
*/
/* ----------------------- System includes ----------------------------------*/
#include "stdlib.h"
#include "string.h"
/* ----------------------- Platform includes --------------------------------*/
#include "port.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbconfig.h"
#include "mbascii.h"
#include "mbframe.h"
#include "mbcrc.h"
#include "mbport.h"
#if MB_SLAVE_ASCII_ENABLED > 0
/* ----------------------- Defines ------------------------------------------*/
#define MB_ASCII_DEFAULT_CR '\r' /*!< Default CR character for Modbus ASCII. */
#define MB_ASCII_DEFAULT_LF '\n' /*!< Default LF character for Modbus ASCII. */
#define MB_SER_PDU_SIZE_MIN 3 /*!< Minimum size of a Modbus ASCII frame. */
#define MB_SER_PDU_SIZE_MAX 256 /*!< Maximum size of a Modbus ASCII frame. */
#define MB_SER_PDU_SIZE_LRC 1 /*!< Size of LRC field in PDU. */
#define MB_SER_PDU_ADDR_OFF 0 /*!< Offset of slave address in Ser-PDU. */
#define MB_SER_PDU_PDU_OFF 1 /*!< Offset of Modbus-PDU in Ser-PDU. */
/* ----------------------- Type definitions ---------------------------------*/
typedef enum
{
STATE_RX_IDLE, /*!< Receiver is in idle state. */
STATE_RX_RCV, /*!< Frame is beeing received. */
STATE_RX_WAIT_EOF /*!< Wait for End of Frame. */
} eMBRcvState;
typedef enum
{
STATE_TX_IDLE, /*!< Transmitter is in idle state. */
STATE_TX_START, /*!< Starting transmission (':' sent). */
STATE_TX_DATA, /*!< Sending of data (Address, Data, LRC). */
STATE_TX_END, /*!< End of transmission. */
STATE_TX_NOTIFY /*!< Notify sender that the frame has been sent. */
} eMBSndState;
typedef enum
{
BYTE_HIGH_NIBBLE, /*!< Character for high nibble of byte. */
BYTE_LOW_NIBBLE /*!< Character for low nibble of byte. */
} eMBBytePos;
/* ----------------------- Static functions ---------------------------------*/
static UCHAR prvucMBCHAR2BIN( UCHAR ucCharacter );
static UCHAR prvucMBBIN2CHAR( UCHAR ucByte );
static UCHAR prvucMBLRC( UCHAR * pucFrame, USHORT usLen );
/* ----------------------- Static variables ---------------------------------*/
static volatile eMBSndState eSndState;
static volatile eMBRcvState eRcvState;
/* We reuse the Modbus RTU buffer because only one buffer is needed and the
* RTU buffer is bigger. */
extern volatile UCHAR ucRTUBuf[];
static volatile UCHAR *ucASCIIBuf = ucRTUBuf;
static volatile USHORT usRcvBufferPos;
static volatile eMBBytePos eBytePos;
static volatile UCHAR *pucSndBufferCur;
static volatile USHORT usSndBufferCount;
static volatile UCHAR ucLRC;
static volatile UCHAR ucMBLFCharacter;
/* ----------------------- Start implementation -----------------------------*/
eMBErrorCode
eMBASCIIInit( UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity )
{
eMBErrorCode eStatus = MB_ENOERR;
( void )ucSlaveAddress;
ENTER_CRITICAL_SECTION( );
ucMBLFCharacter = MB_ASCII_DEFAULT_LF;
if( xMBPortSerialInit( ucPort, ulBaudRate, 7, eParity ) != TRUE )
{
eStatus = MB_EPORTERR;
}
else if( xMBPortTimersInit( MB_ASCII_TIMEOUT_SEC * 20000UL ) != TRUE )
{
eStatus = MB_EPORTERR;
}
EXIT_CRITICAL_SECTION( );
return eStatus;
}
void
eMBASCIIStart( void )
{
ENTER_CRITICAL_SECTION( );
vMBPortSerialEnable( TRUE, FALSE );
eRcvState = STATE_RX_IDLE;
EXIT_CRITICAL_SECTION( );
/* No special startup required for ASCII. */
( void )xMBPortEventPost( EV_READY );
}
void
eMBASCIIStop( void )
{
ENTER_CRITICAL_SECTION( );
vMBPortSerialEnable( FALSE, FALSE );
vMBPortTimersDisable( );
EXIT_CRITICAL_SECTION( );
}
eMBErrorCode
eMBASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
{
eMBErrorCode eStatus = MB_ENOERR;
ENTER_CRITICAL_SECTION( );
assert( usRcvBufferPos < MB_SER_PDU_SIZE_MAX );
/* Length and CRC check */
if( ( usRcvBufferPos >= MB_SER_PDU_SIZE_MIN )
&& ( prvucMBLRC( ( UCHAR * ) ucASCIIBuf, usRcvBufferPos ) == 0 ) )
{
/* Save the address field. All frames are passed to the upper layed
* and the decision if a frame is used is done there.
*/
*pucRcvAddress = ucASCIIBuf[MB_SER_PDU_ADDR_OFF];
/* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
* size of address field and CRC checksum.
*/
*pusLength = ( USHORT )( usRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_LRC );
/* Return the start of the Modbus PDU to the caller. */
*pucFrame = ( UCHAR * ) & ucASCIIBuf[MB_SER_PDU_PDU_OFF];
}
else
{
eStatus = MB_EIO;
}
EXIT_CRITICAL_SECTION( );
return eStatus;
}
eMBErrorCode
eMBASCIISend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength )
{
eMBErrorCode eStatus = MB_ENOERR;
UCHAR usLRC;
ENTER_CRITICAL_SECTION( );
/* Check if the receiver is still in idle state. If not we where too
* slow with processing the received frame and the master sent another
* frame on the network. We have to abort sending the frame.
*/
if( eRcvState == STATE_RX_IDLE )
{
/* First byte before the Modbus-PDU is the slave address. */
pucSndBufferCur = ( UCHAR * ) pucFrame - 1;
usSndBufferCount = 1;
/* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */
pucSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress;
usSndBufferCount += usLength;
/* Calculate LRC checksum for Modbus-Serial-Line-PDU. */
usLRC = prvucMBLRC( ( UCHAR * ) pucSndBufferCur, usSndBufferCount );
ucASCIIBuf[usSndBufferCount++] = usLRC;
/* Activate the transmitter. */
eSndState = STATE_TX_START;
vMBPortSerialEnable( FALSE, TRUE );
}
else
{
eStatus = MB_EIO;
}
EXIT_CRITICAL_SECTION( );
return eStatus;
}
BOOL
xMBASCIIReceiveFSM( void )
{
BOOL xNeedPoll = FALSE;
UCHAR ucByte;
UCHAR ucResult;
assert( eSndState == STATE_TX_IDLE );
( void )xMBPortSerialGetByte( ( CHAR * ) & ucByte );
switch ( eRcvState )
{
/* A new character is received. If the character is a ':' the input
* buffer is cleared. A CR-character signals the end of the data
* block. Other characters are part of the data block and their
* ASCII value is converted back to a binary representation.
*/
case STATE_RX_RCV:
/* Enable timer for character timeout. */
vMBPortTimersEnable( );
if( ucByte == ':' )
{
/* Empty receive buffer. */
eBytePos = BYTE_HIGH_NIBBLE;
usRcvBufferPos = 0;
}
else if( ucByte == MB_ASCII_DEFAULT_CR )
{
eRcvState = STATE_RX_WAIT_EOF;
}
else
{
ucResult = prvucMBCHAR2BIN( ucByte );
switch ( eBytePos )
{
/* High nibble of the byte comes first. We check for
* a buffer overflow here. */
case BYTE_HIGH_NIBBLE:
if( usRcvBufferPos < MB_SER_PDU_SIZE_MAX )
{
ucASCIIBuf[usRcvBufferPos] = ( UCHAR )( ucResult << 4 );
eBytePos = BYTE_LOW_NIBBLE;
break;
}
else
{
/* not handled in Modbus specification but seems
* a resonable implementation. */
eRcvState = STATE_RX_IDLE;
/* Disable previously activated timer because of error state. */
vMBPortTimersDisable( );
}
break;
case BYTE_LOW_NIBBLE:
ucASCIIBuf[usRcvBufferPos] |= ucResult;
usRcvBufferPos++;
eBytePos = BYTE_HIGH_NIBBLE;
break;
}
}
break;
case STATE_RX_WAIT_EOF:
if( ucByte == ucMBLFCharacter )
{
/* Disable character timeout timer because all characters are
* received. */
vMBPortTimersDisable( );
/* Receiver is again in idle state. */
eRcvState = STATE_RX_IDLE;
/* Notify the caller of eMBASCIIReceive that a new frame
* was received. */
xNeedPoll = xMBPortEventPost( EV_FRAME_RECEIVED );
}
else if( ucByte == ':' )
{
/* Empty receive buffer and back to receive state. */
eBytePos = BYTE_HIGH_NIBBLE;
usRcvBufferPos = 0;
eRcvState = STATE_RX_RCV;
/* Enable timer for character timeout. */
vMBPortTimersEnable( );
}
else
{
/* Frame is not okay. Delete entire frame. */
eRcvState = STATE_RX_IDLE;
}
break;
case STATE_RX_IDLE:
if( ucByte == ':' )
{
/* Enable timer for character timeout. */
vMBPortTimersEnable( );
/* Reset the input buffers to store the frame. */
usRcvBufferPos = 0;;
eBytePos = BYTE_HIGH_NIBBLE;
eRcvState = STATE_RX_RCV;
}
break;
}
return xNeedPoll;
}
BOOL
xMBASCIITransmitFSM( void )
{
BOOL xNeedPoll = FALSE;
UCHAR ucByte;
assert( eRcvState == STATE_RX_IDLE );
switch ( eSndState )
{
/* Start of transmission. The start of a frame is defined by sending
* the character ':'. */
case STATE_TX_START:
ucByte = ':';
xMBPortSerialPutByte( ( CHAR )ucByte );
eSndState = STATE_TX_DATA;
eBytePos = BYTE_HIGH_NIBBLE;
break;
/* Send the data block. Each data byte is encoded as a character hex
* stream with the high nibble sent first and the low nibble sent
* last. If all data bytes are exhausted we send a '\r' character
* to end the transmission. */
case STATE_TX_DATA:
if( usSndBufferCount > 0 )
{
switch ( eBytePos )
{
case BYTE_HIGH_NIBBLE:
ucByte = prvucMBBIN2CHAR( ( UCHAR )( *pucSndBufferCur >> 4 ) );
xMBPortSerialPutByte( ( CHAR ) ucByte );
eBytePos = BYTE_LOW_NIBBLE;
break;
case BYTE_LOW_NIBBLE:
ucByte = prvucMBBIN2CHAR( ( UCHAR )( *pucSndBufferCur & 0x0F ) );
xMBPortSerialPutByte( ( CHAR )ucByte );
pucSndBufferCur++;
eBytePos = BYTE_HIGH_NIBBLE;
usSndBufferCount--;
break;
}
}
else
{
xMBPortSerialPutByte( MB_ASCII_DEFAULT_CR );
eSndState = STATE_TX_END;
}
break;
/* Finish the frame by sending a LF character. */
case STATE_TX_END:
xMBPortSerialPutByte( ( CHAR )ucMBLFCharacter );
/* We need another state to make sure that the CR character has
* been sent. */
eSndState = STATE_TX_NOTIFY;
break;
/* Notify the task which called eMBASCIISend that the frame has
* been sent. */
case STATE_TX_NOTIFY:
eSndState = STATE_TX_IDLE;
xNeedPoll = xMBPortEventPost( EV_FRAME_SENT );
/* Disable transmitter. This prevents another transmit buffer
* empty interrupt. */
vMBPortSerialEnable( TRUE, FALSE );
eSndState = STATE_TX_IDLE;
break;
/* We should not get a transmitter event if the transmitter is in
* idle state. */
case STATE_TX_IDLE:
/* enable receiver/disable transmitter. */
vMBPortSerialEnable( TRUE, FALSE );
break;
}
return xNeedPoll;
}
BOOL
xMBASCIITimerT1SExpired( void )
{
switch ( eRcvState )
{
/* If we have a timeout we go back to the idle state and wait for
* the next frame.
*/
case STATE_RX_RCV:
case STATE_RX_WAIT_EOF:
eRcvState = STATE_RX_IDLE;
break;
default:
assert( ( eRcvState == STATE_RX_RCV ) || ( eRcvState == STATE_RX_WAIT_EOF ) );
break;
}
vMBPortTimersDisable( );
/* no context switch required. */
return FALSE;
}
static UCHAR
prvucMBCHAR2BIN( UCHAR ucCharacter )
{
if( ( ucCharacter >= '0' ) && ( ucCharacter <= '9' ) )
{
return ( UCHAR )( ucCharacter - '0' );
}
else if( ( ucCharacter >= 'A' ) && ( ucCharacter <= 'F' ) )
{
return ( UCHAR )( ucCharacter - 'A' + 0x0A );
}
else
{
return 0xFF;
}
}
static UCHAR
prvucMBBIN2CHAR( UCHAR ucByte )
{
if( ucByte <= 0x09 )
{
return ( UCHAR )( '0' + ucByte );
}
else if( ( ucByte >= 0x0A ) && ( ucByte <= 0x0F ) )
{
return ( UCHAR )( ucByte - 0x0A + 'A' );
}
else
{
/* Programming error. */
assert( 0 );
}
return '0';
}
static UCHAR
prvucMBLRC( UCHAR * pucFrame, USHORT usLen )
{
UCHAR ucLRC = 0; /* LRC char initialized */
while( usLen-- )
{
ucLRC += *pucFrame++; /* Add buffer byte without carry */
}
/* Return twos complement */
ucLRC = ( UCHAR ) ( -( ( CHAR ) ucLRC ) );
return ucLRC;
}
#endif
+56
View File
@@ -0,0 +1,56 @@
/*
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
* Copyright (c) 2006-2018 Christian Walter <cwalter@embedded-solutions.at>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* File: $Id: mbascii.h,v 1.8 2006/12/07 22:10:34 wolti Exp $
*/
#ifndef _MB_ASCII_H
#define _MB_ASCII_H
#ifdef __cplusplus
PR_BEGIN_EXTERN_C
#endif
#if MB_SLAVE_ASCII_ENABLED > 0
eMBErrorCode eMBASCIIInit( UCHAR slaveAddress, UCHAR ucPort,
ULONG ulBaudRate, eMBParity eParity );
void eMBASCIIStart( void );
void eMBASCIIStop( void );
eMBErrorCode eMBASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame,
USHORT * pusLength );
eMBErrorCode eMBASCIISend( UCHAR slaveAddress, const UCHAR * pucFrame,
USHORT usLength );
BOOL xMBASCIIReceiveFSM( void );
BOOL xMBASCIITransmitFSM( void );
BOOL xMBASCIITimerT1SExpired( void );
#endif
#ifdef __cplusplus
PR_END_EXTERN_C
#endif
#endif
@@ -0,0 +1,269 @@
/*
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
* Copyright (c) 2006-2018 Christian Walter <cwalter@embedded-solutions.at>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* File: $Id: mbfunccoils.c,v 1.8 2007/02/18 23:47:16 wolti Exp $
*/
/* ----------------------- System includes ----------------------------------*/
#include "stdlib.h"
#include "string.h"
/* ----------------------- Platform includes --------------------------------*/
#include "port.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbframe.h"
#include "mbproto.h"
#include "mbconfig.h"
/* ----------------------- Defines ------------------------------------------*/
#define MB_PDU_FUNC_READ_ADDR_OFF ( MB_PDU_DATA_OFF )
#define MB_PDU_FUNC_READ_COILCNT_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_FUNC_READ_SIZE ( 4 )
#define MB_PDU_FUNC_READ_COILCNT_MAX ( 0x07D0 )
#define MB_PDU_FUNC_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF )
#define MB_PDU_FUNC_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_FUNC_WRITE_SIZE ( 4 )
#define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF )
#define MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF ( MB_PDU_DATA_OFF + 4 )
#define MB_PDU_FUNC_WRITE_MUL_VALUES_OFF ( MB_PDU_DATA_OFF + 5 )
#define MB_PDU_FUNC_WRITE_MUL_SIZE_MIN ( 5 )
#define MB_PDU_FUNC_WRITE_MUL_COILCNT_MAX ( 0x07B0 )
/* ----------------------- Static functions ---------------------------------*/
eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
/* ----------------------- Start implementation -----------------------------*/
#if MB_FUNC_READ_COILS_ENABLED > 0
eMBException
eMBFuncReadCoils( UCHAR * pucFrame, USHORT * usLen )
{
USHORT usRegAddress;
USHORT usCoilCount;
UCHAR ucNBytes;
UCHAR *pucFrameCur;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) )
{
usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 );
usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] );
usRegAddress++;
usCoilCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF] << 8 );
usCoilCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF + 1] );
/* Check if the number of registers to read is valid. If not
* return Modbus illegal data value exception.
*/
if( ( usCoilCount >= 1 ) &&
( usCoilCount < MB_PDU_FUNC_READ_COILCNT_MAX ) )
{
/* Set the current PDU data pointer to the beginning. */
pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF];
*usLen = MB_PDU_FUNC_OFF;
/* First byte contains the function code. */
*pucFrameCur++ = MB_FUNC_READ_COILS;
*usLen += 1;
/* Test if the quantity of coils is a multiple of 8. If not last
* byte is only partially field with unused coils set to zero. */
if( ( usCoilCount & 0x0007 ) != 0 )
{
ucNBytes = ( UCHAR )( usCoilCount / 8 + 1 );
}
else
{
ucNBytes = ( UCHAR )( usCoilCount / 8 );
}
*pucFrameCur++ = ucNBytes;
*usLen += 1;
eRegStatus =
eMBRegCoilsCB( pucFrameCur, usRegAddress, usCoilCount,
MB_REG_READ );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
{
eStatus = prveMBError2Exception( eRegStatus );
}
else
{
/* The response contains the function code, the starting address
* and the quantity of registers. We reuse the old values in the
* buffer because they are still valid. */
*usLen += ucNBytes;;
}
}
else
{
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
}
else
{
/* Can't be a valid read coil register request because the length
* is incorrect. */
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
return eStatus;
}
#endif
#if MB_FUNC_WRITE_COIL_ENABLED > 0
eMBException
eMBFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen )
{
USHORT usRegAddress;
UCHAR ucBuf[2];
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if( *usLen == ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) )
{
usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8 );
usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1] );
usRegAddress++;
if( ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF + 1] == 0x00 ) &&
( ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF ) ||
( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0x00 ) ) )
{
ucBuf[1] = 0;
if( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF )
{
ucBuf[0] = 1;
}
else
{
ucBuf[0] = 0;
}
eRegStatus =
eMBRegCoilsCB( &ucBuf[0], usRegAddress, 1, MB_REG_WRITE );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
{
eStatus = prveMBError2Exception( eRegStatus );
}
}
else
{
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
}
else
{
/* Can't be a valid write coil register request because the length
* is incorrect. */
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
return eStatus;
}
#endif
#if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0
eMBException
eMBFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen )
{
USHORT usRegAddress;
USHORT usCoilCnt;
UCHAR ucByteCount;
UCHAR ucByteCountVerify;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if( *usLen > ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) )
{
usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8 );
usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1] );
usRegAddress++;
usCoilCnt = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF] << 8 );
usCoilCnt |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF + 1] );
ucByteCount = pucFrame[MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF];
/* Compute the number of expected bytes in the request. */
if( ( usCoilCnt & 0x0007 ) != 0 )
{
ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 + 1 );
}
else
{
ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 );
}
if( ( usCoilCnt >= 1 ) &&
( usCoilCnt <= MB_PDU_FUNC_WRITE_MUL_COILCNT_MAX ) &&
( ucByteCountVerify == ucByteCount ) )
{
eRegStatus =
eMBRegCoilsCB( &pucFrame[MB_PDU_FUNC_WRITE_MUL_VALUES_OFF],
usRegAddress, usCoilCnt, MB_REG_WRITE );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
{
eStatus = prveMBError2Exception( eRegStatus );
}
else
{
/* The response contains the function code, the starting address
* and the quantity of registers. We reuse the old values in the
* buffer because they are still valid. */
*usLen = MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF;
}
}
else
{
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
}
else
{
/* Can't be a valid write coil register request because the length
* is incorrect. */
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
return eStatus;
}
#endif
@@ -0,0 +1,390 @@
/*
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* File: $Id: mbfunccoils_m.c,v 1.60 2013/10/12 15:10:12 Armink Add Master Functions
*/
/* ----------------------- System includes ----------------------------------*/
#include "stdlib.h"
#include "string.h"
/* ----------------------- Platform includes --------------------------------*/
#include "port.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mb_m.h"
#include "mbframe.h"
#include "mbproto.h"
#include "mbconfig.h"
/* ----------------------- Defines ------------------------------------------*/
#define MB_PDU_REQ_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 )
#define MB_PDU_REQ_READ_COILCNT_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_REQ_READ_SIZE ( 4 )
#define MB_PDU_FUNC_READ_COILCNT_OFF ( MB_PDU_DATA_OFF + 0 )
#define MB_PDU_FUNC_READ_VALUES_OFF ( MB_PDU_DATA_OFF + 1 )
#define MB_PDU_FUNC_READ_SIZE_MIN ( 1 )
#define MB_PDU_REQ_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF )
#define MB_PDU_REQ_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_REQ_WRITE_SIZE ( 4 )
#define MB_PDU_FUNC_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF )
#define MB_PDU_FUNC_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_FUNC_WRITE_SIZE ( 4 )
#define MB_PDU_REQ_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF )
#define MB_PDU_REQ_WRITE_MUL_COILCNT_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF ( MB_PDU_DATA_OFF + 4 )
#define MB_PDU_REQ_WRITE_MUL_VALUES_OFF ( MB_PDU_DATA_OFF + 5 )
#define MB_PDU_REQ_WRITE_MUL_SIZE_MIN ( 5 )
#define MB_PDU_REQ_WRITE_MUL_COILCNT_MAX ( 0x07B0 )
#define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF )
#define MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_FUNC_WRITE_MUL_SIZE ( 5 )
/* ----------------------- Static functions ---------------------------------*/
eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
/* ----------------------- Start implementation -----------------------------*/
#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
#if MB_FUNC_READ_COILS_ENABLED > 0
/**
* This function will request read coil.
*
* @param ucSndAddr salve address
* @param usCoilAddr coil start address
* @param usNCoils coil total number
* @param lTimeOut timeout (-1 will waiting forever)
*
* @return error code
*/
eMBMasterReqErrCode
eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils ,LONG lTimeOut )
{
UCHAR *ucMBFrame;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
vMBMasterSetDestAddress(ucSndAddr);
ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READ_COILS;
ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] = usCoilAddr >> 8;
ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] = usCoilAddr;
ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF ] = usNCoils >> 8;
ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF + 1] = usNCoils;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
eMBException
eMBMasterFuncReadCoils( UCHAR * pucFrame, USHORT * usLen )
{
UCHAR *ucMBFrame;
USHORT usRegAddress;
USHORT usCoilCount;
UCHAR ucByteCount;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
/* If this request is broadcast, and it's read mode. This request don't need execute. */
if ( xMBMasterRequestIsBroadcast() )
{
eStatus = MB_EX_NONE;
}
else if ( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 );
usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] );
usRegAddress++;
usCoilCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF] << 8 );
usCoilCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF + 1] );
/* Test if the quantity of coils is a multiple of 8. If not last
* byte is only partially field with unused coils set to zero. */
if( ( usCoilCount & 0x0007 ) != 0 )
{
ucByteCount = ( UCHAR )( usCoilCount / 8 + 1 );
}
else
{
ucByteCount = ( UCHAR )( usCoilCount / 8 );
}
/* Check if the number of registers to read is valid. If not
* return Modbus illegal data value exception.
*/
if( ( usCoilCount >= 1 ) &&
( ucByteCount == pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF] ) )
{
/* Make callback to fill the buffer. */
eRegStatus = eMBMasterRegCoilsCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usCoilCount, MB_REG_READ );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
{
eStatus = prveMBError2Exception( eRegStatus );
}
}
else
{
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
}
else
{
/* Can't be a valid read coil register request because the length
* is incorrect. */
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
return eStatus;
}
#endif
#if MB_FUNC_WRITE_COIL_ENABLED > 0
/**
* This function will request write one coil.
*
* @param ucSndAddr salve address
* @param usCoilAddr coil start address
* @param usCoilData data to be written
* @param lTimeOut timeout (-1 will waiting forever)
*
* @return error code
*
* @see eMBMasterReqWriteMultipleCoils
*/
eMBMasterReqErrCode
eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData, LONG lTimeOut )
{
UCHAR *ucMBFrame;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
else if ( ( usCoilData != 0xFF00 ) && ( usCoilData != 0x0000 ) ) eErrStatus = MB_MRE_ILL_ARG;
else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
vMBMasterSetDestAddress(ucSndAddr);
ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_SINGLE_COIL;
ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF] = usCoilAddr >> 8;
ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF + 1] = usCoilAddr;
ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF ] = usCoilData >> 8;
ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usCoilData;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
eMBException
eMBMasterFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen )
{
USHORT usRegAddress;
UCHAR ucBuf[2];
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if( *usLen == ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) )
{
usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8 );
usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1] );
usRegAddress++;
if( ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF + 1] == 0x00 ) &&
( ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF ) ||
( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0x00 ) ) )
{
ucBuf[1] = 0;
if( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF )
{
ucBuf[0] = 1;
}
else
{
ucBuf[0] = 0;
}
eRegStatus =
eMBMasterRegCoilsCB( &ucBuf[0], usRegAddress, 1, MB_REG_WRITE );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
{
eStatus = prveMBError2Exception( eRegStatus );
}
}
else
{
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
}
else
{
/* Can't be a valid write coil register request because the length
* is incorrect. */
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
return eStatus;
}
#endif
#if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0
/**
* This function will request write multiple coils.
*
* @param ucSndAddr salve address
* @param usCoilAddr coil start address
* @param usNCoils coil total number
* @param usCoilData data to be written
* @param lTimeOut timeout (-1 will waiting forever)
*
* @return error code
*
* @see eMBMasterReqWriteCoil
*/
eMBMasterReqErrCode
eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr,
USHORT usCoilAddr, USHORT usNCoils, UCHAR * pucDataBuffer, LONG lTimeOut)
{
UCHAR *ucMBFrame;
USHORT usRegIndex = 0;
UCHAR ucByteCount;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
else if ( usNCoils > MB_PDU_REQ_WRITE_MUL_COILCNT_MAX ) eErrStatus = MB_MRE_ILL_ARG;
else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
vMBMasterSetDestAddress(ucSndAddr);
ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_MULTIPLE_COILS;
ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] = usCoilAddr >> 8;
ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1] = usCoilAddr;
ucMBFrame[MB_PDU_REQ_WRITE_MUL_COILCNT_OFF] = usNCoils >> 8;
ucMBFrame[MB_PDU_REQ_WRITE_MUL_COILCNT_OFF + 1] = usNCoils ;
if( ( usNCoils & 0x0007 ) != 0 )
{
ucByteCount = ( UCHAR )( usNCoils / 8 + 1 );
}
else
{
ucByteCount = ( UCHAR )( usNCoils / 8 );
}
ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF] = ucByteCount;
ucMBFrame += MB_PDU_REQ_WRITE_MUL_VALUES_OFF;
while( ucByteCount > usRegIndex)
{
*ucMBFrame++ = pucDataBuffer[usRegIndex++];
}
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + ucByteCount );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
eMBException
eMBMasterFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen )
{
USHORT usRegAddress;
USHORT usCoilCnt;
UCHAR ucByteCount;
UCHAR ucByteCountVerify;
UCHAR *ucMBFrame;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
/* If this request is broadcast, the *usLen is not need check. */
if( ( *usLen == MB_PDU_FUNC_WRITE_MUL_SIZE ) || xMBMasterRequestIsBroadcast() )
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8 );
usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1] );
usRegAddress++;
usCoilCnt = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF] << 8 );
usCoilCnt |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF + 1] );
ucByteCount = ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF];
/* Compute the number of expected bytes in the request. */
if( ( usCoilCnt & 0x0007 ) != 0 )
{
ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 + 1 );
}
else
{
ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 );
}
if( ( usCoilCnt >= 1 ) && ( ucByteCountVerify == ucByteCount ) )
{
eRegStatus =
eMBMasterRegCoilsCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF],
usRegAddress, usCoilCnt, MB_REG_WRITE );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
{
eStatus = prveMBError2Exception( eRegStatus );
}
}
else
{
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
}
else
{
/* Can't be a valid write coil register request because the length
* is incorrect. */
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
return eStatus;
}
#endif
#endif
@@ -0,0 +1,29 @@
/*
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
* Copyright (c) 2006-2018 Christian Walter <cwalter@embedded-solutions.at>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* File: $Id: mbfuncdiag.c,v 1.3 2006/12/07 22:10:34 wolti Exp $
*/
@@ -0,0 +1,133 @@
/*
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
* Copyright (c) 2006-2018 Christian Walter <cwalter@embedded-solutions.at>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* ----------------------- System includes ----------------------------------*/
#include "stdlib.h"
#include "string.h"
/* ----------------------- Platform includes --------------------------------*/
#include "port.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbframe.h"
#include "mbproto.h"
#include "mbconfig.h"
/* ----------------------- Defines ------------------------------------------*/
#define MB_PDU_FUNC_READ_ADDR_OFF ( MB_PDU_DATA_OFF )
#define MB_PDU_FUNC_READ_DISCCNT_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_FUNC_READ_SIZE ( 4 )
#define MB_PDU_FUNC_READ_DISCCNT_MAX ( 0x07D0 )
/* ----------------------- Static functions ---------------------------------*/
eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
/* ----------------------- Start implementation -----------------------------*/
#if MB_FUNC_READ_COILS_ENABLED > 0
eMBException
eMBFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen )
{
USHORT usRegAddress;
USHORT usDiscreteCnt;
UCHAR ucNBytes;
UCHAR *pucFrameCur;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) )
{
usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 );
usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] );
usRegAddress++;
usDiscreteCnt = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF] << 8 );
usDiscreteCnt |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF + 1] );
/* Check if the number of registers to read is valid. If not
* return Modbus illegal data value exception.
*/
if( ( usDiscreteCnt >= 1 ) &&
( usDiscreteCnt < MB_PDU_FUNC_READ_DISCCNT_MAX ) )
{
/* Set the current PDU data pointer to the beginning. */
pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF];
*usLen = MB_PDU_FUNC_OFF;
/* First byte contains the function code. */
*pucFrameCur++ = MB_FUNC_READ_DISCRETE_INPUTS;
*usLen += 1;
/* Test if the quantity of coils is a multiple of 8. If not last
* byte is only partially field with unused coils set to zero. */
if( ( usDiscreteCnt & 0x0007 ) != 0 )
{
ucNBytes = ( UCHAR ) ( usDiscreteCnt / 8 + 1 );
}
else
{
ucNBytes = ( UCHAR ) ( usDiscreteCnt / 8 );
}
*pucFrameCur++ = ucNBytes;
*usLen += 1;
eRegStatus =
eMBRegDiscreteCB( pucFrameCur, usRegAddress, usDiscreteCnt );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
{
eStatus = prveMBError2Exception( eRegStatus );
}
else
{
/* The response contains the function code, the starting address
* and the quantity of registers. We reuse the old values in the
* buffer because they are still valid. */
*usLen += ucNBytes;;
}
}
else
{
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
}
else
{
/* Can't be a valid read coil register request because the length
* is incorrect. */
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
return eStatus;
}
#endif
@@ -0,0 +1,162 @@
/*
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* File: $Id: mbfuncdisc_m.c,v 1.60 2013/10/15 8:48:20 Armink Add Master Functions Exp $
*/
/* ----------------------- System includes ----------------------------------*/
#include "stdlib.h"
#include "string.h"
/* ----------------------- Platform includes --------------------------------*/
#include "port.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mb_m.h"
#include "mbframe.h"
#include "mbproto.h"
#include "mbconfig.h"
/* ----------------------- Defines ------------------------------------------*/
#define MB_PDU_REQ_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 )
#define MB_PDU_REQ_READ_DISCCNT_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_REQ_READ_SIZE ( 4 )
#define MB_PDU_FUNC_READ_DISCCNT_OFF ( MB_PDU_DATA_OFF + 0 )
#define MB_PDU_FUNC_READ_VALUES_OFF ( MB_PDU_DATA_OFF + 1 )
#define MB_PDU_FUNC_READ_SIZE_MIN ( 1 )
/* ----------------------- Static functions ---------------------------------*/
eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
/* ----------------------- Start implementation -----------------------------*/
#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
#if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED > 0
/**
* This function will request read discrete inputs.
*
* @param ucSndAddr salve address
* @param usDiscreteAddr discrete start address
* @param usNDiscreteIn discrete total number
* @param lTimeOut timeout (-1 will waiting forever)
*
* @return error code
*/
eMBMasterReqErrCode
eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT usNDiscreteIn, LONG lTimeOut )
{
UCHAR *ucMBFrame;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
vMBMasterSetDestAddress(ucSndAddr);
ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READ_DISCRETE_INPUTS;
ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] = usDiscreteAddr >> 8;
ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] = usDiscreteAddr;
ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF ] = usNDiscreteIn >> 8;
ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF + 1] = usNDiscreteIn;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
eMBException
eMBMasterFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen )
{
USHORT usRegAddress;
USHORT usDiscreteCnt;
UCHAR ucNBytes;
UCHAR *ucMBFrame;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
/* If this request is broadcast, and it's read mode. This request don't need execute. */
if ( xMBMasterRequestIsBroadcast() )
{
eStatus = MB_EX_NONE;
}
else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 );
usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] );
usRegAddress++;
usDiscreteCnt = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF] << 8 );
usDiscreteCnt |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF + 1] );
/* Test if the quantity of coils is a multiple of 8. If not last
* byte is only partially field with unused coils set to zero. */
if( ( usDiscreteCnt & 0x0007 ) != 0 )
{
ucNBytes = ( UCHAR )( usDiscreteCnt / 8 + 1 );
}
else
{
ucNBytes = ( UCHAR )( usDiscreteCnt / 8 );
}
/* Check if the number of registers to read is valid. If not
* return Modbus illegal data value exception.
*/
if ((usDiscreteCnt >= 1) && ucNBytes == pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF])
{
/* Make callback to fill the buffer. */
eRegStatus = eMBMasterRegDiscreteCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usDiscreteCnt );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
{
eStatus = prveMBError2Exception( eRegStatus );
}
}
else
{
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
}
else
{
/* Can't be a valid read coil register request because the length
* is incorrect. */
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
return eStatus;
}
#endif
#endif
@@ -0,0 +1,308 @@
/*
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
* Copyright (c) 2006-2018 Christian Walter <cwalter@embedded-solutions.at>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* File: $Id: mbfuncholding.c,v 1.12 2007/02/18 23:48:22 wolti Exp $
*/
/* ----------------------- System includes ----------------------------------*/
#include "stdlib.h"
#include "string.h"
/* ----------------------- Platform includes --------------------------------*/
#include "port.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbframe.h"
#include "mbproto.h"
#include "mbconfig.h"
/* ----------------------- Defines ------------------------------------------*/
#define MB_PDU_FUNC_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0)
#define MB_PDU_FUNC_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_FUNC_READ_SIZE ( 4 )
#define MB_PDU_FUNC_READ_REGCNT_MAX ( 0x007D )
#define MB_PDU_FUNC_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 0)
#define MB_PDU_FUNC_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_FUNC_WRITE_SIZE ( 4 )
#define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF + 0 )
#define MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF ( MB_PDU_DATA_OFF + 4 )
#define MB_PDU_FUNC_WRITE_MUL_VALUES_OFF ( MB_PDU_DATA_OFF + 5 )
#define MB_PDU_FUNC_WRITE_MUL_SIZE_MIN ( 5 )
#define MB_PDU_FUNC_WRITE_MUL_REGCNT_MAX ( 0x0078 )
#define MB_PDU_FUNC_READWRITE_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 )
#define MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 4 )
#define MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF ( MB_PDU_DATA_OFF + 6 )
#define MB_PDU_FUNC_READWRITE_BYTECNT_OFF ( MB_PDU_DATA_OFF + 8 )
#define MB_PDU_FUNC_READWRITE_WRITE_VALUES_OFF ( MB_PDU_DATA_OFF + 9 )
#define MB_PDU_FUNC_READWRITE_SIZE_MIN ( 9 )
/* ----------------------- Static functions ---------------------------------*/
eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
/* ----------------------- Start implementation -----------------------------*/
#if MB_FUNC_WRITE_HOLDING_ENABLED > 0
eMBException
eMBFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
{
USHORT usRegAddress;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if( *usLen == ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) )
{
usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8 );
usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1] );
usRegAddress++;
/* Make callback to update the value. */
eRegStatus = eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF],
usRegAddress, 1, MB_REG_WRITE );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
{
eStatus = prveMBError2Exception( eRegStatus );
}
}
else
{
/* Can't be a valid request because the length is incorrect. */
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
return eStatus;
}
#endif
#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0
eMBException
eMBFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
{
USHORT usRegAddress;
USHORT usRegCount;
UCHAR ucRegByteCount;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if( *usLen >= ( MB_PDU_FUNC_WRITE_MUL_SIZE_MIN + MB_PDU_SIZE_MIN ) )
{
usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8 );
usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1] );
usRegAddress++;
usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF] << 8 );
usRegCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF + 1] );
ucRegByteCount = pucFrame[MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF];
if( ( usRegCount >= 1 ) &&
( usRegCount <= MB_PDU_FUNC_WRITE_MUL_REGCNT_MAX ) &&
( ucRegByteCount == ( UCHAR ) ( 2 * usRegCount ) ) )
{
/* Make callback to update the register values. */
eRegStatus =
eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_MUL_VALUES_OFF],
usRegAddress, usRegCount, MB_REG_WRITE );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
{
eStatus = prveMBError2Exception( eRegStatus );
}
else
{
/* The response contains the function code, the starting
* address and the quantity of registers. We reuse the
* old values in the buffer because they are still valid.
*/
*usLen = MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF;
}
}
else
{
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
}
else
{
/* Can't be a valid request because the length is incorrect. */
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
return eStatus;
}
#endif
#if MB_FUNC_READ_HOLDING_ENABLED > 0
eMBException
eMBFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
{
USHORT usRegAddress;
USHORT usRegCount;
UCHAR *pucFrameCur;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) )
{
usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 );
usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] );
usRegAddress++;
usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] << 8 );
usRegCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] );
/* Check if the number of registers to read is valid. If not
* return Modbus illegal data value exception.
*/
if( ( usRegCount >= 1 ) && ( usRegCount <= MB_PDU_FUNC_READ_REGCNT_MAX ) )
{
/* Set the current PDU data pointer to the beginning. */
pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF];
*usLen = MB_PDU_FUNC_OFF;
/* First byte contains the function code. */
*pucFrameCur++ = MB_FUNC_READ_HOLDING_REGISTER;
*usLen += 1;
/* Second byte in the response contain the number of bytes. */
*pucFrameCur++ = ( UCHAR ) ( usRegCount * 2 );
*usLen += 1;
/* Make callback to fill the buffer. */
eRegStatus = eMBRegHoldingCB( pucFrameCur, usRegAddress, usRegCount, MB_REG_READ );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
{
eStatus = prveMBError2Exception( eRegStatus );
}
else
{
*usLen += usRegCount * 2;
}
}
else
{
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
}
else
{
/* Can't be a valid request because the length is incorrect. */
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
return eStatus;
}
#endif
#if MB_FUNC_READWRITE_HOLDING_ENABLED > 0
eMBException
eMBFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
{
USHORT usRegReadAddress;
USHORT usRegReadCount;
USHORT usRegWriteAddress;
USHORT usRegWriteCount;
UCHAR ucRegWriteByteCount;
UCHAR *pucFrameCur;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if( *usLen >= ( MB_PDU_FUNC_READWRITE_SIZE_MIN + MB_PDU_SIZE_MIN ) )
{
usRegReadAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_ADDR_OFF] << 8U );
usRegReadAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_ADDR_OFF + 1] );
usRegReadAddress++;
usRegReadCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF] << 8U );
usRegReadCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF + 1] );
usRegWriteAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF] << 8U );
usRegWriteAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF + 1] );
usRegWriteAddress++;
usRegWriteCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF] << 8U );
usRegWriteCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF + 1] );
ucRegWriteByteCount = pucFrame[MB_PDU_FUNC_READWRITE_BYTECNT_OFF];
if( ( usRegReadCount >= 1 ) && ( usRegReadCount <= 0x7D ) &&
( usRegWriteCount >= 1 ) && ( usRegWriteCount <= 0x79 ) &&
( ( 2 * usRegWriteCount ) == ucRegWriteByteCount ) )
{
/* Make callback to update the register values. */
eRegStatus = eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_READWRITE_WRITE_VALUES_OFF],
usRegWriteAddress, usRegWriteCount, MB_REG_WRITE );
if( eRegStatus == MB_ENOERR )
{
/* Set the current PDU data pointer to the beginning. */
pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF];
*usLen = MB_PDU_FUNC_OFF;
/* First byte contains the function code. */
*pucFrameCur++ = MB_FUNC_READWRITE_MULTIPLE_REGISTERS;
*usLen += 1;
/* Second byte in the response contain the number of bytes. */
*pucFrameCur++ = ( UCHAR ) ( usRegReadCount * 2 );
*usLen += 1;
/* Make the read callback. */
eRegStatus =
eMBRegHoldingCB( pucFrameCur, usRegReadAddress, usRegReadCount, MB_REG_READ );
if( eRegStatus == MB_ENOERR )
{
*usLen += 2 * usRegReadCount;
}
}
if( eRegStatus != MB_ENOERR )
{
eStatus = prveMBError2Exception( eRegStatus );
}
}
else
{
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
}
return eStatus;
}
#endif
@@ -0,0 +1,455 @@
/*
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* File: $Id: mbfuncholding_m.c,v 1.60 2013/09/02 14:13:40 Armink Add Master Functions Exp $
*/
/* ----------------------- System includes ----------------------------------*/
#include "stdlib.h"
#include "string.h"
/* ----------------------- Platform includes --------------------------------*/
#include "port.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mb_m.h"
#include "mbframe.h"
#include "mbproto.h"
#include "mbconfig.h"
/* ----------------------- Defines ------------------------------------------*/
#define MB_PDU_REQ_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 )
#define MB_PDU_REQ_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_REQ_READ_SIZE ( 4 )
#define MB_PDU_FUNC_READ_REGCNT_MAX ( 0x007D )
#define MB_PDU_FUNC_READ_BYTECNT_OFF ( MB_PDU_DATA_OFF + 0 )
#define MB_PDU_FUNC_READ_VALUES_OFF ( MB_PDU_DATA_OFF + 1 )
#define MB_PDU_FUNC_READ_SIZE_MIN ( 1 )
#define MB_PDU_REQ_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 0)
#define MB_PDU_REQ_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_REQ_WRITE_SIZE ( 4 )
#define MB_PDU_FUNC_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 0)
#define MB_PDU_FUNC_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_FUNC_WRITE_SIZE ( 4 )
#define MB_PDU_REQ_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF + 0 )
#define MB_PDU_REQ_WRITE_MUL_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF ( MB_PDU_DATA_OFF + 4 )
#define MB_PDU_REQ_WRITE_MUL_VALUES_OFF ( MB_PDU_DATA_OFF + 5 )
#define MB_PDU_REQ_WRITE_MUL_SIZE_MIN ( 5 )
#define MB_PDU_REQ_WRITE_MUL_REGCNT_MAX ( 0x0078 )
#define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF + 0 )
#define MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_FUNC_WRITE_MUL_SIZE ( 4 )
#define MB_PDU_REQ_READWRITE_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 )
#define MB_PDU_REQ_READWRITE_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 4 )
#define MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF ( MB_PDU_DATA_OFF + 6 )
#define MB_PDU_REQ_READWRITE_WRITE_BYTECNT_OFF ( MB_PDU_DATA_OFF + 8 )
#define MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF ( MB_PDU_DATA_OFF + 9 )
#define MB_PDU_REQ_READWRITE_SIZE_MIN ( 9 )
#define MB_PDU_FUNC_READWRITE_READ_BYTECNT_OFF ( MB_PDU_DATA_OFF + 0 )
#define MB_PDU_FUNC_READWRITE_READ_VALUES_OFF ( MB_PDU_DATA_OFF + 1 )
#define MB_PDU_FUNC_READWRITE_SIZE_MIN ( 1 )
/* ----------------------- Static functions ---------------------------------*/
eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
/* ----------------------- Start implementation -----------------------------*/
#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
#if MB_FUNC_WRITE_HOLDING_ENABLED > 0
/**
* This function will request write holding register.
*
* @param ucSndAddr salve address
* @param usRegAddr register start address
* @param usRegData register data to be written
* @param lTimeOut timeout (-1 will waiting forever)
*
* @return error code
*/
eMBMasterReqErrCode
eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut )
{
UCHAR *ucMBFrame;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
vMBMasterSetDestAddress(ucSndAddr);
ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_REGISTER;
ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF] = usRegAddr >> 8;
ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF + 1] = usRegAddr;
ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF] = usRegData >> 8;
ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usRegData ;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
eMBException
eMBMasterFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
{
USHORT usRegAddress;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if( *usLen == ( MB_PDU_SIZE_MIN + MB_PDU_FUNC_WRITE_SIZE ) )
{
usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8 );
usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1] );
usRegAddress++;
/* Make callback to update the value. */
eRegStatus = eMBMasterRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF],
usRegAddress, 1, MB_REG_WRITE );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
{
eStatus = prveMBError2Exception( eRegStatus );
}
}
else
{
/* Can't be a valid request because the length is incorrect. */
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
return eStatus;
}
#endif
#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0
/**
* This function will request write multiple holding register.
*
* @param ucSndAddr salve address
* @param usRegAddr register start address
* @param usNRegs register total number
* @param pusDataBuffer data to be written
* @param lTimeOut timeout (-1 will waiting forever)
*
* @return error code
*/
eMBMasterReqErrCode
eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr,
USHORT usRegAddr, USHORT usNRegs, USHORT * pusDataBuffer, LONG lTimeOut )
{
UCHAR *ucMBFrame;
USHORT usRegIndex = 0;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
vMBMasterSetDestAddress(ucSndAddr);
ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_MULTIPLE_REGISTERS;
ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] = usRegAddr >> 8;
ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1] = usRegAddr;
ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF] = usNRegs >> 8;
ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF + 1] = usNRegs ;
ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF] = usNRegs * 2;
ucMBFrame += MB_PDU_REQ_WRITE_MUL_VALUES_OFF;
while( usNRegs > usRegIndex)
{
*ucMBFrame++ = pusDataBuffer[usRegIndex] >> 8;
*ucMBFrame++ = pusDataBuffer[usRegIndex++] ;
}
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + 2*usNRegs );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
eMBException
eMBMasterFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
{
UCHAR *ucMBFrame;
USHORT usRegAddress;
USHORT usRegCount;
UCHAR ucRegByteCount;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
/* If this request is broadcast, the *usLen is not need check. */
if( ( *usLen == MB_PDU_SIZE_MIN + MB_PDU_FUNC_WRITE_MUL_SIZE ) || xMBMasterRequestIsBroadcast() )
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] << 8 );
usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1] );
usRegAddress++;
usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF] << 8 );
usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF + 1] );
ucRegByteCount = ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF];
if( ucRegByteCount == 2 * usRegCount )
{
/* Make callback to update the register values. */
eRegStatus =
eMBMasterRegHoldingCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF],
usRegAddress, usRegCount, MB_REG_WRITE );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
{
eStatus = prveMBError2Exception( eRegStatus );
}
}
else
{
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
}
else
{
/* Can't be a valid request because the length is incorrect. */
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
return eStatus;
}
#endif
#if MB_FUNC_READ_HOLDING_ENABLED > 0
/**
* This function will request read holding register.
*
* @param ucSndAddr salve address
* @param usRegAddr register start address
* @param usNRegs register total number
* @param lTimeOut timeout (-1 will waiting forever)
*
* @return error code
*/
eMBMasterReqErrCode
eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut )
{
UCHAR *ucMBFrame;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
vMBMasterSetDestAddress(ucSndAddr);
ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READ_HOLDING_REGISTER;
ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] = usRegAddr >> 8;
ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] = usRegAddr;
ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] = usNRegs >> 8;
ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
eMBException
eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
{
UCHAR *ucMBFrame;
USHORT usRegAddress;
USHORT usRegCount;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
/* If this request is broadcast, and it's read mode. This request don't need execute. */
if ( xMBMasterRequestIsBroadcast() )
{
eStatus = MB_EX_NONE;
}
else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 );
usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] );
usRegAddress++;
usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] << 8 );
usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] );
/* Check if the number of registers to read is valid. If not
* return Modbus illegal data value exception.
*/
if( ( usRegCount >= 1 ) && ( 2 * usRegCount == pucFrame[MB_PDU_FUNC_READ_BYTECNT_OFF] ) )
{
/* Make callback to fill the buffer. */
eRegStatus = eMBMasterRegHoldingCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount, MB_REG_READ );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
{
eStatus = prveMBError2Exception( eRegStatus );
}
}
else
{
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
}
else
{
/* Can't be a valid request because the length is incorrect. */
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
return eStatus;
}
#endif
#if MB_FUNC_READWRITE_HOLDING_ENABLED > 0
/**
* This function will request read and write holding register.
*
* @param ucSndAddr salve address
* @param usReadRegAddr read register start address
* @param usNReadRegs read register total number
* @param pusDataBuffer data to be written
* @param usWriteRegAddr write register start address
* @param usNWriteRegs write register total number
* @param lTimeOut timeout (-1 will waiting forever)
*
* @return error code
*/
eMBMasterReqErrCode
eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr,
USHORT usReadRegAddr, USHORT usNReadRegs, USHORT * pusDataBuffer,
USHORT usWriteRegAddr, USHORT usNWriteRegs, LONG lTimeOut )
{
UCHAR *ucMBFrame;
USHORT usRegIndex = 0;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
vMBMasterSetDestAddress(ucSndAddr);
ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READWRITE_MULTIPLE_REGISTERS;
ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF] = usReadRegAddr >> 8;
ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF + 1] = usReadRegAddr;
ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF] = usNReadRegs >> 8;
ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF + 1] = usNReadRegs ;
ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF] = usWriteRegAddr >> 8;
ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF + 1] = usWriteRegAddr;
ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF] = usNWriteRegs >> 8;
ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF + 1] = usNWriteRegs ;
ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_BYTECNT_OFF] = usNWriteRegs * 2;
ucMBFrame += MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF;
while( usNWriteRegs > usRegIndex)
{
*ucMBFrame++ = pusDataBuffer[usRegIndex] >> 8;
*ucMBFrame++ = pusDataBuffer[usRegIndex++] ;
}
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READWRITE_SIZE_MIN + 2*usNWriteRegs );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
eMBException
eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
{
USHORT usRegReadAddress;
USHORT usRegReadCount;
USHORT usRegWriteAddress;
USHORT usRegWriteCount;
UCHAR *ucMBFrame;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
/* If this request is broadcast, and it's read mode. This request don't need execute. */
if ( xMBMasterRequestIsBroadcast() )
{
eStatus = MB_EX_NONE;
}
else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READWRITE_SIZE_MIN )
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
usRegReadAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF] << 8U );
usRegReadAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF + 1] );
usRegReadAddress++;
usRegReadCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF] << 8U );
usRegReadCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF + 1] );
usRegWriteAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF] << 8U );
usRegWriteAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF + 1] );
usRegWriteAddress++;
usRegWriteCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF] << 8U );
usRegWriteCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF + 1] );
if( ( 2 * usRegReadCount ) == pucFrame[MB_PDU_FUNC_READWRITE_READ_BYTECNT_OFF] )
{
/* Make callback to update the register values. */
eRegStatus = eMBMasterRegHoldingCB( &ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF],
usRegWriteAddress, usRegWriteCount, MB_REG_WRITE );
if( eRegStatus == MB_ENOERR )
{
/* Make the read callback. */
eRegStatus = eMBMasterRegHoldingCB(&pucFrame[MB_PDU_FUNC_READWRITE_READ_VALUES_OFF],
usRegReadAddress, usRegReadCount, MB_REG_READ);
}
if( eRegStatus != MB_ENOERR )
{
eStatus = prveMBError2Exception( eRegStatus );
}
}
else
{
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
}
return eStatus;
}
#endif
#endif
@@ -0,0 +1,122 @@
/*
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
* Copyright (c) 2006-2018 Christian Walter <cwalter@embedded-solutions.at>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* File: $Id: mbfuncinput.c,v 1.10 2007/09/12 10:15:56 wolti Exp $
*/
/* ----------------------- System includes ----------------------------------*/
#include "stdlib.h"
#include "string.h"
/* ----------------------- Platform includes --------------------------------*/
#include "port.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbframe.h"
#include "mbproto.h"
#include "mbconfig.h"
/* ----------------------- Defines ------------------------------------------*/
#define MB_PDU_FUNC_READ_ADDR_OFF ( MB_PDU_DATA_OFF )
#define MB_PDU_FUNC_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_FUNC_READ_SIZE ( 4 )
#define MB_PDU_FUNC_READ_REGCNT_MAX ( 0x007D )
#define MB_PDU_FUNC_READ_RSP_BYTECNT_OFF ( MB_PDU_DATA_OFF )
/* ----------------------- Static functions ---------------------------------*/
eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
/* ----------------------- Start implementation -----------------------------*/
#if MB_FUNC_READ_INPUT_ENABLED > 0
eMBException
eMBFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen )
{
USHORT usRegAddress;
USHORT usRegCount;
UCHAR *pucFrameCur;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) )
{
usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 );
usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] );
usRegAddress++;
usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] << 8 );
usRegCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] );
/* Check if the number of registers to read is valid. If not
* return Modbus illegal data value exception.
*/
if( ( usRegCount >= 1 )
&& ( usRegCount < MB_PDU_FUNC_READ_REGCNT_MAX ) )
{
/* Set the current PDU data pointer to the beginning. */
pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF];
*usLen = MB_PDU_FUNC_OFF;
/* First byte contains the function code. */
*pucFrameCur++ = MB_FUNC_READ_INPUT_REGISTER;
*usLen += 1;
/* Second byte in the response contain the number of bytes. */
*pucFrameCur++ = ( UCHAR )( usRegCount * 2 );
*usLen += 1;
eRegStatus =
eMBRegInputCB( pucFrameCur, usRegAddress, usRegCount );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
{
eStatus = prveMBError2Exception( eRegStatus );
}
else
{
*usLen += usRegCount * 2;
}
}
else
{
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
}
else
{
/* Can't be a valid read input register request because the length
* is incorrect. */
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
return eStatus;
}
#endif
@@ -0,0 +1,148 @@
/*
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* File: $Id: mbfuncinput_m.c,v 1.60 2013/10/12 14:23:40 Armink Add Master Functions Exp $
*/
/* ----------------------- System includes ----------------------------------*/
#include "stdlib.h"
#include "string.h"
/* ----------------------- Platform includes --------------------------------*/
#include "port.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mb_m.h"
#include "mbframe.h"
#include "mbproto.h"
#include "mbconfig.h"
/* ----------------------- Defines ------------------------------------------*/
#define MB_PDU_REQ_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 )
#define MB_PDU_REQ_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 )
#define MB_PDU_REQ_READ_SIZE ( 4 )
#define MB_PDU_FUNC_READ_BYTECNT_OFF ( MB_PDU_DATA_OFF + 0 )
#define MB_PDU_FUNC_READ_VALUES_OFF ( MB_PDU_DATA_OFF + 1 )
#define MB_PDU_FUNC_READ_SIZE_MIN ( 1 )
#define MB_PDU_FUNC_READ_RSP_BYTECNT_OFF ( MB_PDU_DATA_OFF )
/* ----------------------- Static functions ---------------------------------*/
eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
/* ----------------------- Start implementation -----------------------------*/
#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
#if MB_FUNC_READ_INPUT_ENABLED > 0
/**
* This function will request read input register.
*
* @param ucSndAddr salve address
* @param usRegAddr register start address
* @param usNRegs register total number
* @param lTimeOut timeout (-1 will waiting forever)
*
* @return error code
*/
eMBMasterReqErrCode
eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut )
{
UCHAR *ucMBFrame;
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
else
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
vMBMasterSetDestAddress(ucSndAddr);
ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READ_INPUT_REGISTER;
ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] = usRegAddr >> 8;
ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] = usRegAddr;
ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] = usNRegs >> 8;
ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
eErrStatus = eMBMasterWaitRequestFinish( );
}
return eErrStatus;
}
eMBException
eMBMasterFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen )
{
UCHAR *ucMBFrame;
USHORT usRegAddress;
USHORT usRegCount;
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
/* If this request is broadcast, and it's read mode. This request don't need execute. */
if ( xMBMasterRequestIsBroadcast() )
{
eStatus = MB_EX_NONE;
}
else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
{
vMBMasterGetPDUSndBuf(&ucMBFrame);
usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 );
usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] );
usRegAddress++;
usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] << 8 );
usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] );
/* Check if the number of registers to read is valid. If not
* return Modbus illegal data value exception.
*/
if( ( usRegCount >= 1 ) && ( 2 * usRegCount == pucFrame[MB_PDU_FUNC_READ_BYTECNT_OFF] ) )
{
/* Make callback to fill the buffer. */
eRegStatus = eMBMasterRegInputCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount );
/* If an error occured convert it into a Modbus exception. */
if( eRegStatus != MB_ENOERR )
{
eStatus = prveMBError2Exception( eRegStatus );
}
}
else
{
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
}
else
{
/* Can't be a valid request because the length is incorrect. */
eStatus = MB_EX_ILLEGAL_DATA_VALUE;
}
return eStatus;
}
#endif
#endif
@@ -0,0 +1,88 @@
/*
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
* Copyright (c) 2006-2018 Christian Walter <cwalter@embedded-solutions.at>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* File: $Id: mbfuncother.c,v 1.8 2006/12/07 22:10:34 wolti Exp $
*/
/* ----------------------- System includes ----------------------------------*/
#include "stdlib.h"
#include "string.h"
/* ----------------------- Platform includes --------------------------------*/
#include "port.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbframe.h"
#include "mbproto.h"
#include "mbconfig.h"
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED > 0
/* ----------------------- Static variables ---------------------------------*/
static UCHAR ucMBSlaveID[MB_FUNC_OTHER_REP_SLAVEID_BUF];
static USHORT usMBSlaveIDLen;
/* ----------------------- Start implementation -----------------------------*/
eMBErrorCode
eMBSetSlaveID( UCHAR ucSlaveID, BOOL xIsRunning,
UCHAR const *pucAdditional, USHORT usAdditionalLen )
{
eMBErrorCode eStatus = MB_ENOERR;
/* the first byte and second byte in the buffer is reserved for
* the parameter ucSlaveID and the running flag. The rest of
* the buffer is available for additional data. */
if( usAdditionalLen + 2 < MB_FUNC_OTHER_REP_SLAVEID_BUF )
{
usMBSlaveIDLen = 0;
ucMBSlaveID[usMBSlaveIDLen++] = ucSlaveID;
ucMBSlaveID[usMBSlaveIDLen++] = ( UCHAR )( xIsRunning ? 0xFF : 0x00 );
if( usAdditionalLen > 0 )
{
memcpy( &ucMBSlaveID[usMBSlaveIDLen], pucAdditional,
( size_t )usAdditionalLen );
usMBSlaveIDLen += usAdditionalLen;
}
}
else
{
eStatus = MB_ENORES;
}
return eStatus;
}
eMBException
eMBFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen )
{
memcpy( &pucFrame[MB_PDU_DATA_OFF], &ucMBSlaveID[0], ( size_t )usMBSlaveIDLen );
*usLen = ( USHORT )( MB_PDU_DATA_OFF + usMBSlaveIDLen );
return MB_EX_NONE;
}
#endif
+141
View File
@@ -0,0 +1,141 @@
/*
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
* Copyright (c) 2006-2018 Christian Walter <cwalter@embedded-solutions.at>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* File: $Id: mbutils.c,v 1.6 2007/02/18 23:49:07 wolti Exp $
*/
/* ----------------------- System includes ----------------------------------*/
#include "stdlib.h"
#include "string.h"
/* ----------------------- Platform includes --------------------------------*/
#include "port.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbproto.h"
/* ----------------------- Defines ------------------------------------------*/
#define BITS_UCHAR 8U
/* ----------------------- Start implementation -----------------------------*/
void
xMBUtilSetBits( UCHAR * ucByteBuf, USHORT usBitOffset, UCHAR ucNBits,
UCHAR ucValue )
{
USHORT usWordBuf;
USHORT usMask;
USHORT usByteOffset;
USHORT usNPreBits;
USHORT usValue = ucValue;
RT_ASSERT( ucNBits <= 8 );
RT_ASSERT( ( size_t )BITS_UCHAR == sizeof( UCHAR ) * 8 );
/* Calculate byte offset for first byte containing the bit values starting
* at usBitOffset. */
usByteOffset = ( USHORT )( ( usBitOffset ) / BITS_UCHAR );
/* How many bits precede our bits to set. */
usNPreBits = ( USHORT )( usBitOffset - usByteOffset * BITS_UCHAR );
/* Move bit field into position over bits to set */
usValue <<= usNPreBits;
/* Prepare a mask for setting the new bits. */
usMask = ( USHORT )( ( 1 << ( USHORT ) ucNBits ) - 1 );
usMask <<= usBitOffset - usByteOffset * BITS_UCHAR;
/* copy bits into temporary storage. */
usWordBuf = ucByteBuf[usByteOffset];
usWordBuf |= ucByteBuf[usByteOffset + 1] << BITS_UCHAR;
/* Zero out bit field bits and then or value bits into them. */
usWordBuf = ( USHORT )( ( usWordBuf & ( ~usMask ) ) | usValue );
/* move bits back into storage */
ucByteBuf[usByteOffset] = ( UCHAR )( usWordBuf & 0xFF );
ucByteBuf[usByteOffset + 1] = ( UCHAR )( usWordBuf >> BITS_UCHAR );
}
UCHAR
xMBUtilGetBits( UCHAR * ucByteBuf, USHORT usBitOffset, UCHAR ucNBits )
{
USHORT usWordBuf;
USHORT usMask;
USHORT usByteOffset;
USHORT usNPreBits;
/* Calculate byte offset for first byte containing the bit values starting
* at usBitOffset. */
usByteOffset = ( USHORT )( ( usBitOffset ) / BITS_UCHAR );
/* How many bits precede our bits to set. */
usNPreBits = ( USHORT )( usBitOffset - usByteOffset * BITS_UCHAR );
/* Prepare a mask for setting the new bits. */
usMask = ( USHORT )( ( 1 << ( USHORT ) ucNBits ) - 1 );
/* copy bits into temporary storage. */
usWordBuf = ucByteBuf[usByteOffset];
usWordBuf |= ucByteBuf[usByteOffset + 1] << BITS_UCHAR;
/* throw away unneeded bits. */
usWordBuf >>= usNPreBits;
/* mask away bits above the requested bitfield. */
usWordBuf &= usMask;
return ( UCHAR ) usWordBuf;
}
eMBException
prveMBError2Exception( eMBErrorCode eErrorCode )
{
eMBException eStatus;
switch ( eErrorCode )
{
case MB_ENOERR:
eStatus = MB_EX_NONE;
break;
case MB_ENOREG:
eStatus = MB_EX_ILLEGAL_DATA_ADDRESS;
break;
case MB_ETIMEDOUT:
eStatus = MB_EX_SLAVE_BUSY;
break;
default:
eStatus = MB_EX_SLAVE_DEVICE_FAILURE;
break;
}
return eStatus;
}
+417
View File
@@ -0,0 +1,417 @@
/*
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
* Copyright (c) 2006-2018 Christian Walter <cwalter@embedded-solutions.at>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* File: $Id: mb.h,v 1.17 2006/12/07 22:10:34 wolti Exp $
*/
#ifndef _MB_H
#define _MB_H
#include "port.h"
#ifdef __cplusplus
PR_BEGIN_EXTERN_C
#endif
#include "mbport.h"
#include "mbproto.h"
/*! \defgroup modbus Modbus
* \code #include "mb.h" \endcode
*
* This module defines the interface for the application. It contains
* the basic functions and types required to use the Modbus protocol stack.
* A typical application will want to call eMBInit() first. If the device
* is ready to answer network requests it must then call eMBEnable() to activate
* the protocol stack. In the main loop the function eMBPoll() must be called
* periodically. The time interval between pooling depends on the configured
* Modbus timeout. If an RTOS is available a separate task should be created
* and the task should always call the function eMBPoll().
*
* \code
* // Initialize protocol stack in RTU mode for a slave with address 10 = 0x0A
* eMBInit( MB_RTU, 0x0A, 38400, MB_PAR_EVEN );
* // Enable the Modbus Protocol Stack.
* eMBEnable( );
* for( ;; )
* {
* // Call the main polling loop of the Modbus protocol stack.
* eMBPoll( );
* ...
* }
* \endcode
*/
/* ----------------------- Defines ------------------------------------------*/
/*! \ingroup modbus
* \brief Use the default Modbus TCP port (502)
*/
#define MB_TCP_PORT_USE_DEFAULT 0
/* ----------------------- Type definitions ---------------------------------*/
/*! \ingroup modbus
* \brief Modbus serial transmission modes (RTU/ASCII).
*
* Modbus serial supports two transmission modes. Either ASCII or RTU. RTU
* is faster but has more hardware requirements and requires a network with
* a low jitter. ASCII is slower and more reliable on slower links (E.g. modems)
*/
typedef enum
{
MB_RTU, /*!< RTU transmission mode. */
MB_ASCII, /*!< ASCII transmission mode. */
MB_TCP /*!< TCP mode. */
} eMBMode;
/*! \ingroup modbus
* \brief If register should be written or read.
*
* This value is passed to the callback functions which support either
* reading or writing register values. Writing means that the application
* registers should be updated and reading means that the modbus protocol
* stack needs to know the current register values.
*
* \see eMBRegHoldingCB( ), eMBRegCoilsCB( ), eMBRegDiscreteCB( ) and
* eMBRegInputCB( ).
*/
typedef enum
{
MB_REG_READ, /*!< Read register values and pass to protocol stack. */
MB_REG_WRITE /*!< Update register values. */
} eMBRegisterMode;
/*! \ingroup modbus
* \brief Errorcodes used by all function in the protocol stack.
*/
typedef enum
{
MB_ENOERR, /*!< no error. */
MB_ENOREG, /*!< illegal register address. */
MB_EINVAL, /*!< illegal argument. */
MB_EPORTERR, /*!< porting layer error. */
MB_ENORES, /*!< insufficient resources. */
MB_EIO, /*!< I/O error. */
MB_EILLSTATE, /*!< protocol stack in illegal state. */
MB_ETIMEDOUT /*!< timeout error occurred. */
} eMBErrorCode;
/* ----------------------- Function prototypes ------------------------------*/
/*! \ingroup modbus
* \brief Initialize the Modbus protocol stack.
*
* This functions initializes the ASCII or RTU module and calls the
* init functions of the porting layer to prepare the hardware. Please
* note that the receiver is still disabled and no Modbus frames are
* processed until eMBEnable( ) has been called.
*
* \param eMode If ASCII or RTU mode should be used.
* \param ucSlaveAddress The slave address. Only frames sent to this
* address or to the broadcast address are processed.
* \param ucPort The port to use. E.g. 1 for COM1 on windows. This value
* is platform dependent and some ports simply choose to ignore it.
* \param ulBaudRate The baudrate. E.g. 19200. Supported baudrates depend
* on the porting layer.
* \param eParity Parity used for serial transmission.
*
* \return If no error occurs the function returns eMBErrorCode::MB_ENOERR.
* The protocol is then in the disabled state and ready for activation
* by calling eMBEnable( ). Otherwise one of the following error codes
* is returned:
* - eMBErrorCode::MB_EINVAL If the slave address was not valid. Valid
* slave addresses are in the range 1 - 247.
* - eMBErrorCode::MB_EPORTERR IF the porting layer returned an error.
*/
eMBErrorCode eMBInit( eMBMode eMode, UCHAR ucSlaveAddress,
UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity );
/*! \ingroup modbus
* \brief Initialize the Modbus protocol stack for Modbus TCP.
*
* This function initializes the Modbus TCP Module. Please note that
* frame processing is still disabled until eMBEnable( ) is called.
*
* \param usTCPPort The TCP port to listen on.
* \return If the protocol stack has been initialized correctly the function
* returns eMBErrorCode::MB_ENOERR. Otherwise one of the following error
* codes is returned:
* - eMBErrorCode::MB_EINVAL If the slave address was not valid. Valid
* slave addresses are in the range 1 - 247.
* - eMBErrorCode::MB_EPORTERR IF the porting layer returned an error.
*/
eMBErrorCode eMBTCPInit( USHORT usTCPPort );
/*! \ingroup modbus
* \brief Release resources used by the protocol stack.
*
* This function disables the Modbus protocol stack and release all
* hardware resources. It must only be called when the protocol stack
* is disabled.
*
* \note Note all ports implement this function. A port which wants to
* get an callback must define the macro MB_PORT_HAS_CLOSE to 1.
*
* \return If the resources where released it return eMBErrorCode::MB_ENOERR.
* If the protocol stack is not in the disabled state it returns
* eMBErrorCode::MB_EILLSTATE.
*/
eMBErrorCode eMBClose( void );
/*! \ingroup modbus
* \brief Enable the Modbus protocol stack.
*
* This function enables processing of Modbus frames. Enabling the protocol
* stack is only possible if it is in the disabled state.
*
* \return If the protocol stack is now in the state enabled it returns
* eMBErrorCode::MB_ENOERR. If it was not in the disabled state it
* return eMBErrorCode::MB_EILLSTATE.
*/
eMBErrorCode eMBEnable( void );
/*! \ingroup modbus
* \brief Disable the Modbus protocol stack.
*
* This function disables processing of Modbus frames.
*
* \return If the protocol stack has been disabled it returns
* eMBErrorCode::MB_ENOERR. If it was not in the enabled state it returns
* eMBErrorCode::MB_EILLSTATE.
*/
eMBErrorCode eMBDisable( void );
/*! \ingroup modbus
* \brief The main pooling loop of the Modbus protocol stack.
*
* This function must be called periodically. The timer interval required
* is given by the application dependent Modbus slave timeout. Internally the
* function calls xMBPortEventGet() and waits for an event from the receiver or
* transmitter state machines.
*
* \return If the protocol stack is not in the enabled state the function
* returns eMBErrorCode::MB_EILLSTATE. Otherwise it returns
* eMBErrorCode::MB_ENOERR.
*/
eMBErrorCode eMBPoll( void );
/*! \ingroup modbus
* \brief Configure the slave id of the device.
*
* This function should be called when the Modbus function <em>Report Slave ID</em>
* is enabled ( By defining MB_FUNC_OTHER_REP_SLAVEID_ENABLED in mbconfig.h ).
*
* \param ucSlaveID Values is returned in the <em>Slave ID</em> byte of the
* <em>Report Slave ID</em> response.
* \param xIsRunning If TRUE the <em>Run Indicator Status</em> byte is set to 0xFF.
* otherwise the <em>Run Indicator Status</em> is 0x00.
* \param pucAdditional Values which should be returned in the <em>Additional</em>
* bytes of the <em> Report Slave ID</em> response.
* \param usAdditionalLen Length of the buffer <code>pucAdditonal</code>.
*
* \return If the static buffer defined by MB_FUNC_OTHER_REP_SLAVEID_BUF in
* mbconfig.h is to small it returns eMBErrorCode::MB_ENORES. Otherwise
* it returns eMBErrorCode::MB_ENOERR.
*/
eMBErrorCode eMBSetSlaveID( UCHAR ucSlaveID, BOOL xIsRunning,
UCHAR const *pucAdditional,
USHORT usAdditionalLen );
/*! \ingroup modbus
* \brief Registers a callback handler for a given function code.
*
* This function registers a new callback handler for a given function code.
* The callback handler supplied is responsible for interpreting the Modbus PDU and
* the creation of an appropriate response. In case of an error it should return
* one of the possible Modbus exceptions which results in a Modbus exception frame
* sent by the protocol stack.
*
* \param ucFunctionCode The Modbus function code for which this handler should
* be registers. Valid function codes are in the range 1 to 127.
* \param pxHandler The function handler which should be called in case
* such a frame is received. If \c NULL a previously registered function handler
* for this function code is removed.
*
* \return eMBErrorCode::MB_ENOERR if the handler has been installed. If no
* more resources are available it returns eMBErrorCode::MB_ENORES. In this
* case the values in mbconfig.h should be adjusted. If the argument was not
* valid it returns eMBErrorCode::MB_EINVAL.
*/
eMBErrorCode eMBRegisterCB( UCHAR ucFunctionCode,
pxMBFunctionHandler pxHandler );
/* ----------------------- Callback -----------------------------------------*/
/*! \defgroup modbus_registers Modbus Registers
* \code #include "mb.h" \endcode
* The protocol stack does not internally allocate any memory for the
* registers. This makes the protocol stack very small and also usable on
* low end targets. In addition the values don't have to be in the memory
* and could for example be stored in a flash.<br>
* Whenever the protocol stack requires a value it calls one of the callback
* function with the register address and the number of registers to read
* as an argument. The application should then read the actual register values
* (for example the ADC voltage) and should store the result in the supplied
* buffer.<br>
* If the protocol stack wants to update a register value because a write
* register function was received a buffer with the new register values is
* passed to the callback function. The function should then use these values
* to update the application register values.
*/
/*! \ingroup modbus_registers
* \brief Callback function used if the value of a <em>Input Register</em>
* is required by the protocol stack. The starting register address is given
* by \c usAddress and the last register is given by <tt>usAddress +
* usNRegs - 1</tt>.
*
* \param pucRegBuffer A buffer where the callback function should write
* the current value of the modbus registers to.
* \param usAddress The starting address of the register. Input registers
* are in the range 1 - 65535.
* \param usNRegs Number of registers the callback function must supply.
*
* \return The function must return one of the following error codes:
* - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
* Modbus response is sent.
* - eMBErrorCode::MB_ENOREG If the application can not supply values
* for registers within this range. In this case a
* <b>ILLEGAL DATA ADDRESS</b> exception frame is sent as a response.
* - eMBErrorCode::MB_ETIMEDOUT If the requested register block is
* currently not available and the application dependent response
* timeout would be violated. In this case a <b>SLAVE DEVICE BUSY</b>
* exception is sent as a response.
* - eMBErrorCode::MB_EIO If an unrecoverable error occurred. In this case
* a <b>SLAVE DEVICE FAILURE</b> exception is sent as a response.
*/
eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress,
USHORT usNRegs );
/*! \ingroup modbus_registers
* \brief Callback function used if a <em>Holding Register</em> value is
* read or written by the protocol stack. The starting register address
* is given by \c usAddress and the last register is given by
* <tt>usAddress + usNRegs - 1</tt>.
*
* \param pucRegBuffer If the application registers values should be updated the
* buffer points to the new registers values. If the protocol stack needs
* to now the current values the callback function should write them into
* this buffer.
* \param usAddress The starting address of the register.
* \param usNRegs Number of registers to read or write.
* \param eMode If eMBRegisterMode::MB_REG_WRITE the application register
* values should be updated from the values in the buffer. For example
* this would be the case when the Modbus master has issued an
* <b>WRITE SINGLE REGISTER</b> command.
* If the value eMBRegisterMode::MB_REG_READ the application should copy
* the current values into the buffer \c pucRegBuffer.
*
* \return The function must return one of the following error codes:
* - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
* Modbus response is sent.
* - eMBErrorCode::MB_ENOREG If the application can not supply values
* for registers within this range. In this case a
* <b>ILLEGAL DATA ADDRESS</b> exception frame is sent as a response.
* - eMBErrorCode::MB_ETIMEDOUT If the requested register block is
* currently not available and the application dependent response
* timeout would be violated. In this case a <b>SLAVE DEVICE BUSY</b>
* exception is sent as a response.
* - eMBErrorCode::MB_EIO If an unrecoverable error occurred. In this case
* a <b>SLAVE DEVICE FAILURE</b> exception is sent as a response.
*/
eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress,
USHORT usNRegs, eMBRegisterMode eMode );
/*! \ingroup modbus_registers
* \brief Callback function used if a <em>Coil Register</em> value is
* read or written by the protocol stack. If you are going to use
* this function you might use the functions xMBUtilSetBits( ) and
* xMBUtilGetBits( ) for working with bitfields.
*
* \param pucRegBuffer The bits are packed in bytes where the first coil
* starting at address \c usAddress is stored in the LSB of the
* first byte in the buffer <code>pucRegBuffer</code>.
* If the buffer should be written by the callback function unused
* coil values (I.e. if not a multiple of eight coils is used) should be set
* to zero.
* \param usAddress The first coil number.
* \param usNCoils Number of coil values requested.
* \param eMode If eMBRegisterMode::MB_REG_WRITE the application values should
* be updated from the values supplied in the buffer \c pucRegBuffer.
* If eMBRegisterMode::MB_REG_READ the application should store the current
* values in the buffer \c pucRegBuffer.
*
* \return The function must return one of the following error codes:
* - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
* Modbus response is sent.
* - eMBErrorCode::MB_ENOREG If the application does not map an coils
* within the requested address range. In this case a
* <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
* - eMBErrorCode::MB_ETIMEDOUT If the requested register block is
* currently not available and the application dependent response
* timeout would be violated. In this case a <b>SLAVE DEVICE BUSY</b>
* exception is sent as a response.
* - eMBErrorCode::MB_EIO If an unrecoverable error occurred. In this case
* a <b>SLAVE DEVICE FAILURE</b> exception is sent as a response.
*/
eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress,
USHORT usNCoils, eMBRegisterMode eMode );
/*! \ingroup modbus_registers
* \brief Callback function used if a <em>Input Discrete Register</em> value is
* read by the protocol stack.
*
* If you are going to use his function you might use the functions
* xMBUtilSetBits( ) and xMBUtilGetBits( ) for working with bitfields.
*
* \param pucRegBuffer The buffer should be updated with the current
* coil values. The first discrete input starting at \c usAddress must be
* stored at the LSB of the first byte in the buffer. If the requested number
* is not a multiple of eight the remaining bits should be set to zero.
* \param usAddress The starting address of the first discrete input.
* \param usNDiscrete Number of discrete input values.
* \return The function must return one of the following error codes:
* - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
* Modbus response is sent.
* - eMBErrorCode::MB_ENOREG If no such discrete inputs exists.
* In this case a <b>ILLEGAL DATA ADDRESS</b> exception frame is sent
* as a response.
* - eMBErrorCode::MB_ETIMEDOUT If the requested register block is
* currently not available and the application dependent response
* timeout would be violated. In this case a <b>SLAVE DEVICE BUSY</b>
* exception is sent as a response.
* - eMBErrorCode::MB_EIO If an unrecoverable error occurred. In this case
* a <b>SLAVE DEVICE FAILURE</b> exception is sent as a response.
*/
eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress,
USHORT usNDiscrete );
#ifdef __cplusplus
PR_END_EXTERN_C
#endif
#endif
+414
View File
@@ -0,0 +1,414 @@
/*
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* File: $Id: mb_m.h,v 1.60 2013/09/03 10:20:05 Armink Add Master Functions $
*/
#ifndef _MB_M_H
#define _MB_M_H
#ifdef __cplusplus
PR_BEGIN_EXTERN_C
#endif
/*! \defgroup modbus Modbus
* \code #include "mb_m.h" \endcode
*
* This module defines the interface for the application. It contains
* the basic functions and types required to use the Modbus Master protocol stack.
* A typical application will want to call eMBMasterInit() first. If the device
* is ready to answer network requests it must then call eMBEnable() to activate
* the protocol stack. In the main loop the function eMBMasterPoll() must be called
* periodically. The time interval between pooling depends on the configured
* Modbus timeout. If an RTOS is available a separate task should be created
* and the task should always call the function eMBMasterPoll().
*
* \code
* // Initialize protocol stack in RTU mode for a Master
* eMBMasterInit( MB_RTU, 38400, MB_PAR_EVEN );
* // Enable the Modbus Protocol Stack.
* eMBMasterEnable( );
* for( ;; )
* {
* // Call the main polling loop of the Modbus Master protocol stack.
* eMBMasterPoll( );
* ...
* }
* \endcode
*/
/* ----------------------- Defines ------------------------------------------*/
/*! \ingroup modbus
* \brief Use the default Modbus Master TCP port (502)
*/
#define MB_MASTER_TCP_PORT_USE_DEFAULT 0
/* ----------------------- Type definitions ---------------------------------*/
/*! \ingroup modbus
* \brief Errorcodes used by all function in the Master request.
*/
typedef enum
{
MB_MRE_NO_ERR, /*!< no error. */
MB_MRE_NO_REG, /*!< illegal register address. */
MB_MRE_ILL_ARG, /*!< illegal argument. */
MB_MRE_REV_DATA, /*!< receive data error. */
MB_MRE_TIMEDOUT, /*!< timeout error occurred. */
MB_MRE_MASTER_BUSY, /*!< master is busy now. */
MB_MRE_EXE_FUN /*!< execute function error. */
} eMBMasterReqErrCode;
/*! \ingroup modbus
* \brief TimerMode is Master 3 kind of Timer modes.
*/
typedef enum
{
MB_TMODE_T35, /*!< Master receive frame T3.5 timeout. */
MB_TMODE_RESPOND_TIMEOUT, /*!< Master wait respond for slave. */
MB_TMODE_CONVERT_DELAY /*!< Master sent broadcast ,then delay sometime.*/
}eMBMasterTimerMode;
/* ----------------------- Function prototypes ------------------------------*/
/*! \ingroup modbus
* \brief Initialize the Modbus Master protocol stack.
*
* This functions initializes the ASCII or RTU module and calls the
* init functions of the porting layer to prepare the hardware. Please
* note that the receiver is still disabled and no Modbus frames are
* processed until eMBMasterEnable( ) has been called.
*
* \param eMode If ASCII or RTU mode should be used.
* \param ucPort The port to use. E.g. 1 for COM1 on windows. This value
* is platform dependent and some ports simply choose to ignore it.
* \param ulBaudRate The baudrate. E.g. 19200. Supported baudrates depend
* on the porting layer.
* \param eParity Parity used for serial transmission.
*
* \return If no error occurs the function returns eMBErrorCode::MB_ENOERR.
* The protocol is then in the disabled state and ready for activation
* by calling eMBMasterEnable( ). Otherwise one of the following error codes
* is returned:
* - eMBErrorCode::MB_EPORTERR IF the porting layer returned an error.
*/
eMBErrorCode eMBMasterInit( eMBMode eMode, UCHAR ucPort,
ULONG ulBaudRate, eMBParity eParity );
/*! \ingroup modbus
* \brief Initialize the Modbus Master protocol stack for Modbus TCP.
*
* This function initializes the Modbus TCP Module. Please note that
* frame processing is still disabled until eMBEnable( ) is called.
*
* \param usTCPPort The TCP port to listen on.
* \return If the protocol stack has been initialized correctly the function
* returns eMBErrorCode::MB_ENOERR. Otherwise one of the following error
* codes is returned:
* - eMBErrorCode::MB_EINVAL If the slave address was not valid. Valid
* slave addresses are in the range 1 - 247.
* - eMBErrorCode::MB_EPORTERR IF the porting layer returned an error.
*/
eMBErrorCode eMBMasterTCPInit( USHORT usTCPPort );
/*! \ingroup modbus
* \brief Release resources used by the protocol stack.
*
* This function disables the Modbus Master protocol stack and release all
* hardware resources. It must only be called when the protocol stack
* is disabled.
*
* \note Note all ports implement this function. A port which wants to
* get an callback must define the macro MB_PORT_HAS_CLOSE to 1.
*
* \return If the resources where released it return eMBErrorCode::MB_ENOERR.
* If the protocol stack is not in the disabled state it returns
* eMBErrorCode::MB_EILLSTATE.
*/
eMBErrorCode eMBMasterClose( void );
/*! \ingroup modbus
* \brief Enable the Modbus Master protocol stack.
*
* This function enables processing of Modbus Master frames. Enabling the protocol
* stack is only possible if it is in the disabled state.
*
* \return If the protocol stack is now in the state enabled it returns
* eMBErrorCode::MB_ENOERR. If it was not in the disabled state it
* return eMBErrorCode::MB_EILLSTATE.
*/
eMBErrorCode eMBMasterEnable( void );
/*! \ingroup modbus
* \brief Disable the Modbus Master protocol stack.
*
* This function disables processing of Modbus frames.
*
* \return If the protocol stack has been disabled it returns
* eMBErrorCode::MB_ENOERR. If it was not in the enabled state it returns
* eMBErrorCode::MB_EILLSTATE.
*/
eMBErrorCode eMBMasterDisable( void );
/*! \ingroup modbus
* \brief Check the Modbus Master protocol stack has established or not.
*
* This function must be called and check the return value before calling
* any other functions.
*
* \return If the protocol stack has been established or not
* TRUE. the protocol stack has established
* FALSE. the protocol stack hasn't established
*/
BOOL eMBMasterIsEstablished( void );
/*! \ingroup modbus
* \brief The main pooling loop of the Modbus Master protocol stack.
*
* This function must be called periodically. The timer interval required
* is given by the application dependent Modbus slave timeout. Internally the
* function calls xMBMasterPortEventGet() and waits for an event from the receiver or
* transmitter state machines.
*
* \return If the protocol stack is not in the enabled state the function
* returns eMBErrorCode::MB_EILLSTATE. Otherwise it returns
* eMBErrorCode::MB_ENOERR.
*/
eMBErrorCode eMBMasterPoll( void );
/*! \ingroup modbus
* \brief Registers a callback handler for a given function code.
*
* This function registers a new callback handler for a given function code.
* The callback handler supplied is responsible for interpreting the Modbus PDU and
* the creation of an appropriate response. In case of an error it should return
* one of the possible Modbus exceptions which results in a Modbus exception frame
* sent by the protocol stack.
*
* \param ucFunctionCode The Modbus function code for which this handler should
* be registers. Valid function codes are in the range 1 to 127.
* \param pxHandler The function handler which should be called in case
* such a frame is received. If \c NULL a previously registered function handler
* for this function code is removed.
*
* \return eMBErrorCode::MB_ENOERR if the handler has been installed. If no
* more resources are available it returns eMBErrorCode::MB_ENORES. In this
* case the values in mbconfig.h should be adjusted. If the argument was not
* valid it returns eMBErrorCode::MB_EINVAL.
*/
eMBErrorCode eMBMasterRegisterCB( UCHAR ucFunctionCode,
pxMBFunctionHandler pxHandler );
/* ----------------------- Callback -----------------------------------------*/
/*! \defgroup modbus_master registers Modbus Registers
* \code #include "mb_m.h" \endcode
* The protocol stack does not internally allocate any memory for the
* registers. This makes the protocol stack very small and also usable on
* low end targets. In addition the values don't have to be in the memory
* and could for example be stored in a flash.<br>
* Whenever the protocol stack requires a value it calls one of the callback
* function with the register address and the number of registers to read
* as an argument. The application should then read the actual register values
* (for example the ADC voltage) and should store the result in the supplied
* buffer.<br>
* If the protocol stack wants to update a register value because a write
* register function was received a buffer with the new register values is
* passed to the callback function. The function should then use these values
* to update the application register values.
*/
/*! \ingroup modbus_registers
* \brief Callback function used if the value of a <em>Input Register</em>
* is required by the protocol stack. The starting register address is given
* by \c usAddress and the last register is given by <tt>usAddress +
* usNRegs - 1</tt>.
*
* \param pucRegBuffer A buffer where the callback function should write
* the current value of the modbus registers to.
* \param usAddress The starting address of the register. Input registers
* are in the range 1 - 65535.
* \param usNRegs Number of registers the callback function must supply.
*
* \return The function must return one of the following error codes:
* - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
* Modbus response is sent.
* - eMBErrorCode::MB_ENOREG If the application does not map an coils
* within the requested address range. In this case a
* <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
*/
eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress,
USHORT usNRegs );
/*! \ingroup modbus_registers
* \brief Callback function used if a <em>Holding Register</em> value is
* read or written by the protocol stack. The starting register address
* is given by \c usAddress and the last register is given by
* <tt>usAddress + usNRegs - 1</tt>.
*
* \param pucRegBuffer If the application registers values should be updated the
* buffer points to the new registers values. If the protocol stack needs
* to now the current values the callback function should write them into
* this buffer.
* \param usAddress The starting address of the register.
* \param usNRegs Number of registers to read or write.
* \param eMode If eMBRegisterMode::MB_REG_WRITE the application register
* values should be updated from the values in the buffer. For example
* this would be the case when the Modbus master has issued an
* <b>WRITE SINGLE REGISTER</b> command.
* If the value eMBRegisterMode::MB_REG_READ the application should copy
* the current values into the buffer \c pucRegBuffer.
*
* \return The function must return one of the following error codes:
* - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
* Modbus response is sent.
* - eMBErrorCode::MB_ENOREG If the application does not map an coils
* within the requested address range. In this case a
* <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
*/
eMBErrorCode eMBMasterRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress,
USHORT usNRegs, eMBRegisterMode eMode );
/*! \ingroup modbus_registers
* \brief Callback function used if a <em>Coil Register</em> value is
* read or written by the protocol stack. If you are going to use
* this function you might use the functions xMBUtilSetBits( ) and
* xMBUtilGetBits( ) for working with bitfields.
*
* \param pucRegBuffer The bits are packed in bytes where the first coil
* starting at address \c usAddress is stored in the LSB of the
* first byte in the buffer <code>pucRegBuffer</code>.
* If the buffer should be written by the callback function unused
* coil values (I.e. if not a multiple of eight coils is used) should be set
* to zero.
* \param usAddress The first coil number.
* \param usNCoils Number of coil values requested.
* \param eMode If eMBRegisterMode::MB_REG_WRITE the application values should
* be updated from the values supplied in the buffer \c pucRegBuffer.
* If eMBRegisterMode::MB_REG_READ the application should store the current
* values in the buffer \c pucRegBuffer.
*
* \return The function must return one of the following error codes:
* - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
* Modbus response is sent.
* - eMBErrorCode::MB_ENOREG If the application does not map an coils
* within the requested address range. In this case a
* <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
*/
eMBErrorCode eMBMasterRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress,
USHORT usNCoils, eMBRegisterMode eMode );
/*! \ingroup modbus_registers
* \brief Callback function used if a <em>Input Discrete Register</em> value is
* read by the protocol stack.
*
* If you are going to use his function you might use the functions
* xMBUtilSetBits( ) and xMBUtilGetBits( ) for working with bitfields.
*
* \param pucRegBuffer The buffer should be updated with the current
* coil values. The first discrete input starting at \c usAddress must be
* stored at the LSB of the first byte in the buffer. If the requested number
* is not a multiple of eight the remaining bits should be set to zero.
* \param usAddress The starting address of the first discrete input.
* \param usNDiscrete Number of discrete input values.
* \return The function must return one of the following error codes:
* - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
* Modbus response is sent.
* - eMBErrorCode::MB_ENOREG If the application does not map an coils
* within the requested address range. In this case a
* <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
*/
eMBErrorCode eMBMasterRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress,
USHORT usNDiscrete );
/*! \ingroup modbus
*\brief These Modbus functions are called for user when Modbus run in Master Mode.
*/
eMBMasterReqErrCode
eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr,
USHORT usNRegs, USHORT * pusDataBuffer, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr,
USHORT usReadRegAddr, USHORT usNReadRegs, USHORT * pusDataBuffer,
USHORT usWriteRegAddr, USHORT usNWriteRegs, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr,
USHORT usCoilAddr, USHORT usNCoils, UCHAR * pucDataBuffer, LONG lTimeOut );
eMBMasterReqErrCode
eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT usNDiscreteIn, LONG lTimeOut );
eMBException
eMBMasterFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen );
eMBException
eMBMasterFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen );
eMBException
eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen );
eMBException
eMBMasterFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen );
eMBException
eMBMasterFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen );
eMBException
eMBMasterFuncReadCoils( UCHAR * pucFrame, USHORT * usLen );
eMBException
eMBMasterFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen );
eMBException
eMBMasterFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen );
eMBException
eMBMasterFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen );
eMBException
eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen );
/*\ingroup modbus
*\brief These functions are interface for Modbus Master
*/
void vMBMasterGetPDUSndBuf( UCHAR ** pucFrame );
UCHAR ucMBMasterGetDestAddress( void );
void vMBMasterSetDestAddress( UCHAR Address );
BOOL xMBMasterGetCBRunInMasterMode( void );
void vMBMasterSetCBRunInMasterMode( BOOL IsMasterMode );
USHORT usMBMasterGetPDUSndLength( void );
void vMBMasterSetPDUSndLength( USHORT SendPDULength );
void vMBMasterSetCurTimerMode( eMBMasterTimerMode eMBTimerMode );
BOOL xMBMasterRequestIsBroadcast( void );
eMBMasterErrorEventType eMBMasterGetErrorType( void );
void vMBMasterSetErrorType( eMBMasterErrorEventType errorType );
eMBMasterReqErrCode eMBMasterWaitRequestFinish( void );
/* ----------------------- Callback -----------------------------------------*/
#ifdef __cplusplus
PR_END_EXTERN_C
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More