feat(ota): Boot支持外部Flash暂存搬运(BL_STASH_TO_B状态)

- bsp.c/h: 外部SPI Flash只读驱动(SPI1, 与App同总线Mode3)
- main.c/h: BL_STASH_TO_B状态: AppSize门禁 -> 外部Flash逐8KB搬运B区 -> CRC校验 -> 进BL_COPY_TO_A复用现有搬运链
- 搬运幂等: 搬运中断电重启后B区仍有效自动重搬
This commit is contained in:
2026-09-24 17:14:09 +08:00
parent 48ed25015d
commit 48b789c0c4
4 changed files with 177 additions and 1 deletions
+88
View File
@@ -393,6 +393,7 @@ void BSP_Init(void)
SystemClockConfig();
GPIO_Config();
RS485Ch1_Config(500000);
ExtFlashInit(); /*外部SPI Flash: Cat1远程升级暂存区读取用*/
FeedDog();
SysTick_Init(1000);
@@ -422,6 +423,93 @@ static void FlashRead(uint32_t u32Addr, uint32_t *rData, int rLen)
}
}
/*外部SPI Flash驱动: 供Cat1远程升级时读取暂存区固件(App负责写入暂存区)*/
static uint16_t ExtSpiSendReceive(uint16_t sData)
{
uint16_t retry = 0;
uint16_t rData;
while(Reset == SPI_GetFlag(EXTFLASH_UNIT, SpiFlagSendBufferEmpty)) {
retry++;
if(retry > 0x4000) {
return 0;
}
}
SPI_SendData8(EXTFLASH_UNIT, sData);
retry = 0;
while(Reset == SPI_GetFlag(EXTFLASH_UNIT, SpiFlagReceiveBufferFull)) {
retry++;
if(retry > 0x4000) {
return 0;
}
}
rData = SPI_ReceiveData8(EXTFLASH_UNIT);
return rData;
}
void ExtFlashInit(void)
{
stc_spi_init_t stcSpiInit;
stc_port_init_t stcPortInit;
MEM_ZERO_STRUCT(stcPortInit);
stcPortInit.enPinOType = Pin_OType_Cmos;
PORT_Init(EXTFLASH_SCK_PORT, EXTFLASH_SCK_PIN, &stcPortInit);
PORT_Init(EXTFLASH_MOSI_PORT, EXTFLASH_MOSI_PIN, &stcPortInit);
PORT_Init(EXTFLASH_MISO_PORT, EXTFLASH_MISO_PIN, &stcPortInit);
stcPortInit.enPinMode = Pin_Mode_Out;
stcPortInit.enPinOType = Pin_OType_Cmos;
stcPortInit.enPinDrv = Pin_Drv_H;
stcPortInit.enPullUp = Disable;
PORT_Init(EXTFLASH_NSS_PORT, EXTFLASH_NSS_PIN, &stcPortInit);
EXTFLASH_NSS_SET();
MEM_ZERO_STRUCT(stcSpiInit);
PWC_Fcg1PeriphClockCmd(EXTFLASH_UNIT_CLOCK, Enable);
PORT_SetFunc(EXTFLASH_SCK_PORT, EXTFLASH_SCK_PIN, EXTFLASH_SCK_FUNC, Disable);
PORT_SetFunc(EXTFLASH_MOSI_PORT, EXTFLASH_MOSI_PIN, EXTFLASH_MOSI_FUNC, Disable);
PORT_SetFunc(EXTFLASH_MISO_PORT, EXTFLASH_MISO_PIN, EXTFLASH_MISO_FUNC, Disable);
stcSpiInit.enClkDiv = SpiClkDiv16;
stcSpiInit.enFrameNumber = SpiFrameNumber1;
stcSpiInit.enDataLength = SpiDataLengthBit8;
stcSpiInit.enFirstBitPosition = SpiFirstBitPositionMSB;
stcSpiInit.enSckPolarity = SpiSckIdleLevelHigh;
stcSpiInit.enSckPhase = SpiSckOddChangeEvenSample;
stcSpiInit.enReadBufferObject = SpiReadReceiverBuffer;
stcSpiInit.enWorkMode = SpiWorkMode4Line;
stcSpiInit.enTransMode = SpiTransFullDuplex;
stcSpiInit.enCommAutoSuspendEn = Disable;
stcSpiInit.enModeFaultErrorDetectEn = Disable;
stcSpiInit.enParitySelfDetectEn = Disable;
stcSpiInit.enParityEn = Disable;
stcSpiInit.enParity = SpiParityEven;
stcSpiInit.enMasterSlaveMode = SpiModeMaster;
stcSpiInit.stcDelayConfig.enSsSetupDelayOption = SpiSsSetupDelayCustomValue;
stcSpiInit.stcDelayConfig.enSsSetupDelayTime = SpiSsSetupDelaySck1;
stcSpiInit.stcDelayConfig.enSsHoldDelayOption = SpiSsHoldDelayCustomValue;
stcSpiInit.stcDelayConfig.enSsHoldDelayTime = SpiSsHoldDelaySck1;
stcSpiInit.stcDelayConfig.enSsIntervalTimeOption = SpiSsIntervalCustomValue;
stcSpiInit.stcDelayConfig.enSsIntervalTime = SpiSsIntervalSck6PlusPck2;
stcSpiInit.stcSsConfig.enSsValidBit = SpiSsValidChannel0;
stcSpiInit.stcSsConfig.enSs0Polarity = SpiSsLowValid;
SPI_Init(EXTFLASH_UNIT, &stcSpiInit);
SPI_Cmd(EXTFLASH_UNIT, Enable);
}
void ExtFlashRead(uint32_t Addr, uint8_t *rData, uint16_t rLen)
{
EXTFLASH_NSS_CLR();
ExtSpiSendReceive(0x03);
ExtSpiSendReceive((Addr >> 16) & 0xFF);
ExtSpiSendReceive((Addr >> 8) & 0xFF);
ExtSpiSendReceive(Addr & 0xFF);
for(uint16_t i = 0; i < rLen; i++) {
rData[i] = ExtSpiSendReceive(0xFF);
}
EXTFLASH_NSS_SET();
}
void ReadBootPara(BootPara rData)
{
FlashRead(BOOT_PARA_ADDRESS, (uint32_t *)rData, sizeof(BootPara_t));