各子功能设计引导进入APP功能设计(涉及CPU程序运行原理) 所谓引导至APP,其实就做两件事,一是重置MSP指针,二是重置PC指针。具体原因在OS章节有说明。
typedef void (*pAppFunction)(void); #define BOOT_APP_MAIN_ADDR 0x800E000 static VOID BOOT_GoToApp(VOID) { pAppFunction Jump_To_Application; unsigned long jumpAddress; //跳转至用户代码 jumpAddress = *(volatile U32*)(BOOT_APP_MAIN_ADDR + 4); Jump_To_Application = (pAppFunction)jumpAddress; //初始化用户程序的堆栈指针 __set_MSP(*(volatile U32*) BOOT_APP_MAIN_ADDR); Jump_To_Application(); }
重启功能设计(涉及看门狗)
DRV_IWDG_Init(); /* 利用看门狗复位芯片 */
文件传输功能设计(涉及XMODEM协议)
文件传输采用Xmodem协议,该协议非常简单,如下, 报文格式:
- 串口配置为异步,8位数据,no校验,no停止位
- 报文格式说明
Byte1,Start Of Hearder, 如下, SOH(01H) – Xmodem数据头 EOT(04H) – 发送结束 ACK(06H) – 认可响应 NAK(15H) – 不认可响应 CAN(18H) – 撤销传送 Byte2,Packet Number ,报文序列码,从1开始,每包递加,FF后循环 Byte3,~(Packet Number),报文序列码的补码 Byte4-131,Packet Data,报文数据,每个报文都是128个字节,如果不足128,则用1AH补充 Byte132-133,16bit CRC,Byte132-CRC高位,Byte133-CRC地位,只对128个数据做CRC16运行,多项式为X16+X12+X^5+1。 Tx方发生SOH数据报文 Rx方收到且数正确,回ACK,不正确会NAK 文件传输完毕,Tx发EOT通知Rx,Rx回ACK 任何时候,收到CAN,则强制停止 #define XMODEM_SOH 0x01 /* Xmodem数据头 */ #define XMODEM_STX 0x02 /* 1K-Xmodem数据头 */ #define XMODEM_EOT 0x04 /* 发送结束 */ #define XMODEM_ACK 0x06 /* 认可响应 */ #define XMODEM_NAK 0x15 /* 不认可响应 */ #define XMODEM_CAN 0x18 /* 撤销传送 */ #define XMODEM_CTRLZ 0x1A /* 填充数据包 */
#define XMODEM_TIMEOUT 2000 #define XMODEM_MAXPKTLEN 133 #define XMODEM_PKTBUFLEN 128
static U16 XMODEM_Crc16(IN const U8 *buf, IN U8 len) { U8 i = 0; U16 crc = 0;
while (len--) { crc ^= *buf++ << 8;
for (i = 0; i < 8; ++i) { if( crc & 0x8000 ) { crc = (crc << 1) ^ 0x1021; } else { crc = crc << 1; } } } return crc; }
static S32 XMODEM_Check(IN BOOL isCrc, IN const U8 *buf, U8 sz) { U16 crc = 0; U16 tcrc = 0; U8 i = 0; U8 cks = 0;
if (TRUE == isCrc) { crc = XMODEM_Crc16(buf, sz); tcrc = (buf[sz]<<8)+buf[sz+1]; if (crc != tcrc) { APP_ERROR("%u, %u", crc, tcrc); return OS_ERROR; } } else { for (i = 0; i < sz; ++i) { cks += buf; } if (cks != buf[sz]) { APP_ERROR("%u, %u", cks, buf[sz]); return OS_ERROR; } }
return OS_OK; }
static S32 XMODEM_GetOnePkt(IN U8 pktNum) { U8 ch = 0; S32 ret = OS_OK; U8 i = 0; U8 xbuff[XMODEM_MAXPKTLEN] = {0};
for (i = 1; i < XMODEM_MAXPKTLEN; i++) { ret = DRV_UART1_GetChar(XMODEM_TIMEOUT, &ch); if (ret != OS_OK) { APP_ERROR("ret=%d", ret); return OS_ERROR; } xbuff[i-1] = ch; }
if (xbuff[0] != (U8)(~xbuff[1])) { APP_ERROR("%u,%u", xbuff[0], xbuff[1]); return OS_ERROR; }
ret = XMODEM_Check(TRUE, &xbuff[2], XMODEM_PKTBUFLEN); if (ret != OS_OK) { APP_ERROR("ret=%d", ret); return OS_ERROR; }
if (pktNum != xbuff[0]) { (VOID)APP_FILE_Write(APP_FILE_FD_APPINFLASH, &xbuff[2], XMODEM_PKTBUFLEN); }
return OS_OK; }
S32 APP_XMODEM_Recive(VOID) { U8 ch = 0; S32 ret = OS_OK; U8 pktNum = 0;
ret = DRV_UART1_GetChar(XMODEM_TIMEOUT, &ch); if (ret != OS_OK) { APP_ERROR("ret=%d", ret); return OS_CONTINUE; }
switch (ch) { case XMODEM_SOH: ret = XMODEM_GetOnePkt(pktNum); if (ret != OS_OK) { DRV_UART1_PutChar(XMODEM_NAK); break; } pktNum++; DRV_UART1_PutChar(XMODEM_ACK); break; case XMODEM_EOT: DRV_UART1_PutChar(XMODEM_ACK); return OS_OK; case XMODEM_CAN: DRV_UART1_PutChar(XMODEM_ACK); return OS_ERROR; case 'q': return OS_ERROR; }
return OS_CONTINUE; }
static VOID XMODEM_FillPkt(IN U8 cmd , IN U8 index, IN U8 *buffer) { U16 crc = 0;
buffer[0] = cmd; buffer[1] = index; buffer[2] = (U8)(~index); crc = XMODEM_Crc16(&buffer[3], XMODEM_PKTBUFLEN); buffer[XMODEM_PKTBUFLEN+3] = (crc >> 8); buffer[XMODEM_PKTBUFLEN+4] = crc;
return; }
static S32 XMODEM_SendSohPkt(IN U8 fd) { BOOL resend = FALSE; U8 index = 1; U8 ch = 0; S32 ret = OS_OK; U8 buffer[XMODEM_MAXPKTLEN] = {0}; U8 retryCount = 0;
for (;;) { if (FALSE == resend) { retryCount = 0; memset(buffer, 0, XMODEM_MAXPKTLEN); ret = APP_FILE_Read(fd, XMODEM_PKTBUFLEN, &buffer[3]); if (ret != OS_OK) { return OS_OK; } XMODEM_FillPkt(XMODEM_SOH, index, buffer); }
DRV_UART1_SendBuf(buffer, XMODEM_MAXPKTLEN);
ret = DRV_UART1_GetChar(XMODEM_TIMEOUT, &ch); if (ret != OS_OK) { resend = TRUE; retryCount++; } switch (ch) { case XMODEM_ACK: index++; resend = FALSE; break; case XMODEM_NAK: resend = TRUE; retryCount++; break; case XMODEM_CAN: return OS_ERROR; }
if (retryCount > 16) { return OS_ERROR; } } }
static VOID XMODEM_SendEotPkt(VOID) { U8 retryCount = 0; S32 ret = OS_OK; U8 buffer[XMODEM_MAXPKTLEN] = {0}; U8 ch = 0;
XMODEM_FillPkt(XMODEM_EOT, 1, buffer); DRV_UART1_SendBuf(buffer, XMODEM_MAXPKTLEN);
while (1) { retryCount++; ret = DRV_UART1_GetChar(XMODEM_TIMEOUT, &ch); if (ret != OS_OK) { DRV_UART1_SendBuf(buffer, XMODEM_MAXPKTLEN); } else { switch (ch) { case XMODEM_ACK: return; case XMODEM_NAK: DRV_UART1_SendBuf(buffer, XMODEM_MAXPKTLEN); break; case XMODEM_CAN: return; } } if (retryCount > 16) { return; } } }
static VOID XMODEM_SendCanPkt(VOID) { U8 buffer[XMODEM_MAXPKTLEN] = {0};
XMODEM_FillPkt(XMODEM_CAN, 1, buffer); DRV_UART1_SendBuf(buffer, XMODEM_MAXPKTLEN); }
S32 APP_XMODEM_Send(IN U8 fd) { S32 ret = OS_OK;
ret = XMODEM_SendSohPkt(fd); if (OS_OK == ret) { XMODEM_SendEotPkt(); return OS_OK; } else if (OS_ERROR == ret) { XMODEM_SendCanPkt(); return OS_ERROR; }
return OS_OK; }
|