315 lines
8.9 KiB
C
315 lines
8.9 KiB
C
// 因为main.c由STM32CubeMX自动生成
|
||
// 本模块实现用户自定义的main功能
|
||
|
||
#include "includes.h"
|
||
|
||
// 主程序位置
|
||
#define APROM_BASE (FLASH_BASE + 8192)
|
||
|
||
#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(!(USART2->ISR & LL_USART_ISR_TXE));
|
||
USART2->TDR = (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();
|
||
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
|
||
|
||
#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(!(USART2->ISR & LL_USART_ISR_TC));
|
||
|
||
JumpToEntry(APROM_BASE);
|
||
|
||
// 不应该到这里来
|
||
while(1)
|
||
PRINTF(".");
|
||
}
|