#include #include "FreeRTOS.h" #include "queue.h" #include #include #undef XUARTPS_IXR_RXOVR #define XUARTPS_IXR_RXOVR 0x00000020U /**< Rx Overrun error interrupt */ #define XUARTPS_IXR_RTRIG 0x00000001U /**< RX FIFO trigger interrupt. */ extern XScuGic xInterruptController; /* Interrupt controller instance */ uint8_t uart0_receive_buffer[1024 * 1]; StaticQueue_t uart0_static_queue; QueueHandle_t uart0_receive_queue; /** this is based on XUartPs_InterruptHandler() in xuartps_intr.c*/ void uart0_handle_interrupt(void *) { u32 IsrStatus; /* * Read the interrupt ID register to determine which * interrupt is active */ IsrStatus = XUartPs_ReadReg(XPS_UART0_BASEADDR, XUARTPS_IMR_OFFSET); IsrStatus &= XUartPs_ReadReg(XPS_UART0_BASEADDR, XUARTPS_ISR_OFFSET); // Onlx RX intterupts are enabled // We do not care which interrupt actually triggered, just get all bytes // available into the stack uint8_t RecievedByte; BaseType_t xHigherPriorityTaskWoken; while (XUartPs_IsReceiveData(STDIN_BASEADDRESS)) { RecievedByte = XUartPs_ReadReg(STDIN_BASEADDRESS, XUARTPS_FIFO_OFFSET); xQueueSendToBackFromISR(uart0_receive_queue, &RecievedByte, &xHigherPriorityTaskWoken); } /* Clear the interrupt status. */ XUartPs_WriteReg(STDIN_BASEADDRESS, XUARTPS_ISR_OFFSET, IsrStatus); /* directly yield if sending to the queue woke something in ourselves */ portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } void uart0_enable_receiver() { uart0_receive_queue = xQueueCreateStatic(sizeof(uart0_receive_buffer), 1, uart0_receive_buffer, &uart0_static_queue); /* Install the UART Interrupt handler. */ BaseType_t xStatus = XScuGic_Connect(&xInterruptController, XPAR_XUARTPS_0_INTR, (Xil_ExceptionHandler)uart0_handle_interrupt, NULL); configASSERT(xStatus == XST_SUCCESS); (void)xStatus; /* Remove compiler warning if configASSERT() is not defined. */ // Set trigger level to 62 of 64 bytes, giving interrupt some time to react XUartPs_WriteReg(XPS_UART0_BASEADDR, XUARTPS_RXWM_OFFSET, 62); // Setting the rx timeout to n*4 -1 bits XUartPs_WriteReg(XPS_UART0_BASEADDR, XUARTPS_RXTOUT_OFFSET, 50); // enable UART Interrupts u32 mask = XUARTPS_IXR_RTRIG | XUARTPS_IXR_RXOVR | XUARTPS_IXR_RXFULL | XUARTPS_IXR_TOUT; /* Write the mask to the IER Register */ XUartPs_WriteReg(XPS_UART0_BASEADDR, XUARTPS_IER_OFFSET, mask); /* Write the inverse of the Mask to the IDR register */ XUartPs_WriteReg(XPS_UART0_BASEADDR, XUARTPS_IDR_OFFSET, (~mask)); /* Enable the interrupt for the UART0 in the interrupt controller. */ XScuGic_Enable(&xInterruptController, XPAR_XUARTPS_0_INTR); } int uart0_read(char *ptr, int len) { int received = 0; while (len > 0) { BaseType_t result = xQueueReceive(uart0_receive_queue, ptr, 0); if (result == pdFAIL) { return received; } received++; ptr++; len--; } return received; }