ShipCentralControl/Loader_DTU/User/program.c

314 lines
8.9 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 因为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的程序在前面大小为8K0x08000000~0x08001FFF)
App的程序在后面从0x08002000开始大小为0x3E000
2. Bootloader的内存在前面大小为2K0x20000000~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(".");
}