int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) { /* do basic initialization */ int res = uart_init_blocking(uart, baudrate); if(res < 0) { return res; } /* remember callback addresses */ uart_config[uart].rx_cb = rx_cb; uart_config[uart].arg = arg; /* enable receive and send interrupt */ switch(uart) { #if UART_0_EN case UART_0: NVIC_SetPriority(UART_0_IRQ_RX_CHAN, UART_0_IRQ_RX_PRIO); NVIC_EnableIRQ(UART_0_IRQ_RX_CHAN); USART_IntEnable(UART_0_DEV, _USART_IEN_RXDATAV_MASK); #if UART_0_ENABLE_BUF ringbuffer_init(&rb_uart0, buffer0, UART_0_BUFSIZE); NVIC_SetPriority(UART_0_IRQ_TX_CHAN, UART_0_IRQ_TX_PRIO); NVIC_EnableIRQ(UART_0_IRQ_TX_CHAN); USART_IntEnable(UART_0_DEV, _USART_IEN_TXBL_MASK); #endif break; #endif #if UART_1_EN case UART_1: NVIC_SetPriority(UART_1_IRQ_RX_CHAN, UART_1_IRQ_RX_PRIO); NVIC_SetPriority(UART_1_IRQ_TX_CHAN, UART_1_IRQ_TX_PRIO); NVIC_EnableIRQ(UART_1_IRQ_RX_CHAN); NVIC_EnableIRQ(UART_1_IRQ_TX_CHAN); USART_IntEnable(UART_1_DEV, _USART_IEN_RXDATAV_MASK); #if UART_1_ENABLE_BUF ringbuffer_init(&rb_uart1, buffer1, UART_1_BUFSIZE); NVIC_SetPriority(UART_1_IRQ_TX_CHAN, UART_1_IRQ_TX_PRIO); NVIC_EnableIRQ(UART_1_IRQ_TX_CHAN); USART_IntEnable(UART_1_DEV, _USART_IEN_TXBL_MASK); #endif break; #endif /* UART2 is considered as LEUART device which is functionable in low power mode */ #if UART_2_EN case UART_2: NVIC_SetPriority(UART_2_IRQ, UART_2_IRQ_PRIO); NVIC_EnableIRQ(UART_2_IRQ); LEUART_IntEnable(UART_2_DEV, LEUART_IEN_RXDATAV); #if UART_2_ENABLE_BUF ringbuffer_init(&rb_uart2, buffer2, UART_2_BUFSIZE); LEUART_IntEnable(UART_2_DEV, _LEUART_IEN_TXBL_MASK); #endif break; #endif default: /* Invalid usart device */ return -1; } return 0; }
static void leuartInit(void) { LEUART_Init_TypeDef leuart0Init; leuart0Init.enable = leuartEnable; /* Activate data reception on LEUn_TX pin. */ leuart0Init.refFreq = 0; /* Inherit the clock frequenzy from the LEUART clock source */ leuart0Init.baudrate = LEUART0_BAUDRATE; /* Baudrate = 9600 bps */ leuart0Init.databits = leuartDatabits8; /* Each LEUART frame containes 8 databits */ leuart0Init.parity = leuartNoParity; /* No parity bits in use */ leuart0Init.stopbits = leuartStopbits2; /* Setting the number of stop bits in a frame to 2 bitperiods */ CMU_ClockEnable(cmuClock_CORELE, true); CMU_ClockEnable(cmuClock_LEUART0, true); LEUART_Reset(LEUART0); LEUART_Init(LEUART0, &leuart0Init); LEUART0->SIGFRAME = '\n'; /* Enable LEUART Signal Frame Interrupt */ LEUART_IntEnable(LEUART0, LEUART_IEN_SIGF); /* Enable LEUART0 interrupt vector */ NVIC_SetPriority(LEUART0_IRQn, LEUART0_INT_PRIORITY); LEUART0->ROUTE = LEUART_ROUTE_RXPEN | LEUART_ROUTE_TXPEN | LEUART0_LOCATION; GPIO_PinModeSet(LEUART0_PORT, LEUART0_TX, gpioModePushPull, 1); GPIO_PinModeSet(LEUART0_PORT, LEUART0_RX, gpioModeInputPull, 1); lineEndReceived = xSemaphoreCreateBinary(); DMADRV_AllocateChannel(&dmaChannel, NULL); }
/* *Function name: LEUART0_IRQHandler *Description : Interrupt Service Routine for LEUART0. */ void LEUART0_IRQHandler(void) { leuartif = LEUART_IntGet(LEUART0); // Store the interrupt flag LEUART_IntClear(LEUART0, leuartif); //Clear interrupts if (leuartif & LEUART_IF_SIGF) { int temp = 0, i = 0; char tempChar[7]; // To store the Value of Temperature in char to transmit char temp_string[TX_bufferSize]; // Concatenated string for Message and Temperature, this will be transfered char copyCmp[sizeof(commandString)/sizeof(char)]; // string to store the Received string from Buffer to compare // Stop the LEUART reception and DMA Transfers for (i = 0; i < (strlen(commandString)); i++) // Run loop till the return message (RetTemp!) length and copy RX buffer to copyCmp for comparing { copyCmp[i] = RX_Buffer[i]; } copyCmp[8]='\0'; /* To extract the digits of the temperature variable and put in tempChar. A basic digit extraction algorithm is used and then each digit is passed one by one. */ if (!strcmp(commandString,copyCmp)) // If valid Command is Received ie RetTemp! { temp = temperature*10; tempChar[0] = (temp/100)+48; temp = temp%100; tempChar[1] = (temp/10)+48; temp = temp%10; tempChar[2] = '.'; tempChar[3] = (temp)+48; tempChar[4] = 'C'; tempChar[5] = '\r'; tempChar[6] = '\n'; strcpy(temp_string,returnMsg); //Copy the returnMsg message in the temporary string strcat(temp_string,tempChar); // Concatenate with tempChar to get the final message to be transfered // Enable DMA wake-up from LEUART0 TX LEUART0->CTRL = LEUART_CTRL_TXDMAWU; // Enable DMA wake up for LEUART TX in EM2 // Activate DMA for LEUART TX transfers DMA_ActivateBasic(DMA_CHANNEL_TX, true, false, (void *)&(LEUART0->TXDATA), (void *)temp_string, strlen(temp_string)- 1); // -1 for the Null character which we wont transmit } else { LEUART0->CTRL = LEUART_CTRL_TXDMAWU; // Enable DMA wake up for LEUART0 TX in EM2 // Activate DMA for LEUART TX transfers DMA_ActivateBasic(DMA_CHANNEL_TX, true, false, (void *)&(LEUART0->TXDATA), (void *)errorMsg, strlen(errorMsg)-2); // -1 for the Null character which we wont transmit } LEUART_IntEnable(LEUART0, LEUART_IF_RXDATAV); //Enable RXDATA Interrupt to check for received characters DMA_ActivateBasic(DMA_CHANNEL_RX, true, false, NULL, NULL, LEUART0_BUFFER-1); } else if (leuartif & LEUART_IF_RXDATAV) { LEUART_IntDisable(LEUART0, LEUART_IF_RXDATAV); // Disable after receiving } }
/* * Function Name: main(); * Description: All the function calls are done in main(). The CPU goes to sleep while in main(); until Interupt is generated. */ int main(void) { CHIP_Init(); CMU_HFRCOBandSet(cmuHFRCOBand_14MHz); CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFRCO); CMU_OscillatorEnable(cmuOsc_HFXO, false, false); blockSleepMode(EM2); //Prevents the CPU to go below EM3 mode. #if DEBUG_ON BSP_TraceSwoSetup(); //For simplicity studio Energy profiler code correlation. #endif LETIMER_setup(); //Initialize LETIMER. ADC_Setup(); //Initialize the ADC DMA_Init(); //Initialize DMA. DMA_Setup(); //Setup DMA. LEUART_Setup(); //Initialize LEUART. GPIO_Init(); //Initialize GPOIs. LETIMER_IntEnable(LETIMER0, LETIMER_IF_UF); //Enable underflow UF interrupt. LEUART_IntEnable(LEUART0, LEUART_IF_SIGF); // Enable SF RXDATAV NVIC_EnableIRQ(LETIMER0_IRQn); //Enable LETIMER0 interrupt vector in NVIC (Nested Vector Interrupt Controller) NVIC_EnableIRQ(LEUART0_IRQn); //Enable LETIMER0 interrupt vector in NVIC (Nested Vector Interrupt Controller) LEUART0->SIGFRAME = '!'; // Set LEUART signal frame to '!' LEUART0->CTRL |= LEUART_CTRL_RXDMAWU; // Enable DMA wake up for LEUART RX in EM2 DMA_ActivateBasic(DMA_CHANNEL_RX, true, false, (void *)RX_Buffer, (void *)&(LEUART0->RXDATA), LEUART0_BUFFER-1); // Enable Sleep-on-Exit #if SLEEPONEXIT SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk; // Setting the corresponding bit for SleepOnExit #endif while(1) { sleep(); //CPU goes to EM3 Mode to save energy, waits there until Interrupt is generated. } }
/**************************************************************************//** * @brief UART/LEUART IRQ Handler *****************************************************************************/ void RETARGET_IRQ_NAME(void) { #if defined(RETARGET_USART) if (RETARGET_UART->STATUS & USART_STATUS_RXDATAV) { #else if (RETARGET_UART->IF & LEUART_IF_RXDATAV) { #endif /* Store Data */ rxBuffer[rxWriteIndex] = RETARGET_RX(RETARGET_UART); rxWriteIndex++; rxCount++; if (rxWriteIndex == RXBUFSIZE) { rxWriteIndex = 0; } /* Check for overflow - flush buffer */ if (rxCount > RXBUFSIZE) { rxWriteIndex = 0; rxCount = 0; rxReadIndex = 0; } } } /** @} (end group RetargetIo) */ /**************************************************************************//** * @brief UART/LEUART toggle LF to CRLF conversion * @param on If non-zero, automatic LF to CRLF conversion will be enabled *****************************************************************************/ void RETARGET_SerialCrLf(int on) { if (on) LFtoCRLF = 1; else LFtoCRLF = 0; } /**************************************************************************//** * @brief Intializes UART/LEUART *****************************************************************************/ void RETARGET_SerialInit(void) { /* Enable peripheral clocks */ CMU_ClockEnable(cmuClock_HFPER, true); /* Configure GPIO pins */ CMU_ClockEnable(cmuClock_GPIO, true); /* To avoid false start, configure output as high */ GPIO_PinModeSet(RETARGET_TXPORT, RETARGET_TXPIN, gpioModePushPull, 1); GPIO_PinModeSet(RETARGET_RXPORT, RETARGET_RXPIN, gpioModeInput, 0); #if defined(RETARGET_USART) USART_TypeDef *usart = RETARGET_UART; USART_InitAsync_TypeDef init = USART_INITASYNC_DEFAULT; /* Enable DK RS232/UART switch */ RETARGET_PERIPHERAL_ENABLE(); CMU_ClockEnable(RETARGET_CLK, true); /* Configure USART for basic async operation */ init.enable = usartDisable; USART_InitAsync(usart, &init); /* Enable pins at correct UART/USART location. */ #if defined( USART_ROUTEPEN_RXPEN ) usart->ROUTEPEN = USART_ROUTEPEN_RXPEN | USART_ROUTEPEN_TXPEN; usart->ROUTELOC0 = ( usart->ROUTELOC0 & ~( _USART_ROUTELOC0_TXLOC_MASK | _USART_ROUTELOC0_RXLOC_MASK ) ) | ( RETARGET_TX_LOCATION << _USART_ROUTELOC0_TXLOC_SHIFT ) | ( RETARGET_RX_LOCATION << _USART_ROUTELOC0_RXLOC_SHIFT ); #else usart->ROUTE = USART_ROUTE_RXPEN | USART_ROUTE_TXPEN | RETARGET_LOCATION; #endif /* Clear previous RX interrupts */ USART_IntClear(RETARGET_UART, USART_IF_RXDATAV); NVIC_ClearPendingIRQ(RETARGET_IRQn); /* Enable RX interrupts */ USART_IntEnable(RETARGET_UART, USART_IF_RXDATAV); NVIC_EnableIRQ(RETARGET_IRQn); /* Finally enable it */ USART_Enable(usart, usartEnable); #else LEUART_TypeDef *leuart = RETARGET_UART; LEUART_Init_TypeDef init = LEUART_INIT_DEFAULT; /* Enable DK LEUART/RS232 switch */ RETARGET_PERIPHERAL_ENABLE(); /* Enable CORE LE clock in order to access LE modules */ CMU_ClockEnable(cmuClock_CORELE, true); #if defined(RETARGET_VCOM) /* Select HFXO/2 for LEUARTs (and wait for it to stabilize) */ CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_CORELEDIV2); #else /* Select LFXO for LEUARTs (and wait for it to stabilize) */ CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_LFXO); #endif CMU_ClockEnable(RETARGET_CLK, true); /* Do not prescale clock */ CMU_ClockDivSet(RETARGET_CLK, cmuClkDiv_1); /* Configure LEUART */ init.enable = leuartDisable; #if defined(RETARGET_VCOM) init.baudrate = 115200; #endif LEUART_Init(leuart, &init); /* Enable pins at default location */ leuart->ROUTE = LEUART_ROUTE_RXPEN | LEUART_ROUTE_TXPEN | RETARGET_LOCATION; /* Clear previous RX interrupts */ LEUART_IntClear(RETARGET_UART, LEUART_IF_RXDATAV); NVIC_ClearPendingIRQ(RETARGET_IRQn); /* Enable RX interrupts */ LEUART_IntEnable(RETARGET_UART, LEUART_IF_RXDATAV); NVIC_EnableIRQ(RETARGET_IRQn); /* Finally enable it */ LEUART_Enable(leuart, leuartEnable); #endif #if !defined(__CROSSWORKS_ARM) && defined(__GNUC__) setvbuf(stdout, NULL, _IONBF, 0); /*Set unbuffered mode for stdout (newlib)*/ #endif initialized = true; }
void uart_write(uart_t uart, const uint8_t *data, size_t len) { switch(uart) { #if UART_0_EN case UART_0: #if UART_0_ENABLE_BUF for(int count = 0; count < len; count++) { NVIC_DisableIRQ(UART_0_IRQ_TX_CHAN); ringbuffer_add_one(&rb_uart0, data[count]); NVIC_EnableIRQ(UART_0_IRQ_TX_CHAN); } USART_IntEnable(UART_0_DEV, USART_IF_TXBL); #else for(size_t i = 0; i < len; i++) { /* Check that transmit buffer is empty */ while(!(UART_0_DEV->STATUS & USART_STATUS_TXBL)) ; /* Write data to buffer */ UART_0_DEV->TXDATA = (uint32_t)data[i]; } #endif break; #endif #if UART_1_EN case UART_1: #if UART_1_ENABLE_BUF for(int count = 0; count < len; count++) { NVIC_DisableIRQ(UART_1_IRQ_TX_CHAN); ringbuffer_add_one(&rb_uart1, data[count]); NVIC_EnableIRQ(UART_1_IRQ_TX_CHAN); } USART_IntEnable(UART_1_DEV, USART_IF_TXBL); #else for(size_t i = 0; i < len; i++) { /* Check that transmit buffer is empty */ while(!(UART_1_DEV->STATUS & USART_STATUS_TXBL)) ; /* Write data to buffer */ UART_1_DEV->TXDATA = (uint32_t)data[i]; } #endif break; #endif #if UART_2_EN case UART_2: #if UART_2_ENABLE_BUF for(int count = 0; count < len; count++) { NVIC_DisableIRQ(UART_2_IRQ); ringbuffer_add_one(&rb_uart2, data[count]); NVIC_EnableIRQ(UART_2_IRQ); } LEUART_IntEnable(UART_2_DEV, LEUART_IF_TXBL); #else for(size_t i = 0; i < len; i++) { /* Check that transmit buffer is empty */ while (!(UART_2_DEV->STATUS & LEUART_STATUS_TXBL)) ; /* Avoid deadlock if modifying the same register twice when freeze mode is */ /* activated. */ if (!(UART_2_DEV->FREEZE & LEUART_FREEZE_REGFREEZE)) { /* Wait for any pending previous write operation to have been completed */ /* in low frequency domain */ while (UART_2_DEV->SYNCBUSY & LEUART_SYNCBUSY_TXDATA); ; UART_2_DEV->TXDATA = (uint32_t)data[i]; } } #endif break; #endif } }