48b789c0c4
- 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区仍有效自动重搬
570 lines
17 KiB
C
570 lines
17 KiB
C
#include <stdlib.h>
|
|
#include "bsp.h"
|
|
|
|
/*****************************************************************************************
|
|
* System Clock - HRC 16MHz -> MPLL 200MHz (不用外部晶振)
|
|
****************************************************************************************/
|
|
static void SystemClockConfig(void)
|
|
{
|
|
stc_clk_sysclk_cfg_t stcSysClkCfg;
|
|
stc_clk_mpll_cfg_t stcMpllCfg;
|
|
stc_sram_config_t stcSramConfig;
|
|
|
|
MEM_ZERO_STRUCT(stcSysClkCfg);
|
|
MEM_ZERO_STRUCT(stcMpllCfg);
|
|
MEM_ZERO_STRUCT(stcSramConfig);
|
|
|
|
/* Set bus clk div. */
|
|
stcSysClkCfg.enHclkDiv = ClkSysclkDiv1;
|
|
stcSysClkCfg.enExclkDiv = ClkSysclkDiv2;
|
|
stcSysClkCfg.enPclk0Div = ClkSysclkDiv1;
|
|
stcSysClkCfg.enPclk1Div = ClkSysclkDiv2;
|
|
stcSysClkCfg.enPclk2Div = ClkSysclkDiv4;
|
|
stcSysClkCfg.enPclk3Div = ClkSysclkDiv4;
|
|
stcSysClkCfg.enPclk4Div = ClkSysclkDiv2;
|
|
CLK_SysClkConfig(&stcSysClkCfg);
|
|
|
|
/* sram init include read/write wait cycle setting */
|
|
stcSramConfig.u8SramIdx = Sram12Idx | Sram3Idx | SramHsIdx | SramRetIdx;
|
|
stcSramConfig.enSramRC = SramCycle2;
|
|
stcSramConfig.enSramWC = SramCycle2;
|
|
SRAM_Init(&stcSramConfig);
|
|
|
|
/* flash read wait cycle setting */
|
|
EFM_Unlock();
|
|
EFM_SetLatency(EFM_LATENCY_5);
|
|
EFM_Lock();
|
|
|
|
/* Config HRC and enable HRC */
|
|
CLK_HrcCmd(Enable);
|
|
|
|
/* MPLL config (HRC / pllmDiv * plln / PllpDiv = 16/2*50/2 = 200M). */
|
|
stcMpllCfg.pllmDiv = 2ul;
|
|
stcMpllCfg.plln = 50ul;
|
|
stcMpllCfg.PllpDiv = 2ul;
|
|
stcMpllCfg.PllqDiv = 2ul;
|
|
stcMpllCfg.PllrDiv = 2ul;
|
|
CLK_SetPllSource(ClkPllSrcHRC);
|
|
CLK_MpllConfig(&stcMpllCfg);
|
|
|
|
/* Enable MPLL. */
|
|
CLK_MpllCmd(Enable);
|
|
/* Wait MPLL ready. */
|
|
while(Set != CLK_GetFlagStatus(ClkFlagMPLLRdy))
|
|
{
|
|
;
|
|
}
|
|
/* Switch driver ability */
|
|
PWC_HS2HP();
|
|
/* Switch system clock source to MPLL. */
|
|
CLK_SetSysClkSource(CLKSysSrcMPLL);
|
|
SystemCoreClockUpdate();
|
|
}
|
|
|
|
/*****************************************************************************************
|
|
* Debug Uart (USART1)
|
|
****************************************************************************************/
|
|
static uint8_t DbgUartRec(void)
|
|
{
|
|
uint16_t u16Data = USART_RecData(DBG_USART_CH);
|
|
return (uint8_t)u16Data;
|
|
}
|
|
|
|
static void DBGUsartErrIrqCallback(void)
|
|
{
|
|
if(DBG_USART_CH->SR_f.ORE) {
|
|
DBG_USART_CH->CR1_f.CORE = 1;
|
|
USART_RecData(DBG_USART_CH);
|
|
}
|
|
if(DBG_USART_CH->SR_f.PE)
|
|
DBG_USART_CH->CR1_f.CPE = 1;
|
|
if(DBG_USART_CH->SR_f.FE)
|
|
DBG_USART_CH->CR1_f.CFE = 1;
|
|
}
|
|
|
|
static void DBGUsartRxIrqCallback(void)
|
|
{
|
|
uint8_t rData = DbgUartRec();
|
|
DbgRxIrqCallback(rData);
|
|
}
|
|
|
|
void DbgUart_Config(uint32_t BaudRate)
|
|
{
|
|
stc_usart_uart_init_t stcInitCfg;
|
|
stc_irq_regi_conf_t stcIrqRegiCfg;
|
|
en_result_t enRet;
|
|
stc_port_init_t stcPortInit;
|
|
|
|
MEM_ZERO_STRUCT(stcPortInit);
|
|
stcPortInit.enPinOType = Pin_OType_Cmos;
|
|
PORT_Init(DBG_USART_RX_PORT, DBG_USART_RX_PIN, &stcPortInit);
|
|
PORT_Init(DBG_USART_TX_PORT, DBG_USART_TX_PIN, &stcPortInit);
|
|
|
|
stcInitCfg.enClkMode = UsartIntClkCkNoOutput;
|
|
stcInitCfg.enClkDiv = UsartClkDiv_1;
|
|
stcInitCfg.enDataLength = UsartDataBits8;
|
|
stcInitCfg.enDirection = UsartDataLsbFirst;
|
|
stcInitCfg.enStopBit = UsartOneStopBit;
|
|
stcInitCfg.enParity = UsartParityNone;
|
|
stcInitCfg.enSampleMode = UsartSampleBit8;
|
|
stcInitCfg.enDetectMode = UsartStartBitFallEdge;
|
|
stcInitCfg.enHwFlow = UsartRtsEnable;
|
|
|
|
PWC_Fcg1PeriphClockCmd(DBG_FCG1_PERIPH, Enable);
|
|
|
|
PORT_SetFunc(DBG_USART_RX_PORT, DBG_USART_RX_PIN, DBG_USART_RX_FUNC, Disable);
|
|
PORT_SetFunc(DBG_USART_TX_PORT, DBG_USART_TX_PIN, DBG_USART_TX_FUNC, Disable);
|
|
|
|
enRet = USART_UART_Init(DBG_USART_CH, &stcInitCfg);
|
|
if(enRet != Ok) {
|
|
Error_Handler();
|
|
}
|
|
enRet = USART_SetBaudrate(DBG_USART_CH, BaudRate);
|
|
if(enRet != Ok) {
|
|
Error_Handler();
|
|
}
|
|
|
|
stcIrqRegiCfg.enIRQn = DBGUART_IRQn;
|
|
stcIrqRegiCfg.pfnCallback = &DBGUsartRxIrqCallback;
|
|
stcIrqRegiCfg.enIntSrc = DBG_USART_RI_NUM;
|
|
enIrqRegistration(&stcIrqRegiCfg);
|
|
NVIC_SetPriority(stcIrqRegiCfg.enIRQn, 2);
|
|
NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
|
|
NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
|
|
|
|
stcIrqRegiCfg.enIRQn = DBGUART_EI_IRQn;
|
|
stcIrqRegiCfg.pfnCallback = &DBGUsartErrIrqCallback;
|
|
stcIrqRegiCfg.enIntSrc = DBG_USART_EI_NUM;
|
|
enIrqRegistration(&stcIrqRegiCfg);
|
|
NVIC_SetPriority(stcIrqRegiCfg.enIRQn, 2);
|
|
NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
|
|
NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
|
|
|
|
USART_FuncCmd(DBG_USART_CH, UsartTx, Enable);
|
|
USART_FuncCmd(DBG_USART_CH, UsartRx, Enable);
|
|
USART_FuncCmd(DBG_USART_CH, UsartRxInt, Enable);
|
|
}
|
|
|
|
void DebugUartSend(uint8_t *sData, uint16_t sLen)
|
|
{
|
|
for(int i = 0; i < sLen; i++) {
|
|
USART_SendData(DBG_USART_CH, sData[i]);
|
|
while(USART_GetStatus(DBG_USART_CH, UsartTxComplete) == Reset);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************************
|
|
* RS485 Ch1 (USART2) - 升级通道, 按GateWay APP配置方式
|
|
****************************************************************************************/
|
|
static uint8_t RS485Ch1UartRec(void)
|
|
{
|
|
uint16_t u16Data = USART_RecData(RS485_CH1_USART_CH);
|
|
return (uint8_t)u16Data;
|
|
}
|
|
|
|
static void RS485Ch1UsartErrIrqCallback(void)
|
|
{
|
|
if(RS485_CH1_USART_CH->SR_f.ORE) {
|
|
RS485_CH1_USART_CH->CR1_f.CORE = 1;
|
|
USART_RecData(RS485_CH1_USART_CH);
|
|
}
|
|
if(RS485_CH1_USART_CH->SR_f.PE)
|
|
RS485_CH1_USART_CH->CR1_f.CPE = 1;
|
|
if(RS485_CH1_USART_CH->SR_f.FE)
|
|
RS485_CH1_USART_CH->CR1_f.CFE = 1;
|
|
}
|
|
|
|
static void RS485Ch1UsartRxIrqCallback(void)
|
|
{
|
|
uint8_t rData = RS485Ch1UartRec();
|
|
RS485Ch1RxIrqCallback(rData);
|
|
}
|
|
|
|
void RS485Ch1_Config(uint32_t BaudRate)
|
|
{
|
|
stc_usart_uart_init_t stcInitCfg;
|
|
stc_irq_regi_conf_t stcIrqRegiCfg;
|
|
en_result_t enRet;
|
|
stc_port_init_t stcPortInit;
|
|
|
|
MEM_ZERO_STRUCT(stcPortInit);
|
|
stcPortInit.enPinOType = Pin_OType_Cmos;
|
|
PORT_Init(RS485_CH1_USART_RX_PORT, RS485_CH1_USART_RX_PIN, &stcPortInit);
|
|
PORT_Init(RS485_CH1_USART_TX_PORT, RS485_CH1_USART_TX_PIN, &stcPortInit);
|
|
|
|
stcInitCfg.enClkMode = UsartIntClkCkNoOutput;
|
|
stcInitCfg.enClkDiv = UsartClkDiv_16;
|
|
stcInitCfg.enDataLength = UsartDataBits8;
|
|
stcInitCfg.enDirection = UsartDataLsbFirst;
|
|
stcInitCfg.enStopBit = UsartOneStopBit;
|
|
stcInitCfg.enParity = UsartParityNone;
|
|
stcInitCfg.enSampleMode = UsartSampleBit8;
|
|
stcInitCfg.enDetectMode = UsartStartBitFallEdge;
|
|
stcInitCfg.enHwFlow = UsartRtsEnable;
|
|
|
|
PWC_Fcg1PeriphClockCmd(RS485_CH1_FCG1_PERIPH, Enable);
|
|
|
|
PORT_SetFunc(RS485_CH1_USART_RX_PORT, RS485_CH1_USART_RX_PIN, RS485_CH1_USART_RX_FUNC, Disable);
|
|
PORT_SetFunc(RS485_CH1_USART_TX_PORT, RS485_CH1_USART_TX_PIN, RS485_CH1_USART_TX_FUNC, Disable);
|
|
|
|
enRet = USART_UART_Init(RS485_CH1_USART_CH, &stcInitCfg);
|
|
if(enRet != Ok) {
|
|
Error_Handler();
|
|
}
|
|
enRet = USART_SetBaudrate(RS485_CH1_USART_CH, BaudRate);
|
|
if(enRet != Ok) {
|
|
Error_Handler();
|
|
}
|
|
|
|
stcIrqRegiCfg.enIRQn = RS485CH1_UART_IRQn;
|
|
stcIrqRegiCfg.pfnCallback = &RS485Ch1UsartRxIrqCallback;
|
|
stcIrqRegiCfg.enIntSrc = RS485_CH1_USART_RI_NUM;
|
|
enIrqRegistration(&stcIrqRegiCfg);
|
|
NVIC_SetPriority(stcIrqRegiCfg.enIRQn, 2);
|
|
NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
|
|
NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
|
|
|
|
stcIrqRegiCfg.enIRQn = RS485CH1_UART_EI_IRQn;
|
|
stcIrqRegiCfg.pfnCallback = &RS485Ch1UsartErrIrqCallback;
|
|
stcIrqRegiCfg.enIntSrc = RS485_CH1_USART_EI_NUM;
|
|
enIrqRegistration(&stcIrqRegiCfg);
|
|
NVIC_SetPriority(stcIrqRegiCfg.enIRQn, 2);
|
|
NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
|
|
NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
|
|
|
|
USART_FuncCmd(RS485_CH1_USART_CH, UsartTx, Enable);
|
|
USART_FuncCmd(RS485_CH1_USART_CH, UsartRx, Enable);
|
|
USART_FuncCmd(RS485_CH1_USART_CH, UsartRxInt, Enable);
|
|
}
|
|
|
|
void RS485Ch1UartSend(uint8_t *sData, uint16_t sLen)
|
|
{
|
|
RS485_CH1_TX();
|
|
for(int i = 0; i < sLen; i++) {
|
|
USART_SendData(RS485_CH1_USART_CH, sData[i]);
|
|
while(USART_GetStatus(RS485_CH1_USART_CH, UsartTxComplete) == Reset);
|
|
}
|
|
RS485_CH1_RX();
|
|
}
|
|
|
|
/*****************************************************************************************
|
|
* RS485 Ch2 (USART3)
|
|
****************************************************************************************/
|
|
static uint8_t RS485Ch2UartRec(void)
|
|
{
|
|
uint16_t u16Data = USART_RecData(RS485_CH2_USART_CH);
|
|
return (uint8_t)u16Data;
|
|
}
|
|
|
|
static void RS485Ch2UsartErrIrqCallback(void)
|
|
{
|
|
if(RS485_CH2_USART_CH->SR_f.ORE) {
|
|
RS485_CH2_USART_CH->CR1_f.CORE = 1;
|
|
USART_RecData(RS485_CH2_USART_CH);
|
|
}
|
|
if(RS485_CH2_USART_CH->SR_f.PE)
|
|
RS485_CH2_USART_CH->CR1_f.CPE = 1;
|
|
if(RS485_CH2_USART_CH->SR_f.FE)
|
|
RS485_CH2_USART_CH->CR1_f.CFE = 1;
|
|
}
|
|
|
|
static void RS485Ch2UsartRxIrqCallback(void)
|
|
{
|
|
uint8_t rData = RS485Ch2UartRec();
|
|
RS485Ch2RxIrqCallback(rData);
|
|
}
|
|
|
|
void RS485Ch2_Config(uint32_t BaudRate)
|
|
{
|
|
stc_usart_uart_init_t stcInitCfg;
|
|
stc_irq_regi_conf_t stcIrqRegiCfg;
|
|
en_result_t enRet;
|
|
stc_port_init_t stcPortInit;
|
|
|
|
MEM_ZERO_STRUCT(stcPortInit);
|
|
stcPortInit.enPinOType = Pin_OType_Cmos;
|
|
PORT_Init(RS485_CH2_USART_RX_PORT, RS485_CH2_USART_RX_PIN, &stcPortInit);
|
|
PORT_Init(RS485_CH2_USART_TX_PORT, RS485_CH2_USART_TX_PIN, &stcPortInit);
|
|
|
|
stcInitCfg.enClkMode = UsartIntClkCkNoOutput;
|
|
stcInitCfg.enClkDiv = UsartClkDiv_16;
|
|
stcInitCfg.enDataLength = UsartDataBits8;
|
|
stcInitCfg.enDirection = UsartDataLsbFirst;
|
|
stcInitCfg.enStopBit = UsartOneStopBit;
|
|
stcInitCfg.enParity = UsartParityNone;
|
|
stcInitCfg.enSampleMode = UsartSampleBit8;
|
|
stcInitCfg.enDetectMode = UsartStartBitFallEdge;
|
|
stcInitCfg.enHwFlow = UsartRtsEnable;
|
|
|
|
PWC_Fcg1PeriphClockCmd(RS485_CH2_FCG1_PERIPH, Enable);
|
|
|
|
PORT_SetFunc(RS485_CH2_USART_RX_PORT, RS485_CH2_USART_RX_PIN, RS485_CH2_USART_RX_FUNC, Disable);
|
|
PORT_SetFunc(RS485_CH2_USART_TX_PORT, RS485_CH2_USART_TX_PIN, RS485_CH2_USART_TX_FUNC, Disable);
|
|
|
|
enRet = USART_UART_Init(RS485_CH2_USART_CH, &stcInitCfg);
|
|
if(enRet != Ok) {
|
|
Error_Handler();
|
|
}
|
|
enRet = USART_SetBaudrate(RS485_CH2_USART_CH, BaudRate);
|
|
if(enRet != Ok) {
|
|
Error_Handler();
|
|
}
|
|
|
|
stcIrqRegiCfg.enIRQn = RS485CH2_UART_IRQn;
|
|
stcIrqRegiCfg.pfnCallback = &RS485Ch2UsartRxIrqCallback;
|
|
stcIrqRegiCfg.enIntSrc = RS485_CH2_USART_RI_NUM;
|
|
enIrqRegistration(&stcIrqRegiCfg);
|
|
NVIC_SetPriority(stcIrqRegiCfg.enIRQn, 2);
|
|
NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
|
|
NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
|
|
|
|
stcIrqRegiCfg.enIRQn = RS485CH2_UART_EI_IRQn;
|
|
stcIrqRegiCfg.pfnCallback = &RS485Ch2UsartErrIrqCallback;
|
|
stcIrqRegiCfg.enIntSrc = RS485_CH2_USART_EI_NUM;
|
|
enIrqRegistration(&stcIrqRegiCfg);
|
|
NVIC_SetPriority(stcIrqRegiCfg.enIRQn, 2);
|
|
NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
|
|
NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
|
|
|
|
USART_FuncCmd(RS485_CH2_USART_CH, UsartTx, Enable);
|
|
USART_FuncCmd(RS485_CH2_USART_CH, UsartRx, Enable);
|
|
USART_FuncCmd(RS485_CH2_USART_CH, UsartRxInt, Enable);
|
|
}
|
|
|
|
void RS485Ch2UartSend(uint8_t *sData, uint16_t sLen)
|
|
{
|
|
RS485_CH2_TX();
|
|
for(int i = 0; i < sLen; i++) {
|
|
USART_SendData(RS485_CH2_USART_CH, sData[i]);
|
|
while(USART_GetStatus(RS485_CH2_USART_CH, UsartTxComplete) == Reset);
|
|
}
|
|
RS485_CH2_RX();
|
|
}
|
|
|
|
/*****************************************************************************************
|
|
* GPIO - RS485收发控制引脚 (PC7=Ch1方向, PB13=Ch2方向), PC10供电不动
|
|
****************************************************************************************/
|
|
static void GPIO_Config(void)
|
|
{
|
|
stc_port_init_t stcPortInit;
|
|
stc_port_pub_set_t stcPortPub;
|
|
|
|
PORT_DebugPortSetting(TDO_SWO, Disable);
|
|
PORT_DebugPortSetting(TDI, Disable);
|
|
PORT_DebugPortSetting(TRST, Disable);
|
|
|
|
MEM_ZERO_STRUCT(stcPortInit);
|
|
MEM_ZERO_STRUCT(stcPortPub);
|
|
|
|
stcPortPub.enReadWait = WaitCycle3;
|
|
PORT_PubSetting(&stcPortPub);
|
|
|
|
stcPortInit.enPinMode = Pin_Mode_Out;
|
|
stcPortInit.enPinOType = Pin_OType_Cmos;
|
|
stcPortInit.enPinDrv = Pin_Drv_H;
|
|
stcPortInit.enPullUp = Disable;
|
|
|
|
/* RS485 Ch1 方向控制 PC7: 高=发送, 低=接收 */
|
|
PORT_Init(RS485_CH1_CTRL_PORT, RS485_CH1_CTRL_PIN, &stcPortInit);
|
|
RS485_CH1_RX();
|
|
|
|
/* RS485 Ch2 方向控制 PB13 */
|
|
PORT_Init(RS485_CH2_CTRL_PORT, RS485_CH2_CTRL_PIN, &stcPortInit);
|
|
RS485_CH2_RX();
|
|
}
|
|
|
|
void Error_Handler(void)
|
|
{
|
|
while(1){ ; }
|
|
}
|
|
|
|
/*****************************************************************************************
|
|
* Watch Dog - HC32F460 SWDT由ICG硬件启动, 周期喂狗
|
|
****************************************************************************************/
|
|
void FeedDog(void)
|
|
{
|
|
#if (WATCH_DOG == 1)
|
|
SWDT_RefreshCounter();
|
|
#endif
|
|
}
|
|
|
|
void BSP_Init(void)
|
|
{
|
|
SystemClockConfig();
|
|
GPIO_Config();
|
|
RS485Ch1_Config(500000);
|
|
ExtFlashInit(); /*外部SPI Flash: Cat1远程升级暂存区读取用*/
|
|
|
|
FeedDog();
|
|
SysTick_Init(1000);
|
|
FeedDog();
|
|
}
|
|
|
|
/*****************************************************************************************
|
|
* Flash操作
|
|
****************************************************************************************/
|
|
void FlashWrite(uint32_t Addr, uint32_t *wData, int wLen)
|
|
{
|
|
EFM_Unlock();
|
|
EFM_FlashCmd(Enable);
|
|
while(Set != EFM_GetFlagStatus(EFM_FLAG_RDY)) { ; }
|
|
for(int i = 0; i < wLen; i++) {
|
|
if(EFM_SingleProgram(Addr + i * 4, wData[i]) != Ok) {
|
|
break;
|
|
}
|
|
}
|
|
EFM_Lock();
|
|
}
|
|
|
|
static void FlashRead(uint32_t u32Addr, uint32_t *rData, int rLen)
|
|
{
|
|
for(int i = 0; i < rLen / 4; i++) {
|
|
rData[i] = *((volatile uint32_t*)(u32Addr + i * 4));
|
|
}
|
|
}
|
|
|
|
/*外部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));
|
|
}
|
|
|
|
void WriteBootPara(BootPara wData)
|
|
{
|
|
int wLen;
|
|
uint32_t *Data;
|
|
|
|
Data = (uint32_t *)wData;
|
|
wLen = sizeof(BootPara_t) / 4;
|
|
EFM_Unlock();
|
|
EFM_FlashCmd(Enable);
|
|
while(Set != EFM_GetFlagStatus(EFM_FLAG_RDY)) { ; }
|
|
|
|
/* Erase sector. */
|
|
EFM_SectorErase(BOOT_PARA_ADDRESS);
|
|
|
|
for(int i = 0; i < wLen; i++) {
|
|
if(EFM_SingleProgram(BOOT_PARA_ADDRESS + i * 4, Data[i]) != Ok) {
|
|
break;
|
|
}
|
|
}
|
|
EFM_Lock();
|
|
}
|
|
|
|
void EraseFlash(uint32_t BaseAddr, uint32_t SectorCnt)
|
|
{
|
|
EFM_Unlock();
|
|
EFM_FlashCmd(Enable);
|
|
while(Set != EFM_GetFlagStatus(EFM_FLAG_RDY)) { ; }
|
|
|
|
/*从BaseAddr起连续擦除SectorCnt个扇区(A/B区通用), 不碰参数区*/
|
|
for(uint32_t i = 0; i < SectorCnt; i++) {
|
|
EFM_SectorErase(BaseAddr + i * FLASH_SECTOR_SIZE);
|
|
FeedDog();
|
|
}
|
|
EFM_Lock();
|
|
}
|
|
|
|
/*****************************************************************************************
|
|
* User Irq CallBack (weak)
|
|
****************************************************************************************/
|
|
__weak void DbgRxIrqCallback(uint8_t rData)
|
|
{
|
|
}
|
|
|
|
__weak void RS485Ch1RxIrqCallback(uint8_t rData)
|
|
{
|
|
}
|
|
|
|
__weak void RS485Ch2RxIrqCallback(uint8_t rData)
|
|
{
|
|
}
|
|
|
|
|