之前做过STM32F107的 UART IAP功能,是使用ST官方提供的bootloader程序,官方的例程是基于YMODE协议进行固件传输的。但是HDSC官方没有提供UART IAP的例程,现将ST官方bootloader例程中关键代码移植到HC32F120的工程中。
1.新建一个HC32F120H6的基础工程
过程略。
2.划分Flash区域
HC32F120H6的FLASH总容量为32KB,一个扇区512字节,总共64个扇区。
------------------------------------------
- BootLoader -
- 12kB -
- -
-------------0x00003000-------------
- Boot Param -
- 512B -
-------------0x00003200-------------
- User Code -
- 18.5kB -
- -
- -
-------------0x00007C00-------------
- User Param -
- 1kB -
-------------------------------------------
3.移植文件
将ST bootloader例程下的ymodem.c、ymodem.h、flash_if.c、flash_if.h、common.c、common.h、menu.c、menu.h移植到HC32F120H6工程下。
flash_if.c文件主要是一些对flash进行读、写、擦除的接口函数,需要根据HC32F120的flash驱动函数进行修改。修改之后的flash_if.c代码如下:
/* Includes ------------------------------------------------------------------*/
#include "flash_if.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
* @brief Unlocks Flash for write access
* @param None
* @retval None
*/
void FLASH_If_Init(void)
{
/* Unlock the Program memory */
EFM_Unlock();
/* Clear all FLASH flags */
EFM_ClearFlag(EFM_FLAG_CLR_OPTEND | EFM_FLAG_CLR_PEPRTERR | EFM_FLAG_CLR_PEWERR);
/* Unlock the Program memory */
EFM_Lock();
}
/**
* @brief This function does an erase of all user flash area
* @param start: start of user flash area
* @retval FLASHIF_OK : user flash area successfully erased
* FLASHIF_ERASEKO : error occurred
*/
uint32_t FLASH_If_Erase(uint32_t start)
{
uint32_t NbrOfPages = 0;
uint32_t PageError = 0;
en_result_t result = Ok;
/* Unlock the Flash to enable the flash control register access *************/
EFM_Unlock();
/* Get the sector where start the user flash area */
uint32_t StartAddr = start/FLASH_PAGE_STEP * FLASH_PAGE_STEP;
NbrOfPages = (USER_FLASH_END_ADDRESS - StartAddr)/FLASH_PAGE_STEP;
for( uint16_t i = 0; i < NbrOfPages; i++ )
{
if( EFM_SectorErase( StartAddr + i*FLASH_PAGE_STEP ) != Ok )
{
result = Error;
break;
}
}
/* Lock the Flash to disable the flash control register access (recommended
to protect the FLASH memory against possible unwanted operation) *********/
EFM_Lock();
if (result != Ok)
{
/* Error occurred while page erase */
return FLASHIF_ERASEKO;
}
return FLASHIF_OK;
}
/* Public functions ---------------------------------------------------------*/
/**
* @brief This function writes a data buffer in flash (data are 32-bit aligned).
* @note After writing data buffer, the flash content is checked.
* @param destination: start address for target location
* @param p_source: pointer on buffer with data to write
* @param length: length of data buffer (unit is 32-bit word)
* @retval uint32_t 0: Data successfully written to Flash memory
* 1: Error occurred while writing data in Flash memory
* 2: Written Data in flash memory is different from expected one
*/
uint32_t FLASH_If_Write(uint32_t destination, uint32_t *p_source, uint32_t length)
{
uint32_t i = 0;
/* Unlock the Flash to enable the flash control register access *************/
EFM_Unlock();
for (i = 0; (i < length) && (destination <= (USER_FLASH_END_ADDRESS-4)); i++)
{
/* Device voltage range supposed to be [2.7V to 3.6V], the operation will
be done by word */
if( EFM_ProgramWord( destination, *(uint32_t*)(p_source+i) ) == Ok )
{
/* Check the written value */
if (*(uint32_t*)destination != *(uint32_t*)(p_source+i))
{
/* Flash content doesn't match SRAM content */
return(FLASHIF_WRITINGCTRL_ERROR);
}
/* Increment FLASH destination address */
destination += 4;
}
else
{
/* Error occurred while writing data in Flash memory */
return (FLASHIF_WRITING_ERROR);
}
}
/* Lock the Flash to disable the flash control register access (recommended
to protect the FLASH memory against possible unwanted operation) *********/
EFM_Lock();
return (FLASHIF_OK);
}
修改之后的flash_if.h代码如下:
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __FLASH_IF_H
#define __FLASH_IF_H
/* Includes ------------------------------------------------------------------*/
#include "hc32_ddl.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Error code */
enum
{
FLASHIF_OK = 0,
FLASHIF_ERASEKO,
FLASHIF_WRITINGCTRL_ERROR,
FLASHIF_WRITING_ERROR,
FLASHIF_PROTECTION_ERRROR
};
/* protection type */
enum{
FLASHIF_PROTECTION_NONE = 0,
FLASHIF_PROTECTION_PCROPENABLED = 0x1,
FLASHIF_PROTECTION_WRPENABLED = 0x2,
FLASHIF_PROTECTION_RDPENABLED = 0x4,
};
/* protection update */
enum {
FLASHIF_WRP_ENABLE,
FLASHIF_WRP_DISABLE
};
/* Define the address from where user application will be loaded.
Note: this area is reserved for the IAP code */
#define FLASH_PAGE_STEP 0x200 /* Size of page : 2 Kbytes */
#define APPLICATION_ADDRESS (uint32_t)0x00003200 /* Start user code address: ADDR_FLASH_PAGE_8 */
/* Notable Flash addresses */
#define USER_FLASH_END_ADDRESS 0x00007C00
/* Define the user application size */
#define USER_FLASH_SIZE ((uint32_t)0x00004A00) /* Small default template application */
/* Define bitmap representing user flash area that could be write protected (check restricted to pages 8-39). */
#define FLASH_PAGE_TO_BE_PROTECTED (OB_WRP_PAGES8TO9 | OB_WRP_PAGES10TO11 | OB_WRP_PAGES12TO13 | OB_WRP_PAGES14TO15 | \
OB_WRP_PAGES16TO17 | OB_WRP_PAGES18TO19 | OB_WRP_PAGES20TO21 | OB_WRP_PAGES22TO23 | \
OB_WRP_PAGES24TO25 | OB_WRP_PAGES26TO27 | OB_WRP_PAGES28TO29 | OB_WRP_PAGES30TO31 | \
OB_WRP_PAGES32TO33 | OB_WRP_PAGES34TO35 | OB_WRP_PAGES36TO37 | OB_WRP_PAGES38TO39 )
/* Exported macro ------------------------------------------------------------*/
/* ABSoulute value */
#define ABS_RETURN(x,y) ((x) < (y)) ? ((y)-(x)) : ((x)-(y))
/* Get the number of sectors from where the user program will be loaded */
#define FLASH_SECTOR_NUMBER ((uint32_t)(ABS_RETURN(APPLICATION_ADDRESS,FLASH_START_BANK1))>>12)
/* Compute the mask to test if the Flash memory, where the user program will be
loaded, is write protected */
#define FLASH_PROTECTED_SECTORS (~(uint32_t)((1 << FLASH_SECTOR_NUMBER) - 1))
/* Exported functions ------------------------------------------------------- */
void FLASH_If_Init(void);
uint32_t FLASH_If_Erase(uint32_t StartSector);
uint32_t FLASH_If_GetWriteProtectionStatus(void);
uint32_t FLASH_If_Write(uint32_t destination, uint32_t *p_source, uint32_t length);
uint32_t FLASH_If_WriteProtectionConfig(uint32_t modifier);
#endif /* __FLASH_IF_H */
common.c为字符类的转换函数,不用修改。common.h只需将包含的头文件修改下即可。
新增ymodem_uart.c、ymodem_uart.h文件,主要是UART相关的功能函数,发送、接收、初始化。STM32F10x例程里UART功能函数时调用HAL库编写的,用到了中断接收以及接收数据缓存。HC32F120没有HAL库,所以这部分的改动比较大。UART的发送我使用阻塞模式发送,接收使用中断模式+RIngBuffer的方式,就是接收一直开启,接收的到的数据放在buffer里,应用程序从buffer里读出数据,buffer的大小为1500B,ymodem 1k size一包数据为1030字节。ymodem函数中用到的uart接收函数的参数有一个是接收超时时间,我在uart的接收功能函数中用了SysTick的时钟节拍来判断接收超时,当没有读取到足够的长度,并且buffer一直为空且超过一定的节拍数就认定为超时,函数立即返回。ymodem_uart.c代码如下:
/**
******************************************************************************
* File Name : uartDebug.c
* Description : Code for net applications
******************************************************************************
*/
/* includes ------------------------------------------------------------------*/
#include "stdbool.h"
#include "stdint.h"
#include "string.h"
#include "hc32_ddl.h"
#include "ymodem_uart.h"
/* typedef -------------------------------------------------------------------*/
/* define --------------------------------------------------------------------*/
/* UART RX/TX Port/Pin definition */
#define UART_RX_PORT (GPIO_PORT_1)
#define UART_RX_PIN (GPIO_PIN_4) /* P11: USART3_RX */
#define UART_TX_PORT (GPIO_PORT_1)
#define UART_TX_PIN (GPIO_PIN_3) /* P12: USART3_TX */
/* UART unit definition */
#define UART_UNIT (M0P_USART3)
/* UART unit interrupt definition */
#define UART_UNIT_ERR_INT (INT_USART_3_EI)
#define UART_UNIT_ERR_IRQn (Int013_IRQn)
#define UART_UNIT_RX_INT (INT_USART_3_RI)
#define UART_UNIT_RX_IRQn (Int015_IRQn)
/* Function clock gate definition */
#define FUNCTION_CLK_GATE (CLK_FCG_UART3)
#define IS_RING_BUFFER_EMPTY(x) (0U == ((x)->u16UsedSize))
/* macro ---------------------------------------------------------------------*/
/* variables -----------------------------------------------------------------*/
static stc_ring_buffer_t m_stcRingBuf = {
.u16InIdx = 0,
.u16OutIdx = 0,
.u16UsedSize = 0,
.u16Capacity = RING_BUFFER_SIZE,
};
static uint8_t m_u8Status = 0U;
/* function prototypes -------------------------------------------------------*/
static void UartErrIrqCallback(void);
static void UartRxIrqCallback(void);
static en_result_t RingBufWrite(stc_ring_buffer_t *pstcBuffer, uint8_t u8Data);
static en_result_t RingBufRead(stc_ring_buffer_t *pstcBuffer, uint8_t *pu8Data);
/**
* @brief : None.
* @param : None.
* @retval : None.
*/
bool ymodemUartInit( void )
{
stc_irq_regi_config_t stcIrqRegiConf;
const stc_uart_init_t stcUartInit = {
.u32Baudrate = 57600UL,
.u32ClkPrescaler = USART_CLK_PRESCALER_DIV1,
.u32BitDirection = USART_LSB,
.u32StopBit = USART_STOP_BITS_1,
.u32Parity = USART_PARITY_NONE,
.u32DataWidth = USART_DATA_WIDTH_BITS_8,
.u32ClkMode = USART_INTCLK_NONE_OUTPUT,
.u32OversamplingBits = USART_OVERSAMPLING_BITS_8,
.u32NoiseFilterState = USART_NOISE_FILTER_DISABLE,
.u32SbDetectPolarity = USART_SB_DETECT_FALLING,
};
CLK_FcgPeriphClockCmd(FUNCTION_CLK_GATE, Enable);
/* Configure USART RX/TX pin. */
GPIO_SetFunc(UART_RX_PORT, UART_RX_PIN, GPIO_FUNC_3_USART1);
GPIO_SetFunc(UART_TX_PORT, UART_TX_PIN, GPIO_FUNC_3_USART1);
/* Enable peripheral clock */
CLK_FcgPeriphClockCmd(FUNCTION_CLK_GATE, Enable);
/* Initialize UART function. */
if (Ok != USART_UartInit(UART_UNIT, &stcUartInit))
{
return false;
}
/* Register error IRQ handler && configure NVIC. */
stcIrqRegiConf.enIRQn = UART_UNIT_ERR_IRQn;
stcIrqRegiConf.enIntSrc = UART_UNIT_ERR_INT;
stcIrqRegiConf.pfnCallback = &UartErrIrqCallback;
INTC_IrqRegistration(&stcIrqRegiConf);
NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn);
NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIORITY_03);
NVIC_EnableIRQ(stcIrqRegiConf.enIRQn);
/* Register RX IRQ handler && configure NVIC. */
stcIrqRegiConf.enIRQn = UART_UNIT_RX_IRQn;
stcIrqRegiConf.enIntSrc = UART_UNIT_RX_INT;
stcIrqRegiConf.pfnCallback = &UartRxIrqCallback;
INTC_IrqRegistration(&stcIrqRegiConf);
NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn);
NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIORITY_03);
NVIC_EnableIRQ(stcIrqRegiConf.enIRQn);
m_stcRingBuf.u16InIdx = 0,
m_stcRingBuf.u16OutIdx = 0,
m_stcRingBuf.u16UsedSize = 0,
m_stcRingBuf.u16Capacity = RING_BUFFER_SIZE;
/* Enable RX function */
USART_FuncCmd(UART_UNIT, ( USART_TX | USART_RX | USART_INT_RX ), Enable);
return true;
}
/**
* @brief USART error IRQ callback.
* @param None
* @retval None
*/
static void UartErrIrqCallback( void )
{
USART_ClearFlag(UART_UNIT, (USART_CLEAR_FLAG_PE | USART_CLEAR_FLAG_FE | USART_CLEAR_FLAG_ORE));
}
/**
* @brief USART RX IRQ callback
* @param None
* @retval None
*/
static void UartRxIrqCallback(void)
{
uint16_t u16Data = USART_RecData(UART_UNIT);
RingBufWrite(&m_stcRingBuf, (uint8_t)u16Data);
}
/**
* @brief Write ring buffer.
* @param [in] pstcBuffer Pointer to a @ref stc_ring_buffer_t structure
* @param [in] u8Data Data to write
* @retval An en_result_t enumeration value:
* - Ok: Write success.
* - ErrorBufferFull: Buffer is full.
*/
static en_result_t RingBufWrite(stc_ring_buffer_t *pstcBuffer, uint8_t u8Data)
{
en_result_t enRet = Ok;
if (pstcBuffer->u16UsedSize >= pstcBuffer->u16Capacity)
{
enRet = ErrorBufferFull;
}
else
{
pstcBuffer->au8Buf[pstcBuffer->u16InIdx++] = u8Data;
pstcBuffer->u16InIdx %= pstcBuffer->u16Capacity;
pstcBuffer->u16UsedSize++;
}
return enRet;
}
/**
* @brief Write ring buffer.
* @param [in] pstcBuffer Pointer to a @ref stc_ring_buffer_t structure
* @param [in] pu8Data Pointer to data buffer to read
* @retval An en_result_t enumeration value:
* - Ok: Write success.
* - ErrorNotReady: Buffer is empty.
*/
static en_result_t RingBufRead(stc_ring_buffer_t *pstcBuffer, uint8_t *pu8Data)
{
en_result_t enRet = Ok;
if (!pstcBuffer->u16UsedSize)
{
enRet = ErrorNotReady;
}
else
{
*pu8Data = pstcBuffer->au8Buf[pstcBuffer->u16OutIdx++];
pstcBuffer->u16OutIdx %= pstcBuffer->u16Capacity;
pstcBuffer->u16UsedSize--;
}
return enRet;
}
/**
* @brief Receives an amount of data in blocking mode.
* @param pData: Pointer to data buffer
* @param Size: Amount of data to be received
* @param Timeout: Timeout duration
* @retval : None.
*/
en_result_t ymodemUartReceive( uint8_t *pData, uint16_t Size, uint32_t Timeout )
{
uint32_t tickstart = 0;
uint8_t u8Data = 0U;
/* Get tick */
tickstart = SysTick_GetTick();
while( ( Size > 0 ) && ((SysTick_GetTick() - tickstart ) < Timeout) )
{
if( RingBufRead(&m_stcRingBuf, &u8Data) == Ok )
{
*pData = u8Data;
pData++;
Size --;
tickstart = SysTick_GetTick();
}
}
if( Size > 0 )
{
return ErrorTimeout;
}
return Ok;
}
/**
* @brief Receives an amount of data in blocking mode.
* @param pData: Pointer to data buffer
* @param Size: Amount of data to be received
* @param Timeout: Timeout duration
* @retval : None.
*/
en_result_t ymodemUartTransmit( uint8_t *pData, uint16_t Size, uint32_t Timeout )
{
uint32_t tickstart = 0;
/* Get tick */
tickstart = SysTick_GetTick();
while( ( Size > 0 ) && ((SysTick_GetTick() - tickstart ) < Timeout))
{
if( USART_GetFlag( UART_UNIT, USART_FLAG_TXE ) == Set )
{
USART_SendData(UART_UNIT, (uint16_t)(*pData));
pData++;
Size --;
tickstart = SysTick_GetTick();
}
}
if( Size > 0 )
{
return ErrorTimeout;
}
return Ok;
}
ymodem_uart.h代码如下:
#ifndef __YMODEM_UART_H
#define __YMODEM_UART_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stdint.h"
#include "stdbool.h"
#include "hc32_ddl.h"
/* Private includes ----------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
/* Ring buffer size */
#define RING_BUFFER_SIZE (1500U)
#define IS_RING_BUFFER_EMPTY(x) (0U == ((x)->u16UsedSize))
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported variable prototypes ----------------------------------------------*/
typedef struct
{
uint16_t u16Capacity;
__IO uint16_t u16UsedSize;
uint16_t u16InIdx;
uint16_t u16OutIdx;
uint8_t au8Buf[RING_BUFFER_SIZE];
} stc_ring_buffer_t;
/* Exported functions prototypes ---------------------------------------------*/
bool ymodemUartInit( void );
en_result_t ymodemUartReceive( uint8_t *pData, uint16_t Size, uint32_t Timeout );
en_result_t ymodemUartTransmit( uint8_t *pData, uint16_t Size, uint32_t Timeout );
#ifdef __cplusplus
}
#endif
#endif /* __YMODEM_UART_H */
menu.c为控制下载过程的代码,只需做少量的修改,替换UART发送和接收函数即可。
ymodem.c为ymodem协议相关的一些发送、接收、解析、封包函数,改动比较小,替换UART发送和接收函数、修改超时相关参数的值,因为时间单位变了。
4.编写main.c
初始化SysTick,节拍周期1ms,如果上电时KEY被按下,则进入下载模式,否则跳转到应用程序。
/*******************************************************************************
* Include files
******************************************************************************/
#include "string.h"
#include "hc32_ddl.h"
#include "led.h"
#include "gpioinput.h"
#include "board.h"
#include "menu.h"
#include "ymodem_uart.h"
#include "flash_if.h"
/**
* @addtogroup HC32F120_DDL_Examples
* @{
*/
/**
* @addtogroup Templates
* @{
*/
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
static pFunction JumpToApplication;
static uint32_t JumpAddress;
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
static void SystemClockConfig(void);
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @brief Main function of template project
* @param None
* @retval int32_t return value, if needed
*/
int32_t main(void)
{
uint32_t RunCnt = 0;
/* Add your code here */
DDL_PrintfInit( );
SysTick_Init( 1000 );
BoardInit( );
gpioInputInit( );
LedInit( );
uint8_t keyCheckCnt;
for( keyCheckCnt = 0;keyCheckCnt < 10; keyCheckCnt++ )
{
DDL_Delay1ms( 10 );
if( gpioInputLowDetect( KEY_INPUT ) == true )
{
keyCheckCnt++;
}
else
{
break;
}
}
if( keyCheckCnt > 7 )
{
LedxOn( LED1 );
LedxOn( LED3 );
printf("Firmware update!\n");
/* Initialise Flash */
FLASH_If_Init();
if( ymodemUartInit( ) == false )
{
printf("uartUpgradeInit fail!\n");
}
/* Display main menu */
Main_Menu();
}
else
{
printf("Jump App!\r\n");
/* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */
if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
{
/* Jump to user application */
JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
JumpToApplication = (pFunction) JumpAddress;
SysTick_Suspend();
/* Initialize user application's Stack Pointer */
__set_MSP( *(__IO uint32_t*) APPLICATION_ADDRESS );
__set_PSP( *(__IO uint32_t*) APPLICATION_ADDRESS );
__set_CONTROL(0);
__disable_irq();
JumpToApplication();
}
}
if( ymodemUartInit( ) == false )
{
printf("uartUpgradeInit fail!\n");
}
while (1)
{
if( RunCnt ++ > 10000 )
{
RunCnt = 0;
LedxToggle( LED1 );
}
}
}
/**
* @}
*/
/**
* @}
*/
/**
* @brief Configure system clock.
* @param None
* @retval None
*/
static void SystemClockConfig(void)
{
stc_clk_xtal_init_t stcXTALInit;
/* Configure XTAL */
stcXTALInit.u8XtalState = CLK_XTAL_ON;
stcXTALInit.u8XtalMode = CLK_XTALMODE_OSC;
stcXTALInit.u8XtalDrv = CLK_XTALDRV_HIGH;
stcXTALInit.u8XtalSupDrv = CLK_XTAL_SUPDRV_OFF;
stcXTALInit.u8XtalStb = CLK_XTALSTB_8;
/* Initialize XTAL clock */
CLK_XTALInit(&stcXTALInit);
/* Switch system clock from HRC(default) to XTAL */
CLK_SetSysclkSrc(CLK_SYSCLKSOURCE_XTAL);
}
5.生成应用程序BIN文件
将应用程序的起始地址设为0x3200,大小设为0x4A00:
添加编译指令以生成BIN文件:
main()函数开头设置中断向量表偏移:
/**
* @brief Main function of template project
* @param None
* @retval int32_t return value, if needed
*/
int32_t main(void)
{
#ifndef VECT_TAB_OFFSET
SCB->VTOR = 0x00003200;
#else
SCB->VTOR = 0x00003200 + VECT_TAB_OFFSET;
#endif
...
}
修改hc32f120_interrupts.c中void SysTick_Handler(void)函数:
/**
* @brief SysTick IRQ handler
* @param None
* @retval None
*/
void SysTick_Handler(void)
{
SysTick_IrqHandler();
}
如果DDL_ICG_ENABLE定义为DDL_ON,那么还需要修改hc32f120_icg.c文件中的代码:
#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
const uint32_t u32ICG[] __attribute__((section(".ARM.__at_0x32C0"))) = //改
#elif defined (__GNUC__) && !defined (__CC_ARM)
const uint32_t u32ICG[] __attribute__((section(".icg_sec"))) =
#elif defined (__CC_ARM)
const uint32_t u32ICG[] __attribute__((at(0x00003200 + 0xC0))) = //改
#elif defined (__ICCARM__)
#pragma location = 0x00003200 + 0xC0
__root static const uint32_t u32ICG[] =
#else
#error "unsupported compiler!!"
#endif
{
/* ICG 0~ 3 */
ICG0_REGISTER_CONSTANT,
ICG1_REGISTER_CONSTANT,
ICG2_REGISTER_CONSTANT,
ICG3_REGISTER_CONSTANT,
/* ICG 4~ 6 */
ICG4_REGISTER_CONSTANT,
ICG5_REGISTER_CONSTANT,
ICG6_REGISTER_CONSTANT,
};
也是地址的修改,不然无法生成bin文件。
6.升级固件
上位机使用的SecureCRT 8工具:
波特率57600,之前用115200,下载过程会出错,目前还未找到问题。