HC32F120开发之IAP

发布于:2023-01-18 ⋅ 阅读:(865) ⋅ 点赞:(0)

        之前做过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,下载过程会出错,目前还未找到问题。

源代码下载。


网站公告

今日签到

点亮在社区的每一天
去签到