/* This function is only used for retrive exception log*/ static void USB2UART_PutUARTBytes(UART_PORT port, kal_uint8 *Buffaddr, kal_uint16 Length) { kal_uint32 index; kal_uint16 data_length = 0; kal_uint16 offset = 0; /* This function can only be called after exception*/ if(INT_Exception_Enter == 0) ASSERT(0); if ( (gUsbDevice.device_type != USB_CDC_ACM)||(USB2UARTPort.initialized == KAL_FALSE)) { /* This function should only be called when assertion, if not CDC_ACM type, return it directly*/ return; } /* flush previous data first*/ USB2UART_Polling_Flush_Transmit_Data(); /* If data length is larger than TX ring buffer, seperate to send as seceral times*/ do { if((Length - offset) > g_UsbACM.acm_param->tx_ringbuff_size) { data_length = g_UsbACM.acm_param->tx_ringbuff_size; } else { data_length = Length - offset; } /* put data to tx queue*/ /* push data from caller buffer to ring buffer */ for (index = 0; index < data_length; index++) { Buf_Push(&(USB2UARTPort.Tx_Buffer),*(Buffaddr+offset+index)); } offset+=data_length; /* flush the tx queue*/ USB2UART_Polling_Flush_Transmit_Data(); } while(offset<Length); }
/* This function is only used for retrive exception log*/ static void USB2UART_PutUARTByte(UART_PORT port, kal_uint8 data) { /* This function can only be called after exception*/ if(INT_Exception_Enter == 0) ASSERT(0); if ((gUsbDevice.device_type != USB_CDC_ACM)||(USB2UARTPort.initialized == KAL_FALSE)) { /* This function should only be called when assertion, if not CDC_ACM type, return it directly*/ return; } /* flush previous data first*/ USB2UART_Polling_Flush_Transmit_Data(); /* put data to tx queue*/ /* push data from caller buffer to ring buffer */ Buf_Push(&(USB2UARTPort.Tx_Buffer), data); /* flush the tx queue*/ USB2UART_Polling_Flush_Transmit_Data(); }
/* * task context * write user data to UART tx buffer * uint8 *Buffaddr:pointer to user's data * uint16 Length: user's data length * return:real length write to tx buffer */ uint16 uart_put_bytes(volatile uint8 *pBufAdr, volatile uint16 BufLen) { uint16 len, i; volatile uint16 roomleft = 0; uint8 *ptr = pBufAdr; volatile uint16 size = BufLen; /*UART TX interrupt mode*/ if (UART_TX_POLL_ENABLE == FALSE) { /*when litter tx buff, should use polling*/ while (size) { len = 0; Buf_GetRoomLeft(&(UARTPort.Tx_Buffer), roomleft); if (roomleft) { if (size <= roomleft) len = size; else if (size > roomleft) len = roomleft; for (i = 0; i < len; i++ ) Buf_Push(&(UARTPort.Tx_Buffer),*(ptr++)); size -= len; } UART_EnableTX(); } return BufLen; } else { /*UART TX polling mode*/ i = 0; while (i < BufLen) { UART_PutUARTByte(*(pBufAdr + i)); i++; } return BufLen; } }
/* put bytes to ISR tx buffer, handle the special character in this function(add escape character) return value is the actually put out bytes*/ static kal_uint16 USB2UART_SendISRData(UART_PORT port, kal_uint8 *buffaddr, kal_uint16 length, kal_uint8 mode, kal_uint8 escape_char, module_type ownerid) { kal_int16 real_count, index; kal_uint8 data; kal_uint32 savedMask; kal_uint8 ep_num = 0; kal_bool setup_dma = KAL_FALSE; BUFFER_INFO *tx_isr_info = &(USB2UARTPort.Tx_Buffer_ISR); if(ownerid != USB2UARTPort.ownerid) { #ifdef __PRODUCTION_RELEASE__ return 0; #else EXT_ASSERT( 0, (kal_uint32) ownerid, USB2UARTPort.ownerid, 0); #endif } if ( (gUsbDevice.device_type != USB_CDC_ACM) || (USB2UARTPort.initialized == KAL_FALSE) || (gUsbDevice.nDevState!=DEVSTATE_CONFIG)) return 0; if (mode == 0) { real_count = USB2UART_PutISRBytes(port, buffaddr, length, ownerid); } else { savedMask = SaveAndSetIRQMask(); Buf_GetRoomLeft(tx_isr_info, real_count); RestoreIRQMask(savedMask); /* determine real sent data count */ if (real_count > length) real_count = length; for (index = 0; index < real_count; index++) { kal_uint16 roomleft; savedMask = SaveAndSetIRQMask(); Buf_GetRoomLeft(tx_isr_info, roomleft); RestoreIRQMask(savedMask); data = *(buffaddr + index); /* if the character is special character, translate it. PC has the ability to distinguish it*/ if (data == USB2UARTPort.DCB.xonChar) { if ( roomleft >= 2 ) { Buf_Push(tx_isr_info, escape_char); Buf_Push(tx_isr_info, 0x01); } else { break; } } else if (data == USB2UARTPort.DCB.xoffChar) { if ( roomleft >= 2 ) { Buf_Push(tx_isr_info, escape_char); Buf_Push(tx_isr_info, 0x02); } else { break; } } else if (data == escape_char) { if ( roomleft >= 2 ) { Buf_Push(tx_isr_info, escape_char); Buf_Push(tx_isr_info, 0x03); } else { break; } } else { if (roomleft) { Buf_Push(tx_isr_info, data); } else { break; } } } real_count = index; savedMask = SaveAndSetIRQMask(); /* in case usb is plugged out just before this critical section */ if(gUsbDevice.device_type == USB_CDC_ACM) { // if(USB_DMA_Get_Run_Status(g_UsbACM.txpipe->byEP) == KAL_FALSE) if(g_UsbACM.setup_dma == KAL_FALSE) { g_UsbACM.setup_dma = KAL_TRUE; setup_dma = KAL_TRUE; ep_num = g_UsbACM.txpipe->byEP; } } RestoreIRQMask(savedMask); if(setup_dma == KAL_TRUE) { USB_Dbg_Trace(USB_ACM_DMA_SETUP_3, drv_get_current_time(), ep_num, 0); USB2UART_DMATransmit(ep_num, KAL_FALSE); } } #ifndef __PRODUCTION_RELEASE__ if(ownerid != USB2UARTPort.ownerid) { EXT_ASSERT( 0, (kal_uint32) ownerid, (kal_uint32)USB2UARTPort.ownerid, 0); } #endif if(ownerid != MOD_TST_READER) { drv_trace1(TRACE_FUNC, USBACM_SEND_ISR_DATA, real_count); // kal_prompt_trace(MOD_USB, "SendISR %d", real_count); } return real_count; }
void uart_rb_push(uint8 ch) { BUFFER_INFO *puart_rb_info = &uart_rb_info; Buf_Push(puart_rb_info,ch); return; }
/* * ISR context * uart_rx_cb() will be called when UART rx interrupt assert, * then we should featch data from HW FIFO quickly. * fucntion: fetch data from HW FIFO to rx ring buffer * we should use uart_get_byte(&ch) to fetch byte from HW FIFO as quickly as possible */ void uart_rx_cb(void) { uint16 roomleft = 0; PKT_FIFO *infor; PKT_FIFO *temp_info; uint8 ch = 0; PKT_DESC *rx_desc = &(UARTPort.Rx_desc); BUFFER_INFO *rx_ring = &(UARTPort.Rx_Buffer); static uint8 ATMatchNum = 0; static uint8 IWMatchNum = 0; /* * MCU only forward uart rx data to air * here,copy to rx ring and return */ #if (UARTRX_TO_AIR_LEVEL == 2) if (iot_uart_rx_mode == UARTRX_PUREDATA_MODE) { while (uart_get_byte(&ch)) { Buf_Push(rx_ring,ch); } return; } #endif /* * MCU should collect data to be packet */ //normal case Buf_GetRoomLeft(rx_ring,roomleft); while (uart_get_byte(&ch)) { //new receive begin,detect packet header at first switch (rx_desc->cur_type) { case PKT_UNKNOWN: { /**************** detect packet type ***************/ //support more ATcmd prefix analysis /*case 1:AT#*/ if (ATCmdPrefixAT[ATMatchNum] == ch) { ATMatchNum++; } else { ATMatchNum = 0; } /*case 2:iwpriv ra0*/ if (ATCmdPrefixIW[IWMatchNum] == ch) { IWMatchNum++; } else { IWMatchNum = 0; } if ((ATMatchNum == sizeof(ATCmdPrefixAT)-1) || //match case 1: AT# (IWMatchNum == sizeof(ATCmdPrefixIW)-1)) { //match case 2:iwpriv ra0 rx_desc->cur_num = rx_desc->pkt_num; infor = &(rx_desc->infor[rx_desc->cur_num]); infor->pkt_len = 0; if (ATMatchNum == sizeof(ATCmdPrefixAT)-1) { rx_desc->cur_type = PKT_ATCMD; //match case 1: AT# } else if (IWMatchNum == sizeof(ATCmdPrefixIW)-1) { rx_desc->cur_type = PKT_IWCMD; //match case 2:iwpriv ra0 } ATMatchNum = 0; IWMatchNum = 0; continue; } } break; case PKT_ATCMD: case PKT_IWCMD: { infor = &(rx_desc->infor[rx_desc->cur_num]); /*received one complete packet*/ if (ch == '\n' || ch == '\r') { //if task has consumed some packets if (rx_desc->cur_num != rx_desc->pkt_num) { temp_info = infor; infor = &(rx_desc->infor[rx_desc->pkt_num]); infor->pkt_len = temp_info->pkt_len; temp_info->pkt_len = 0; temp_info->pkt_type = PKT_UNKNOWN; } infor->pkt_type = rx_desc->cur_type; // PKT_ATCMD / PKT_IWCMD; rx_desc->pkt_num++; rx_desc->cur_type = PKT_UNKNOWN; } else { /*continue to receiving packet */ Buf_Push(rx_ring,ch); roomleft--; infor->pkt_len++; } /* * if overflow,we discard the current packet * example1:packet length > ring size * example2:rx ring buff can no be freed by task as quickly as rx interrupt coming */ if ((!roomleft) || (rx_desc->pkt_num >= NUM_DESCS)) { //rollback Buff_RollBack(rx_ring,infor->pkt_len); roomleft += infor->pkt_len; infor->pkt_type = PKT_UNKNOWN; infor->pkt_len = 0; rx_desc->cur_type = PKT_UNKNOWN; if (rx_desc->pkt_num >= NUM_DESCS) { rx_desc->pkt_num--; } } } break; default: break; } } }
/********************************************************************************************************* ** Function name: UartProcessMsg() ** Descriptions: 处理串口消息 ** input parameters: 无 ** Output parameters:: 无 ** Returned value: 无 ** Created by: ** Created Date: 2014.10.03 **-------------------------------------------------------------------------------------------------------- ** Modified by: ** Modified date: 2014.10.03 **-------------------------------------------------------------------------------------------------------- *********************************************************************************************************/ void UartProcessMsg(u8 ch) { u16 roomleft = 0; PKT_FIFO *infor; PKT_FIFO *temp_info; PKT_DESC *rx_desc = &(UART1Port.Rx_desc); BUFFER_INFO *rx_ring = &(UART1Port.Rx_Buffer); static u16 AMHeadLen = sizeof(RCTRL_STRU_MSGHEAD); static u16 AMBodyLen =0; static u8 PDMatchNum = 0; static u8 PrintMatchNum = 0; Buf_GetRoomLeft(rx_ring,roomleft); switch (rx_desc->cur_type) { case PKT_UNKNOWN: { /**************** detect packet type ***************/ if (PureDataPrefix[PDMatchNum] == ch) { PDMatchNum++; } else { PDMatchNum = 0; } if (PrintCmdPrefix[PrintMatchNum] == ch) { PrintMatchNum++; } else { PrintMatchNum = 0; } if ((PDMatchNum == sizeof(PureDataPrefix)-1) || (PrintMatchNum == sizeof(PrintCmdPrefix)-1)) //match case 3:arm data { rx_desc->cur_num = rx_desc->pkt_num; infor = &(rx_desc->infor[rx_desc->cur_num]); infor->pkt_len = 0; if (PrintMatchNum == sizeof(PrintCmdPrefix)-1) { rx_desc->cur_type = PKT_PRINTCMD; //match case 2:iwpriv ra0 } else if (PDMatchNum == sizeof(PureDataPrefix)-1) { u8 i= 0; rx_desc->cur_type = PKT_PUREDATA; //match case 2:iwpriv ra0 if(roomleft<AMHeadLen) { rx_desc->cur_type= PKT_UNKNOWN; } else { for(i = 0;i < sizeof(PureDataPrefix)-1;i++) { Buf_Push(rx_ring,PureDataPrefix[i]); } roomleft= roomleft-sizeof(PureDataPrefix)+1; infor = &(rx_desc->infor[rx_desc->cur_num]); infor->pkt_len = infor->pkt_len + i; } } PrintMatchNum = 0; PDMatchNum = 0; } } break; case PKT_PRINTCMD: { /* * received one complete packet */ if(ch == '\0'||ch == '\n' || ch == '\r') { rx_desc->cur_type = PKT_UNKNOWN; return; } } break; case PKT_PUREDATA: { infor = &(rx_desc->infor[rx_desc->cur_num]); Buf_Push(rx_ring,ch); roomleft--; infor->pkt_len++; if(infor->pkt_len==AC_PAYLOADLENOFFSET) { AMBodyLen = ch; } else if(infor->pkt_len==(AC_PAYLOADLENOFFSET +1)) { AMBodyLen = (AMBodyLen<<8) + ch; } /* * if overflow,we discard the current packet * example1:packet length > ring size * example2:rx ring buff can no be freed by task as quickly as rx interrupt coming */ if ((!roomleft) || (rx_desc->pkt_num >= NUM_DESCS)) { //rollback Buff_RollBack(rx_ring,infor->pkt_len); roomleft += infor->pkt_len; infor->pkt_type = PKT_UNKNOWN; infor->pkt_len = 0; rx_desc->cur_type = PKT_UNKNOWN; if (rx_desc->pkt_num >= NUM_DESCS) { rx_desc->pkt_num--; } } /* * received one complete packet */ if(AMHeadLen+AMBodyLen==infor->pkt_len) { //if task has consumed some packets if (rx_desc->cur_num != rx_desc->pkt_num) { temp_info = infor; infor = &(rx_desc->infor[rx_desc->pkt_num]); infor->pkt_len = temp_info->pkt_len; temp_info->pkt_len = 0; temp_info->pkt_type = PKT_UNKNOWN; } infor->pkt_type = rx_desc->cur_type; // PKT_ATCMD / PKT_IWCMD; rx_desc->pkt_num++; rx_desc->cur_type = PKT_UNKNOWN; AMBodyLen =0; return; } } break; default: break; } }