/** * Test USB CDC Serial */ static void _SendText(void) { uint32_t i, testCnt; if (!isCdcSerialON) { printf("\n\r!! Host serial program not ready!\n\r"); return; } printf("\n\r- USB CDC Serial writing ...\n\r"); /* Test data initialize */ for (i = 0; i < TEST_BUFFER_SIZE; i ++) testBuffer[i] = (i % 10) + '0'; printf("- Send 0,1,2 ... to host:\n\r"); for (testCnt = 0; testCnt < TEST_COUNT; testCnt ++) { txDoneFlag = 0; CDCDSerialDriver_Write(testBuffer, TEST_BUFFER_SIZE, (TransferCallback) _UsbDataSent, 0); while (!txDoneFlag); } }
//------------------------------------------------------------------------------ /// Handles interrupts coming from Timer #0. //------------------------------------------------------------------------------ static void ISR_Timer0() { unsigned char size; unsigned int status = AT91C_BASE_TC0->TC_SR; if ((status & AT91C_TC_CPCS) != 0) { // Flush PDC buffer size = DATABUFFERSIZE - AT91C_BASE_US0->US_RCR; if (size == 0) { AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; return; } AT91C_BASE_US0->US_RCR = 0; // Send current buffer through the USB while (CDCDSerialDriver_Write(usartBuffers[usartCurrentBuffer], size, 0, 0) != USBD_STATUS_SUCCESS); // Restart read on buffer USART_ReadBuffer(AT91C_BASE_US0, usartBuffers[usartCurrentBuffer], DATABUFFERSIZE); usartCurrentBuffer = 1 - usartCurrentBuffer; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; } }
/*---------------------------------------------------------------------------- * Callback invoked when data has been received on the USB. *----------------------------------------------------------------------------*/ static void _UsbDataReceived(uint32_t unused, uint8_t status, uint32_t received, uint32_t remaining) { unused = unused; Usart *pUs = BASE_USART; /* Check that data has been received successfully */ if (status == USBD_STATUS_SUCCESS) { SCB_InvalidateDCache_by_Addr((uint32_t *)usbBuffer, received); /* Send back CDC data */ if (isCdcEchoON) { while (CDCDSerialDriver_Write(usbBuffer, received, 0, 0) != USBD_STATUS_SUCCESS); } /* Send data through USART */ if (isCdcSerialON) _UsartDmaTx((uint32_t)&pUs->US_THR, usbBuffer, received); /* Check if bytes have been discarded */ if ((received == DATAPACKETSIZE) && (remaining > 0)) { TRACE_WARNING( "_UsbDataReceived: %u bytes discarded\n\r", (unsigned int)remaining); } } else { TRACE_WARNING("_UsbDataReceived: Transfer error\n\r"); } }
void usb_printf(const char * format, ...) { if (!isSerialConnected) return; if (USBState == STATE_SUSPEND) return; unsigned int timeout=1000; while(bufferInUse && timeout--) { delay_ms(1); } if (bufferInUse) { printf("usb_printf timeout\r\n"); return; } unsigned int str_len = 0; va_list args; va_start (args, format); str_len = vsprintf (printBuffer,format, args); va_end (args); bufferInUse = 1; if(CDCDSerialDriver_Write((void *)printBuffer,str_len, UsbWriteCompleted, 0)!= USBD_STATUS_SUCCESS) { printf("USB FAIL\r\n"); bufferInUse = 0; } }
void flush_stdout() { // This must not be called from within a USB callback // because the write function will not succeed until the interrupt // at the end of the last TX is serviced. while (CDCDSerialDriver_Write(usb_tx_buffer, usb_tx_len, 0, 0) != USBD_STATUS_SUCCESS); usb_tx_len = 0; }
/** * USART interrupt handler */ void USART2_Handler(void) { Usart *pUs = BASE_USART; uint32_t status; uint16_t serialState; uint32_t count; status = USART_GetStatus(pUs); status &= USART_GetItMask(pUs); /* If USB device is not configured, do nothing */ if (!isCdcSerialON) { USART_DisableIt(pUs, 0xFFFFFFFF); return; } if (status & US_CSR_TIMEOUT) { /*Clear TIMEOUT Flag and Start Time-out After Next Character Received*/ USART_AcknowledgeRxTimeOut(BASE_USART, 0); /* Flush the DMA FIFO */ XDMAC_SoftwareFlushReq(dmad.pXdmacs, usartDmaRxChannel); /* Transfer the last pack through USB */ count = dmad.pXdmacs->XDMAC_CHID[usartDmaRxChannel].XDMAC_CUBC; SCB_InvalidateDCache_by_Addr((uint32_t *)usartBuffers, DATAPACKETSIZE - count); while (CDCDSerialDriver_Write(usartBuffers, DATAPACKETSIZE - count, 0, 0) != USBD_STATUS_SUCCESS); /*Reset DMA transfer*/ XDMAD_StopTransfer(&dmad, usartDmaRxChannel); _UsartDmaRx(); } else { /* Errors */ serialState = CDCDSerialDriver_GetSerialState(); /* Overrun */ if ((status & US_CSR_OVRE) != 0) { TRACE_WARNING("USART_IrqHandler: Overrun\n\r"); serialState |= CDCSerialState_OVERRUN; } /* Framing error */ if ((status & US_CSR_FRAME) != 0) { TRACE_WARNING("USART_IrqHandler: Framing error\n\r"); serialState |= CDCSerialState_FRAMING; } CDCDSerialDriver_SetSerialState(serialState); } }
int UartWrite(int uart, char *data, int len) { if(uart == 0) { if(g_UartUsbWriteBufferBusy) return 0; if(len > USB_BUFFER_SIZE) len = USB_BUFFER_SIZE; memcpy(g_UartUsbWriteBuffer, data, len); CDCDSerialDriver_Write(g_UartUsbWriteBuffer, len, UartUsbWrite, 0); return len; } else { return DMA_Write(&g_Uart1DMA, (void*)data, len); } }
static void prvCDCSend( const char *pcData, size_t xDataLength ) { const TickType_t xTransferCompleteDelay = pdMS_TO_TICKS( 500UL ); ( void ) pcData; ( void ) xDataLength; if( xDataLength > 0 ) { if( CDCDSerialDriver_Write( ( void * ) pcData, xDataLength, ( TransferCallback ) prvCDCDataTransmittedCallback, 0 ) == USBD_STATUS_SUCCESS ) { /* Wait for the transfer to complete. */ xEventGroupWaitBits( xCDCEventBits, cmdTX_COMPLETE_BIT, /* The bit to wait for. */ pdTRUE, /* Clear the bit before exiting the function. */ pdFALSE, /* Only need to wait for one bit anyway. */ xTransferCompleteDelay ); /* The maximum time to wait for the event. */ } } }
//unsigned int received_tmp = 0; void UsbDataWrite(unsigned char* data, unsigned int size) { // int transmit_attempts = 0; // // while (CDCDSerialDriver_Write(puchMsg, received_tmp, 0, 0) != USBD_STATUS_SUCCESS) { // if (++transmit_attempts == max_number_of_cyclic_transfers) { // usb_state = USB_WRITE_ERROR; // break; // } // } int transmit_attempts = 0; while (CDCDSerialDriver_Write(data, size, 0, 0) != USBD_STATUS_SUCCESS) { if (++transmit_attempts == max_number_of_cyclic_transfers) { usb_state = USB_WRITE_ERROR; break; } } }
/** * \brief DMA RX callback function */ static void _UsDmaRxCallback(uint32_t channel, void *pArg) { pArg = pArg; if (channel != usartDmaRxChannel) return; /*Clear TIMEOUT Flag and Start Time-out After Next Character Received*/ USART_AcknowledgeRxTimeOut(BASE_USART, 0); SCB_InvalidateDCache_by_Addr((uint32_t *)(usartBuffers[usartCurrentBuffer]), DATABUFFERSIZE); /* Send buffer through the USB */ while (CDCDSerialDriver_Write(usartBuffers[usartCurrentBuffer], DATAPACKETSIZE, 0, 0) != USBD_STATUS_SUCCESS); /* Restart read on buffer */ _UsartDmaRx(); }
//------------------------------------------------------------------------------ /// Handles interrupts coming from USART #0. //------------------------------------------------------------------------------ static void ISR_Usart0() { unsigned int status = AT91C_BASE_US0->US_CSR; unsigned short serialState; // If USB device is not configured, do nothing if (USBD_GetState() != USBD_STATE_CONFIGURED) { AT91C_BASE_US0->US_IDR = 0xFFFFFFFF; return; } // Buffer has been read successfully if ((status & AT91C_US_ENDRX) != 0) { // Disable timer AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // Send buffer through the USB while (CDCDSerialDriver_Write(usartBuffers[usartCurrentBuffer], DATABUFFERSIZE, 0, 0) != USBD_STATUS_SUCCESS); // Restart read on buffer USART_ReadBuffer(AT91C_BASE_US0, usartBuffers[usartCurrentBuffer], DATABUFFERSIZE); usartCurrentBuffer = 1 - usartCurrentBuffer; // Restart timer AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; } // Buffer has been sent if ((status & AT91C_US_TXBUFE) != 0) { // Restart USB read CDCDSerialDriver_Read(usbBuffer, DATABUFFERSIZE, (TransferCallback) UsbDataReceived, 0); AT91C_BASE_US0->US_IDR = AT91C_US_TXBUFE; } // Errors serialState = CDCDSerialDriver_GetSerialState(); // Overrun if ((status & AT91C_US_OVER) != 0) { TRACE_WARNING( "ISR_Usart0: Overrun\n\r"); serialState |= CDCDSerialDriver_STATE_OVERRUN; } // Framing error if ((status & AT91C_US_FRAME) != 0) { TRACE_WARNING( "ISR_Usart0: Framing error\n\r"); serialState |= CDCDSerialDriver_STATE_FRAMING; } CDCDSerialDriver_SetSerialState(serialState); }
/* * This function is called when the USB transfer from the * device to the host is finished. */ static void usb0_tx_complete_handler( unsigned int unused, unsigned char status, unsigned int transferred, unsigned int remaining) { ENTER_CRITICAL_REGION(); while (transferred--) { if ((USB_TX_BUF_MAX_SIZE - 1) == usb_0_buffer.tx_buf_head) { /* Reached the end of buffer, revert back to beginning of buffer. */ usb_0_buffer.tx_buf_head = 0; } else { /* * * Increment the index to point the next character to be * * transmitted. * */ usb_0_buffer.tx_buf_head++; } } if (usb_0_buffer.tx_buf_head != usb_0_buffer.tx_buf_tail) { /* * Prepare a linear buffer for submitting data * remaining data in the buffer */ uint8_t tx_length = 0; uint8_t i = 0; uint8_t head = 0; uint8_t tail = 0; head = usb_0_buffer.tx_buf_head; tail = usb_0_buffer.tx_buf_tail; while (head != tail) { usb_0_tx_temp_buf[i] = usb_0_buffer.tx_buf[head]; if (i == (USB_TX_MAX_SIZE - 1)) //cannot transmit more than USB_TX_MAX_SIZE at once break; if ((head) == (USB_TX_BUF_MAX_SIZE - 1)) head = 0; else head++; i++; } tx_length = i; usb_0_buffer.tx_count = 1; while (CDCDSerialDriver_Write(usb_0_tx_temp_buf, tx_length, (TransferCallback) usb0_tx_complete_handler, 0) != USBD_STATUS_SUCCESS) ; } else { /* No more data for transmission */ usb_0_buffer.tx_count = 0; } LEAVE_CRITICAL_REGION(); }
/** * @brief Transmit data via USB 0 * * This function transmits data via USB channel 0. * * @param data Pointer to the buffer where the data to be transmitted is present * @param length Number of bytes to be transmitted * * @return Number of bytes actually transmitted */ uint8_t sio_usb_0_tx(uint8_t *data, uint8_t length) { uint8_t bytes_to_be_written = 0; uint8_t head = 0; uint8_t tail = 0; uint8_t size = 0; uint8_t back = 0; uint8_t tx_length = 0; uint8_t i = 0; /* The transmit interrupt is disabled. */ //ENTER_CRITICAL_REGION(); /* * Initialize head and tail */ head = usb_0_buffer.tx_buf_head; tail = usb_0_buffer.tx_buf_tail; size = get_buffer_size( usb_0_buffer.tx_buf_head, usb_0_buffer.tx_buf_tail, USB_TX_BUF_MAX_SIZE); if (size < length) { /* Not enough buffer space available. Use the remaining size. */ bytes_to_be_written = size; } else { bytes_to_be_written = length; } /* Remember the number of bytes transmitted. */ back = bytes_to_be_written; /* The data is copied to the transmit buffer. */ while (bytes_to_be_written > 0) { usb_0_buffer.tx_buf[usb_0_buffer.tx_buf_tail] = *data; if ((USB_TX_BUF_MAX_SIZE - 1) == usb_0_buffer.tx_buf_tail) { /* Reached the end of buffer, revert back to beginning of buffer. */ usb_0_buffer.tx_buf_tail = 0; } else { /* * Increment the index to point the next character to be * inserted. */ usb_0_buffer.tx_buf_tail++; } bytes_to_be_written--; data++; } /* * Check whether there is a transmission ongoing. Otherwise write * data into the UART data register. Transmission of subsequent * bytes / data will be taken care in the ISR. */ if (usb_0_buffer.tx_count == 0) { /* * Prepare a linear buffer for submitting data */ head = usb_0_buffer.tx_buf_head; tail = usb_0_buffer.tx_buf_tail; while (head != tail) { usb_0_tx_temp_buf[i] = usb_0_buffer.tx_buf[head]; if (i == USB_TX_MAX_SIZE) //cannot transmit more than USB_TX_MAX_SIZE at once break; if ((head) == (USB_TX_BUF_MAX_SIZE - 1)) head = 0; else head++; i++; } tx_length = i; /* The transmit interrupt is enabled. */ //LEAVE_CRITICAL_REGION(); usb_0_buffer.tx_count = 1; while (CDCDSerialDriver_Write(usb_0_tx_temp_buf, tx_length, (TransferCallback) usb0_tx_complete_handler, 0) != USBD_STATUS_SUCCESS) ; } return back; }
/*! \brief Main function. Execution starts here. */ int main(void) { uint8_t isUsbConnected = 0; /* Disable watchdog */ WDT_Disable(WDT); SCB_EnableICache(); SCB_EnableDCache(); /* Output example information */ printf("-- USB Device CDC Serial Project %s --\n\r", SOFTPACK_VERSION); printf("-- %s\n\r", BOARD_NAME); printf("-- Compiled: %s %s With %s--\n\r", __DATE__, __TIME__ , COMPILER_NAME); /* Initialize PIO interrupts */ PIO_InitializeInterrupts(0); /* Interrupt priority */ NVIC_SetPriority(USBHS_IRQn, 2); /* Configure DMA driver */ _ConfigureDma(); /* Configure USART */ _ConfigureUsart(); _UsartDmaRxSetup(); /* Initialize OTG clocks */ _ConfigureUotghs(); /* CDC serial driver initialization */ CDCDSerialDriver_Initialize(&cdcdSerialDriverDescriptors); /* Help information */ _DebugHelp(); // Start USB stack to authorize VBus monitoring USBD_Connect(); /* Driver loop */ while (1) { /* Device is not configured */ if (USBD_GetState() < USBD_STATE_CONFIGURED) { if (isUsbConnected) { isUsbConnected = 0; isCdcSerialON = 0; } } else if (isUsbConnected == 0) isUsbConnected = 1; /* Serial port ON/OFF */ if (CDCDSerialDriver_GetControlLineState() & CDCControlLineState_DTR) { if (!isCdcSerialON) { isCdcSerialON = 1; /* Start receiving data on the USART */ _UsartDmaRx(); USART_EnableIt(BASE_USART, US_CSR_FRAME | US_CSR_OVRE | US_IER_TIMEOUT); USART_EnableRecvTimeOut(BASE_USART, USART_TIMEOUT); /* Start receiving data on the USB */ CDCDSerialDriver_Read(usbBuffer, DATAPACKETSIZE, (TransferCallback) _UsbDataReceived, 0); } } else if (isCdcSerialON) isCdcSerialON = 0; if (DBG_IsRxReady()) { uint8_t key = DBG_GetChar(); /* ESC: CDC Echo ON/OFF */ if (key == 27) { printf("** CDC Echo %s\n\r", isCdcEchoON ? "OFF" : "ON"); isCdcEchoON = !isCdcEchoON; } /* 't': Test CDC writing */ else if (key == 't') _SendText(); else { printf("Alive\n\r"); while (CDCDSerialDriver_Write((char *)"Alive\n\r", 8, 0, 0) != USBD_STATUS_SUCCESS); _DebugHelp(); } } } }
//////////////////// // Fill data from USB to the RingBuffer and vice-versa void CDC_Task(void) { static char inCDC_TASK = 0; if(!USB_IsConnected) return; #ifdef ARM if(!inCDC_TASK){ // USB -> RingBuffer inCDC_TASK = 1; output_flush_func = CDC_Task; input_handle_func(DISPLAY_USB); inCDC_TASK = 0; } if(TTY_Tx_Buffer.nbytes) { uint16_t i=0; while(TTY_Tx_Buffer.nbytes && i<DATABUFFERSIZEOUT) { usbBufferOut[i++]=rb_get(&TTY_Tx_Buffer); } while (CDCDSerialDriver_Write(usbBufferOut,i, 0, 0) != USBD_STATUS_SUCCESS); } #else Endpoint_SelectEndpoint(CDC_RX_EPNUM); // First data in if(!inCDC_TASK && Endpoint_ReadWriteAllowed()){ // USB -> RingBuffer while (Endpoint_BytesInEndpoint()) { // Discard data on buffer full rb_put(&TTY_Rx_Buffer, Endpoint_Read_Byte()); } Endpoint_ClearCurrentBank(); inCDC_TASK = 1; output_flush_func = CDC_Task; input_handle_func(DISPLAY_USB); inCDC_TASK = 0; } Endpoint_SelectEndpoint(CDC_TX_EPNUM); // Then data out if(TTY_Tx_Buffer.nbytes && Endpoint_ReadWriteAllowed()) { cli(); while(TTY_Tx_Buffer.nbytes && (Endpoint_BytesInEndpoint() < USB_BUFSIZE)) Endpoint_Write_Byte(rb_get(&TTY_Tx_Buffer)); sei(); Endpoint_ClearCurrentBank(); // Send the data } #endif }