一、环境介绍
MCU: N32G030F6S7 TSSOP20
代码开发工具: Keil5
上位机工具:SecureCRT
协议: ymodem
本篇文章主要讲解如何在国民技术N32G030F6S7工程里添加移植ymodem协议,最终完成串口升级固件,因为主要是讲ymodem协议栈的移植。
工程源码下载地址:
二、ymodem协议
协议通讯过程如图,不需要彻底明白,只需要了解便可。
1、单片机发送'C'字符给上位机
2、上位机发送文件名,文件大小等信息给单片机,数据开头为SOH(0X01)
3、单片机接收数据校验成功后返回ACK给上位机,然后再发送'C'等待上位机发送固件(固件已1K数据包的形式进行发送)
截图链接:https://blog.csdn.net/lcmsir/article/details/80550821
三、移植过程讲解
1、跳转程序
#define MMU_VTOR ((__IO unsigned*)(0x40024C30)) //用宏定义把0x40024C30这个地址用MMU_VTOR这个名字来代替
#define _VTOREN() (*MMU_VTOR = (*MMU_VTOR) | 0x88000000); //对MMU_VTOR跟0x8800_0000做或等于操作,也就是将这个寄存器的bit31和bit27都置一,然后用宏定义取名为_VTOREN(),由名字可以判断出来这是这个寄存器的使能操作
#define _VTORVALUE() (*MMU_VTOR = (*MMU_VTOR) | APPOffset); //对MMU_VTOR跟0x4000做或等于操作,然后用宏定义取名为_VTORVALUE(),由名字可以判断出来这是往寄存器里面写偏移量
/* Private functions ---------------------------------------------------------*/
typedef void (*iapfun)(void); // 定义一个函数类型的参数.
iapfun jump2app;
void iap_load_app(u32 appxaddr)
{
// if(((*(vu32*)appxaddr)&0x0FFFFFFF) < 1024*144) // 检查栈顶地址是否合法.
{
jump2app = (iapfun)*(vu32*)(appxaddr+4);
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
jump2app(); // 跳转到APP.
}
}
void Bsp_Run_APP(void)
{
SerialPutString("RUN APP...\r\n");
_VTOREN();
_VTORVALUE();
iap_load_app(APPLICATION_ADDRESS);
}
注意:
1)M0没有中断偏移寄存器,即VTOR
2)APPOffset位偏移量
3)此段代码是向原厂索要的,直接用便可(我也不懂)
2、ymodem移植文件修改
1)、command.c
此文件只需要修改两个函数:
void SerialPutChar(uint8_t c); //发送字节
void SerialPutChar(uint8_t c)
{
USART_SendData(USART1, c);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXC) == RESET)
{
}
}
2)、flash_if.c
此文件为对flash操作的底层文件,需要将其中操作函数使用该芯片库函数代替。
3)、flash_if.h
/* Includes ------------------------------------------------------------------*/
#include "n32g030.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
#define USER_FLASH_LAST_PAGE_ADDRESS 0x08007E00 //倒数第二页的首地址
#define USER_FLASH_END_ADDRESS 0x08007FFF /* 32 KBytes */
#define FLASH_PAGE_SIZE 0x200 /* 512 bytes */
/* define the address from where user application will be loaded,
the application address should be a start sector address
定义加载用户应用程序的地址,申请地址应该是一个起始扇区地址
预留Bootloader空间为16K
*/
#define APPOffset (16*1024) //APP地址偏移量
#define APPLICATION_ADDRESS (uint32_t)(0x08000000 |APPOffset)
/* Get the number of Sector from where the user program will be loaded */
#define FLASH_PAGE_NUMBER (uint32_t)((APPLICATION_ADDRESS - 0x08000000) >> 12)
/* Compute the mask to test if the Flash memory, where the user program will be
loaded, is write protected */
#define FLASH_PROTECTED_PAGES ((uint32_t)~((1 << FLASH_PAGE_NUMBER) - 1))
/* define the user application size */
#define USER_FLASH_SIZE (USER_FLASH_END_ADDRESS - APPLICATION_ADDRESS + 1)
注意:移植时候这里的芯片参数得根据实际进行修改
(1)、USER_FLASH_LAST_PAGE_ADDRESS //flash倒数第二页的首地址
(2)、USER_FLASH_END_ADDRESS //flash最后一页的尾地址
(3)、FLASH_PAGE_SIZE //flash一页的大小
(4)、APPOffset //APP地址偏移量
四、keil配置
1)、IAP工程里的地址按照正常来写便可
2)、APP工程里面的ROM开始地址为APPLICATION_ADDRESS,ROM大小为USER_FLASH_END_ADDRESS-APPLICATION_ADDRESS。我预留给bootloader的空间为16K,所以APP的地址得从0x08004000开始,ROM空间为0x4000