forked from ROMEO/obsw
z7 uart0 buffered read
This commit is contained in:
91
bsp_z7/hardware/uart.c
Normal file
91
bsp_z7/hardware/uart.c
Normal file
@ -0,0 +1,91 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
|
||||
#include <xscugic.h>
|
||||
#include <xuartps.h>
|
||||
|
||||
#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;
|
||||
}
|
Reference in New Issue
Block a user