// 因为main.c由STM32CubeMX自动生成 // 本模块实现用户自定义的main功能 #include "includes.h" // 主程序位置: 16K(第2个扇区) #define APROM_BASE (FLASH_BASE + 0x4000) #pragma pack(push, 1) // 升级文件头 typedef struct // size=12 { unsigned short check; // 数据有效标志, 0x55AA表示有效 unsigned upgrade_request : 1; // 升级请求标志,0-无升级,1-有升级 unsigned upgrade_result : 3; // 升级失败标志,0-成功,1-失败,其余保留 unsigned encrypt_flag : 2; // 加密标志, 0-无加密,其余保留 unsigned compress_flag : 2; // 压缩标志, 0-无压缩,1-有压缩,其余保留 unsigned rerseved1 : 8; // 保留,必须为0xFF unsigned long upgrade_length; // 升级文件长度 unsigned rerseved2 : 8; // 保留,必须为0xFF unsigned rerseved3 : 8; // 保留,必须为0xFF unsigned short crc; // 对前面内容的crc校验 } TUpgradeHeader; #pragma pack(pop) // 实现stdout的硬件输出 int stdout_putchar(int ch) { while(!(USART6->SR & LL_USART_SR_TXE)); USART6->DR = (uint8_t) ch; return ch; } /* ************************************************************************* Bootloader和App跳转设计要点 1. Bootloader的程序在前面,大小为8K(0x08000000~0x08001FFF) App的程序在后面,从0x08002000开始,大小为0x3E000 2. Bootloader的内存在前面,大小为2K(0x20000000~0x200007FF) //App的内存在后面,从0x20000800开始,大小为0xF800 3. 从Bootloader跳转到App: 1)关闭全局中断响应(__disable_irq) 2)禁止中断允许(将各中断的允许位清零) 3)清除中断标志(将各中断的标志位清零) 4) 设置堆栈(MSP)为App的堆栈值 5)跳转到App的程序入口 4. 从App跳转到Bootloader: 直接系统复位,运行Bootloader 5. Bootloader工程的特殊处理 1)在Target页,按照上述要求设置IROM1和IRAM1 2)在Linker页,勾选“Use Memory Layout from Target Dialog” 6. App工程的特殊处理 1)在Target页,按照上述要求设置IROM1和IRAM1 2)在Linker页,勾选“Use Memory Layout from Target Dialog” 3) 在system_stm32l4xx.c中修改以下代码: a. 将宏定义VECT_TAB_OFFSET改为0x2000 b. 在SystemInit()函数最后,重新打开全局中断响应(__enable_irq) 7. 从App的任务中跳转到Bootloader,按第3条的方法试验不成功。 具体原因未明,可能是因为要关掉的中断太多,没有一一试验; 也可能是因为FreeRTOS将CPU的特权模式接管了,导致PSP、MSP设置无效等。 ************************************************************************* */ // 实现从Bootloader跳转到App typedef void (*pIapFun_TypeDef)(void); //定义一个函数类型的参数. void JumpToEntry(uint32_t addr) { __disable_irq(); SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk); __set_MSP(*(volatile uint32_t *) addr); ((pIapFun_TypeDef) (*(volatile uint32_t *) (addr + 4)))(); // 不应该到这里来 while(1) PRINTF("."); } // 最小匹配块大小 #define MIN_MATCH_LEN 3 #define MAX_MATCH_LEN (7 + MIN_MATCH_LEN) // =match_len+MIN_MATCH_LEN // 从Flash读出数据 long Get_Bits(unsigned long baseAddr, long *byte_index, unsigned char *bit_index, unsigned char bit_count) { long word = 0; unsigned char total_bits = 0; unsigned short mask; unsigned char bits; static unsigned char buf; while(total_bits < bit_count) { // 读入一个字符 if(*bit_index == 0) SFlash_BufferRead(baseAddr + *byte_index, &buf, 1); bits = 8 - *bit_index; if(bits > bit_count - total_bits) bits = bit_count - total_bits; mask = (1 << bits) - 1; word |= ((buf >> (*bit_index)) & mask) << total_bits; *bit_index += bits; if(*bit_index == 8) { (*byte_index)++; *bit_index = 0; } total_bits += bits; } return word; } // 写入数据到缓冲或Flash void Put_Bytes(unsigned long *baseAddr, long *byte_index2, unsigned char *data_buf, unsigned char data_len) { unsigned char i = 0; while(i < data_len) { Flash_rdBuf[*byte_index2] = data_buf[i]; (*byte_index2)++; i++; // 够一页了就写入Flash if((*baseAddr + *byte_index2) % FLASH_ERASE_SIZE == 0) { Flash_BufferWrite(*baseAddr, Flash_rdBuf, *byte_index2); if(!Flash_BufferVerify(*baseAddr, Flash_rdBuf, *byte_index2)) PRINTF("*** Verify flash failed at %08X, %d bytes\r\n", *baseAddr, *byte_index2); *baseAddr += *byte_index2; *byte_index2 = 0; } } } void Flash_Copy(uint32_t toAddr, uint32_t fromAddr, uint32_t nbytes) { uint32_t count, offset; while(nbytes > 0) { // 计算页内偏移(只有第一页有可能非0) offset = toAddr % FLASH_ERASE_SIZE; // 计算一页内写入字节数 count = FLASH_ERASE_SIZE - offset; if(count > nbytes) count = nbytes; // 读本页内数据 SFlash_BufferRead(fromAddr, Flash_rdBuf, count); // 写入本页数据 Flash_BufferWrite(toAddr, Flash_rdBuf, count); if(!Flash_BufferVerify(toAddr, Flash_rdBuf, count)) PRINTF("*** Verify flash failed at %08X, %d bytes\r\n", toAddr, count); // 计算下一页 fromAddr += count; toAddr += count; nbytes -= count; } } // 解压升级包 void decompress_aprom(unsigned long toAddr, unsigned long fromAddr, long size) { long byte_index = 0; unsigned char bit_index = 0; long byte_index2 = 0; unsigned char buf[MAX_MATCH_LEN]; unsigned long baseAddr = toAddr; // 每一个记录为9/16bit,所以最后一个标志位在倒数第二字节 while(byte_index < size - 1) { if(Get_Bits(fromAddr, &byte_index, &bit_index, 1) == 1) { // 获取一段重复字节 long offset = Get_Bits(fromAddr, &byte_index, &bit_index, 12) + 1; unsigned char len = Get_Bits(fromAddr, &byte_index, &bit_index, 3) + MIN_MATCH_LEN; if(offset <= byte_index2) { // 全部在缓冲区内,还未写入Flash memmove(buf, Flash_rdBuf + byte_index2 - offset, len); } else if(offset - byte_index2 >= len) { // 全部在Flash里 Flash_BufferRead(baseAddr - (offset - byte_index2), buf, len); } else { // 前面部分在Flash Flash_BufferRead(baseAddr - (offset - byte_index2), buf, offset - byte_index2); // 后面部分在缓冲区 memmove(buf + (offset - byte_index2), Flash_rdBuf, len - (offset - byte_index2)); } Put_Bytes(&baseAddr, &byte_index2, buf, len); } else { // 获取一个原始字节 buf[0] = Get_Bits(fromAddr, &byte_index, &bit_index, 8); Put_Bytes(&baseAddr, &byte_index2, buf, 1); } } // 最后不满一页的数据 if(byte_index2 > 0) { Flash_BufferWrite(baseAddr, Flash_rdBuf, byte_index2); if(!Flash_BufferVerify(baseAddr, Flash_rdBuf, byte_index2)) PRINTF("*** Verify flash failed at %08X, %d bytes\r\n", baseAddr, byte_index2); } } uint8_t Flash_apBuf[FLASH_ERASE_SIZE] = {0}; //#define _COPY_SFLASH_TO_APROM_ // 主循环,被main()函数调用 void main_task(void *argument) { TUpgradeHeader upHeader = {0}; uint32_t nbytes, fromAddr, toAddr; SFlash_Open(); #ifndef _COPY_SFLASH_TO_APROM_ SFlash_BufferRead(SFLASH_UPGRADE_BASE, (uint8_t *) &upHeader, sizeof(upHeader)); if(upHeader.check == 0x55AA && upHeader.upgrade_request == 1 && do_crc_16(0, (uint8_t *) &upHeader, sizeof(upHeader)) == 0 && do_sflash_crc(SFLASH_UPGRADE_BASE + sizeof(upHeader), upHeader.upgrade_length) == 0) #endif { // 解压 PRINTF("\r\nDecompress upgrade package ...\r\n"); HAL_FLASH_Unlock(); #ifndef _COPY_SFLASH_TO_APROM_ if(!upHeader.compress_flag) Flash_Copy(APROM_BASE, SFLASH_UPGRADE_BASE + sizeof(upHeader), upHeader.upgrade_length - 2); else decompress_aprom(APROM_BASE, SFLASH_UPGRADE_BASE + sizeof(upHeader), upHeader.upgrade_length - 2); #else nbytes = 50 * 1024; fromAddr = SFLASH_UPGRADE_BASE; toAddr = APROM_BASE; while(nbytes > 0) { // 读本页内数据 SFlash_BufferRead(fromAddr, Flash_rdBuf, FLASH_ERASE_SIZE); // 写入本页数据 Flash_BufferWrite(toAddr, Flash_rdBuf, FLASH_ERASE_SIZE); if(!Flash_BufferVerify(toAddr, Flash_rdBuf, FLASH_ERASE_SIZE)) PRINTF("*** Verify flash failed at %08X, %d bytes\r\n", toAddr, FLASH_ERASE_SIZE); // 计算下一页 fromAddr += FLASH_ERASE_SIZE; toAddr += FLASH_ERASE_SIZE; nbytes -= FLASH_ERASE_SIZE; } PRINTF("Verify ...\r\n"); nbytes = 50 * 1024; fromAddr = SFLASH_UPGRADE_BASE; toAddr = APROM_BASE; while(nbytes > 0) { // 读本页内数据 SFlash_BufferRead(fromAddr, Flash_rdBuf, FLASH_ERASE_SIZE); Flash_BufferRead(toAddr, Flash_apBuf, FLASH_ERASE_SIZE); if(memcmp(Flash_apBuf, Flash_rdBuf, FLASH_ERASE_SIZE) != 0) { PRINTF("data mismatch on 0x%x\r\n", toAddr); break; } // 计算下一页 fromAddr += FLASH_ERASE_SIZE; toAddr += FLASH_ERASE_SIZE; nbytes -= FLASH_ERASE_SIZE; } PRINTF("OK.\r\n"); #endif HAL_FLASH_Lock(); #ifndef _COPY_SFLASH_TO_APROM_ SFlash_UnlockBPR(); upHeader.upgrade_request = 0; SFlash_BufferWrite(SFLASH_UPGRADE_BASE, (uint8_t *) &upHeader, sizeof(upHeader)); if(!SFlash_BufferVerify(SFLASH_UPGRADE_BASE, (uint8_t *) &upHeader, sizeof(upHeader))) PRINTF("*** Verify SFlash failed at %08X, %d bytes\r\n", SFLASH_UPGRADE_BASE, sizeof(upHeader)); #endif } PRINTF("\r\nJump to APROM ...\r\n"); while(!(USART6->SR & LL_USART_SR_TC)); JumpToEntry(APROM_BASE); // 不应该到这里来 while(1) PRINTF("."); }