/* * Copyright (c) 2022 OpenLuat & AirM2M * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "user.h" #define JTT_PACK_FLAG (0x7e) #define JTT_PACK_CODE (0x7d) #define JTT_PACK_CODE_F1 (0x02) #define JTT_PACK_CODE_F2 (0x01) #ifdef __BUILD_APP__ #define DBG_BUF_SIZE (2048) #define DBG_TXBUF_SIZE DBG_BUF_SIZE #define DBG_RXBUF_SIZE (0) #define DBG_RXBUF_BAND (1) #else #define DBG_BUF_SIZE (4080) #define DBG_TXBUF_SIZE DBG_BUF_SIZE #define DBG_RXBUF_SIZE DBG_BUF_SIZE #define DBG_RXBUF_BAND (4) #endif typedef struct { Buffer_Struct LogBuffer; Buffer_Struct RxBuffer; CBFuncEx_t Fun; CBDataFun_t TxFun; //Loop_Buffer IrqBuffer; uint8_t Data[DBG_BUF_SIZE]; uint8_t CacheData[DBG_BUF_SIZE * 2]; uint8_t RxData[DBG_BUF_SIZE * 2]; uint8_t TxBuf[DBG_TXBUF_SIZE]; uint8_t RxDMABuf[DBG_RXBUF_BAND][DBG_RXBUF_SIZE + 16]; uint8_t AppMode; uint8_t InitDone; uint8_t InsertBusy; uint8_t TxBusy; uint8_t RxDMASn; }DBG_CtrlStruct; static DBG_CtrlStruct prvDBGCtrl; static void prvDBG_Out(void) { uint32_t TxLen; SEND_AGAIN: if (prvDBGCtrl.LogBuffer.Pos) { prvDBGCtrl.TxBusy = 1; TxLen = (prvDBGCtrl.LogBuffer.Pos > sizeof(prvDBGCtrl.TxBuf))?sizeof(prvDBGCtrl.TxBuf):prvDBGCtrl.LogBuffer.Pos; memcpy(prvDBGCtrl.TxBuf, prvDBGCtrl.LogBuffer.Data, TxLen); OS_BufferRemove(&prvDBGCtrl.LogBuffer, TxLen); Uart_DMATx(DBG_UART_ID, DBG_UART_TX_DMA_STREAM, prvDBGCtrl.TxBuf, TxLen); // if (!Uart_BufferTx(DBG_UART_ID, prvDBGCtrl.TxBuf, TxLen)) // { // prvDBGCtrl.TxBusy = 0; // goto SEND_AGAIN; // } } else { if (prvDBGCtrl.LogBuffer.MaxLen > (DBG_BUF_SIZE * 8)) { OS_ReInitBuffer(&prvDBGCtrl.LogBuffer, (DBG_BUF_SIZE * 4)); } } } static void add_trace_data(uint8_t *data, uint32_t len) { Buffer_StaticWrite(&prvDBGCtrl.LogBuffer, data, len); } void add_printf_data(uint8_t *data, uint32_t len) { #ifdef __BUILD_APP__ uint32_t Critical = OS_EnterCritical(); configASSERT(prvDBGCtrl.InsertBusy == 0); prvDBGCtrl.InsertBusy = 1; if ((prvDBGCtrl.LogBuffer.Pos + len) > prvDBGCtrl.LogBuffer.MaxLen) { OS_ReSizeBuffer(&prvDBGCtrl.LogBuffer, prvDBGCtrl.LogBuffer.MaxLen * 2); } OS_BufferWrite(&prvDBGCtrl.LogBuffer, data, len); prvDBGCtrl.InsertBusy = 0; if (prvDBGCtrl.TxBusy || !prvDBGCtrl.InitDone || !prvDBGCtrl.AppMode) { OS_ExitCritical(Critical); return; } prvDBG_Out(); OS_ExitCritical(Critical); #endif } extern const uint8_t ByteToAsciiTable[16]; void DBG_Trace(const char* format, ...) { #ifndef __RAMRUN__ char c; char *s = 0; int d = 0, i = 0, p = 0; uint32_t slen; unsigned int ud = 0; unsigned char ch[36] = {0}; unsigned char int_max; unsigned char flag; va_list ap; #ifdef __BUILD_APP__ __disable_irq(); if (prvDBGCtrl.AppMode) { prvDBGCtrl.AppMode = 0; //关闭掉APP的DMA UART输出 // DMA_StopStream(DBG_UART_TX_DMA_STREAM); Buffer_StaticInit(&prvDBGCtrl.LogBuffer, prvDBGCtrl.Data, sizeof(prvDBGCtrl.Data)); } #endif va_start(ap, format); while (* format) { if (* format != '%') { add_trace_data((uint8_t *)format, 1); format += 1; continue; } slen = 0; repeat: switch (*(++format)) { case '*': slen = va_arg(ap, int); goto repeat; break; case 's': case 'S': s = va_arg(ap, char *); if (!slen) { for ( ; *s; s++) { add_trace_data((uint8_t *) s, 1); } } else { add_trace_data((uint8_t *) s, slen); } break; case 'c': case 'C': c = va_arg(ap, int); add_trace_data((uint8_t *)&c, 1); break; case 'x': case 'X': ud = va_arg(ap, int); p = 8; for(i = 0; i < p; i++) { ch[i] = ByteToAsciiTable[(unsigned char)(ud&0x0f)]; ud >>= 4; } for(i = p; i > 0; i--) { add_trace_data(&ch[i -1], 1); } break; case 'u': case 'U': ud = va_arg(ap, unsigned int); int_max = 0; for(i = 0; i < 16; i++) { ch[i] = ud%10 + '0'; ud = ud/10; int_max++; if (!ud) break; } for(i = int_max; i > 0; i--) { add_trace_data(&ch[i -1], 1); } break; case 'd': case 'D': d = va_arg(ap, int); if (d < 0) { flag = 1; } else { flag = 0; } d = abs(d); int_max = 0; for(i = 0; i < 16; i++) { ch[i] = d%10 + '0'; d = d/10; int_max++; if (!d) break; } if (flag) { flag = '-'; add_trace_data(&flag, 1); } for(i = int_max; i > 0; i--) { add_trace_data(&ch[i -1], 1); } break; case 'b': case 'B': ud = va_arg(ap, int); if (ud > 0xffff) { p = 32; } else if (ud > 0xff) { p = 16; } else { p = 8; } for(i = 0; i < p; i++) { ch[i] = ByteToAsciiTable[(unsigned char)(ud&0x01)]; ud >>= 1; } for(i = p; i > 0; i--) { add_trace_data(&ch[i -1], 1); } break; default: //add_trace_data((uint8_t *)format, 1); goto repeat; break; } format++; } va_end(ap); add_trace_data("\r\n", 2); // va_list ap; // va_start(ap, format); // prvDBGCtrl.TxPos = vsnprintf(prvDBGCtrl.TxBuf, sizeof(prvDBGCtrl.TxBuf) - 2, format, ap); // va_end(ap); // prvDBGCtrl.TxBuf[prvDBGCtrl.TxPos] = '\r'; // prvDBGCtrl.TxBuf[prvDBGCtrl.TxPos + 1] = '\n'; Uart_BlockTx(DBG_UART_ID, prvDBGCtrl.LogBuffer.Data, prvDBGCtrl.LogBuffer.Pos); prvDBGCtrl.LogBuffer.Pos = 0; #ifdef __BUILD_APP__ __enable_irq(); #endif #endif } void DBG_BlHexPrintf(void *Data, unsigned int len) { uint8_t *data = (uint8_t *)Data; int8_t uart_buf[128]; uint32_t i,j; j = 0; if (!len) { return ; } for (i = 0; i < len; i++) { uart_buf[j++] = ByteToAsciiTable[(data[i] & 0xf0) >> 4]; uart_buf[j++] = ByteToAsciiTable[data[i] & 0x0f]; uart_buf[j++] = ' '; } uart_buf[j++] = '\r'; uart_buf[j++] = '\n'; add_trace_data(uart_buf, j); Uart_BlockTx(DBG_UART_ID, prvDBGCtrl.LogBuffer.Data, prvDBGCtrl.LogBuffer.Pos); prvDBGCtrl.LogBuffer.Pos = 0; } #ifdef __BUILD_OS__ void DBG_HexPrintf(void *Data, unsigned int len) { uint8_t *data = (uint8_t *)Data; int8_t *uart_buf; uint32_t i,j; uint32_t Critical; j = 0; if (!prvDBGCtrl.AppMode) return; if (!len) { return ; } uart_buf = OS_Zalloc(len * 3 + 2); if (!uart_buf) { return; } for (i = 0; i < len; i++) { uart_buf[j++] = ByteToAsciiTable[(data[i] & 0xf0) >> 4]; uart_buf[j++] = ByteToAsciiTable[data[i] & 0x0f]; uart_buf[j++] = ' '; } uart_buf[j++] = '\r'; uart_buf[j++] = '\n'; prvDBGCtrl.TxFun(uart_buf, len * 3 + 2); OS_Free(uart_buf); } void DBG_Printf(const char* format, ...) { char *buf = NULL; char isr_buf[256]; va_list ap; if (!prvDBGCtrl.AppMode) return; va_start(ap, format); if (OS_CheckInIrq()) { buf = isr_buf; vsnprintf_(buf, 255, format, ap); } else { buf = OS_Zalloc(1024); vsnprintf_(buf, 1023, format, ap); } va_end(ap); prvDBGCtrl.TxFun( buf, strlen(buf)); if (!OS_CheckInIrq()) { OS_Free(buf); } } void DBG_DirectOut(void *Data, uint32_t Len) { add_printf_data(Data, Len); } void DBG_Send(void) { uint32_t Critical; uint32_t TxLen; if (prvDBGCtrl.TxBusy || !prvDBGCtrl.InitDone || !prvDBGCtrl.AppMode) { return; } Critical = OS_EnterCritical(); prvDBG_Out(); OS_ExitCritical(Critical); } #endif int32_t DBG_UartIrqCB(void *pData, void *pParam) { uint32_t Length; uint32_t State = (uint32_t)pParam; uint8_t LastRxSn; switch (State) { case UART_CB_TX_BUFFER_DONE: case UART_CB_TX_ALL_DONE: #ifdef __BUILD_APP__ case DMA_CB_DONE: { DMA_ClearStreamFlag(DBG_UART_TX_DMA_STREAM); prvDBGCtrl.TxBusy = 0; if (!prvDBGCtrl.InsertBusy) { DBG_Send(); } } #endif break; case UART_CB_RX_BUFFER_FULL: case UART_CB_RX_TIMEOUT: #ifdef __BUILD_APP__ Uart_RxBufferCB(DBG_UART_ID, prvDBGCtrl.Fun); break; #endif case UART_CB_RX_NEW: #ifndef __BUILD_APP__ case DMA_CB_DONE: DMA_StopStream(DBG_UART_RX_DMA_STREAM); Length = DMA_GetDataLength(DBG_UART_RX_DMA_STREAM, &prvDBGCtrl.RxDMABuf[prvDBGCtrl.RxDMASn][0]); Length += Uart_FifoRead(DBG_UART_ID, &prvDBGCtrl.RxDMABuf[prvDBGCtrl.RxDMASn][Length]); LastRxSn = prvDBGCtrl.RxDMASn; prvDBGCtrl.RxDMASn = (prvDBGCtrl.RxDMASn + 1)%DBG_RXBUF_BAND; Uart_DMARx(DBG_UART_ID, DBG_UART_RX_DMA_STREAM, &prvDBGCtrl.RxDMABuf[prvDBGCtrl.RxDMASn][0], DBG_RXBUF_SIZE); if (Length) { prvDBGCtrl.Fun(&prvDBGCtrl.RxDMABuf[LastRxSn][0], Length); } #else // Length = Uart_FifoRead(DBG_UART_ID, &prvDBGCtrl.RxDMABuf[prvDBGCtrl.RxDMASn][0]); // LastRxSn = prvDBGCtrl.RxDMASn; // prvDBGCtrl.RxDMASn = (prvDBGCtrl.RxDMASn + 1)%DBG_RXBUF_BAND; #endif break; case UART_CB_ERROR: // DBG("%x", pParam); break; } } void DBG_Response(uint8_t Cmd, uint8_t Result, uint8_t *Data, uint8_t Len) { uint8_t Temp[260]; uint16_t TxLen, Check; Temp[0] = Cmd; Temp[1] = Result; Temp[2] = Len; memcpy(Temp + 3, Data, Len); Check = CRC16Cal(Temp, Len + 3, CRC16_CCITT_SEED, CRC16_CCITT_GEN, 0); BytesPutLe16(&Temp[Len + 3], Check); TxLen = TransferPack(JTT_PACK_FLAG, JTT_PACK_CODE, JTT_PACK_CODE_F1, JTT_PACK_CODE_F2, Temp, Len + 5, prvDBGCtrl.TxBuf); Uart_BufferTx(DBG_UART_ID, prvDBGCtrl.TxBuf, TxLen); } static int32_t DBG_RebootTimeoutCB(void *pData, void *pParam) { NVIC_SystemReset(); } static void DBG_Reboot(uint8_t *Data, uint32_t Len) { #ifdef __BUILD_APP__ timer_t *Timer = Timer_Create(DBG_RebootTimeoutCB, NULL, NULL); Timer_StartMS(Timer, 100, 1); Uart_DeInit(DBG_UART_ID); prvDBGCtrl.AppMode = 0; #else NVIC_SystemReset(); #endif } static void DBG_FlashDownloadStart(uint8_t *Data, uint32_t Len) { #ifdef __BUILD_APP__ #else if (Len < 12) { DBG_Response(DBG_CMD_FLASHDOWNLOADSTART, ERROR_PARAM_INVALID, &Len, 4); return; } uint32_t StartAddress = BytesGetLe32(Data); uint32_t TotalLen = BytesGetLe32(Data + 4); uint32_t CRC32 = BytesGetLe32(Data + 8); if (BL_StartNewDownload(StartAddress, TotalLen, CRC32)) { DBG_Response(DBG_CMD_FLASHDOWNLOADSTART, ERROR_PERMISSION_DENIED, &Len, 4); return; } else { DBG_Response(DBG_CMD_FLASHDOWNLOADSTART, ERROR_NONE, &Len, 4); return; } #endif } static void DBG_FlashDownload(uint8_t *Data, uint32_t Len) { #ifdef __BUILD_APP__ #else if (Len < 7) { DBG_Response(DBG_CMD_FLASHDOWNLOAD, ERROR_PARAM_INVALID, &Len, 4); return; } uint32_t PacketSn = BytesGetLe32(Data); uint32_t NextPacketSn; int Result; uint16_t PacketLen = BytesGetLe32(Data + 4); if ( (PacketLen + 6) != Len ) { DBG_Response(DBG_CMD_FLASHDOWNLOAD, ERROR_PARAM_INVALID, &Len, 4); return; } else { Result = BL_DownloadAddData(PacketSn, Data + 6, PacketLen, &NextPacketSn); if (Result >= 0) { DBG_Response(DBG_CMD_FLASHDOWNLOAD, ERROR_NONE, &Result, 4); } else { DBG_Response(DBG_CMD_FLASHDOWNLOAD, ERROR_PARAM_OVERFLOW, &NextPacketSn, 4); } return; } #endif } static void DBG_FlashDownloadEnd(uint8_t *Data, uint32_t Len) { #ifdef __BUILD_APP__ #else uint8_t Result = BL_DownloadEnd(); DBG_Response(DBG_CMD_FLASHDOWNLOADEND, Result, &Result, 1); #endif } static void DBG_RunApp(uint8_t *Data, uint32_t Len) { #ifdef __BUILD_APP__ #else uint8_t Result = BL_RunAPP(); DBG_Response(DBG_CMD_RUNAPP, Result, &Result, 1); #endif } static const CBDataFun_t DBG_ProtoclFunlist[] = { DBG_Reboot, DBG_FlashDownloadStart, DBG_FlashDownload, DBG_FlashDownloadEnd, DBG_RunApp, }; static int32_t DBG_DummyRx(void *pData, void *pParam) { uint32_t DelLen; uint32_t i, DealLen; uint16_t Check, Check2; //Buffer_Struct Buffer; uint8_t FindHead = 0; uint8_t FindEnd = 0; uint8_t NoMoreData = 0; int32_t Result; Buffer_Struct *RxBuf = &prvDBGCtrl.RxBuffer; DBG("%u", pParam); if (pParam) { #ifdef __BUILD_APP__ OS_BufferWrite(&prvDBGCtrl.RxBuffer, (uint8_t *)pData, (uint32_t)pParam); #else Buffer_StaticWrite(&prvDBGCtrl.RxBuffer, (uint8_t *)pData, (uint32_t)pParam); #endif while(!NoMoreData) { if (!RxBuf->Pos) { // DBG("no more net rx data"); break; } if (!FindHead) { for(i = 0; i < RxBuf->Pos; i++) { if (JTT_PACK_FLAG == RxBuf->Data[i]) { OS_BufferRemove(RxBuf, i); FindHead = 1; break; } } if (!FindHead) { NoMoreData = 1; RxBuf->Pos = 0; continue; } } FindEnd = 0; DealLen = 0; DelLen = 0; for(i = 1; i < RxBuf->Pos; i++) { if (JTT_PACK_FLAG == RxBuf->Data[i]) { DelLen = i + 1; // DBG("msg rec len %dbyte", DelLen); DealLen = i + 1; FindEnd = 1; break; } } if (!FindEnd) { // DBG("rest %dbyte", RxBuf->Pos); NoMoreData = 1; continue; } if (2 == DealLen) //连续2个0x7E,去除第一个,第二个作为头开始重新搜索 { // DBG("!"); OS_BufferRemove(RxBuf, 1); FindHead = 1; continue; } if (FindEnd) { FindHead = 0; if (DelLen > DBG_BUF_SIZE) { DBG("msg too long, %u", DelLen); OS_BufferRemove(RxBuf, DelLen); continue; } DealLen = TransferUnpack(JTT_PACK_FLAG, JTT_PACK_CODE, JTT_PACK_CODE_F1, JTT_PACK_CODE_F2, &RxBuf->Data[1], DealLen - 2, prvDBGCtrl.RxData); OS_BufferRemove(RxBuf, DelLen); if (DealLen >= 5) { Check = CRC16Cal(prvDBGCtrl.RxData, DealLen - 2, CRC16_CCITT_SEED, CRC16_CCITT_GEN, 0); Check2 = BytesGetLe16(&prvDBGCtrl.RxData[DealLen - 2]); if (Check != Check2) { // DBG_BlHexPrintf(Data, Len); DBG("check error %04x %04x", Check, Check2); DBG_Response(prvDBGCtrl.RxData[0], ERROR_PROTOCL, &Result, 4); RxBuf->Pos = 0; return 0; } else { DealLen -= 2; if (prvDBGCtrl.RxData[0] < sizeof(DBG_ProtoclFunlist)/sizeof(CBDataFun_t)) { DBG_ProtoclFunlist[prvDBGCtrl.RxData[0]](prvDBGCtrl.RxData + 1, DealLen - 1); } } } else { DBG("%d", DealLen); } } } } return 0; } void DBG_Init(uint8_t AppMode) { prvDBGCtrl.AppMode = AppMode; GPIO_Iomux(DBG_UART_TX_PIN, DBG_UART_TX_AF); GPIO_Iomux(DBG_UART_RX_PIN, DBG_UART_RX_AF); #ifdef __BUILD_APP__ if (AppMode) { OS_InitBuffer(&prvDBGCtrl.LogBuffer, DBG_BUF_SIZE * 4); OS_InitBuffer(&prvDBGCtrl.RxBuffer, DBG_BUF_SIZE); //Buffer_StaticInit(&prvDBGCtrl.LogBuffer, prvDBGCtrl.Data, sizeof(prvDBGCtrl.Data)); Uart_BaseInit(DBG_UART_ID, DBG_UART_BR, 1, UART_DATA_BIT8, UART_PARITY_NONE, UART_STOP_BIT1, DBG_UartIrqCB); Uart_EnableRxIrq(DBG_UART_ID); DMA_TakeStream(DBG_UART_TX_DMA_STREAM); Uart_DMATxInit(DBG_UART_ID, DBG_UART_TX_DMA_STREAM, DBG_UART_TX_DMA_CHANNEL); prvDBGCtrl.TxFun = add_printf_data; } else #endif { Buffer_StaticInit(&prvDBGCtrl.LogBuffer, prvDBGCtrl.Data, sizeof(prvDBGCtrl.Data)); Buffer_StaticInit(&prvDBGCtrl.RxBuffer, prvDBGCtrl.CacheData, sizeof(prvDBGCtrl.CacheData)); Uart_BaseInit(DBG_UART_ID, BL_UART_BR, 0, UART_DATA_BIT8, UART_PARITY_NONE, UART_STOP_BIT1, DBG_UartIrqCB); DMA_TakeStream(DBG_UART_RX_DMA_STREAM); Uart_DMARxInit(DBG_UART_ID, DBG_UART_RX_DMA_STREAM, DBG_UART_RX_DMA_CHANNEL); Uart_DMARx(DBG_UART_ID, DBG_UART_RX_DMA_STREAM, &prvDBGCtrl.RxDMABuf[prvDBGCtrl.RxDMASn][0], DBG_RXBUF_SIZE); } prvDBGCtrl.InitDone = 1; prvDBGCtrl.Fun = DBG_DummyRx; } void DBG_SetRxCB(CBFuncEx_t cb) { prvDBGCtrl.Fun = cb; } void DBG_SetTxCB(CBDataFun_t cb) { prvDBGCtrl.TxFun = cb; }