forked from ROMEO/obsw
z7 uart0 buffered read
This commit is contained in:
parent
cbe8184fab
commit
926ef26000
@ -89,7 +89,7 @@
|
||||
#define configUSE_APPLICATION_TASK_TAG 0
|
||||
#define configUSE_COUNTING_SEMAPHORES 1
|
||||
#define configUSE_QUEUE_SETS 1
|
||||
#define configSUPPORT_STATIC_ALLOCATION 0
|
||||
#define configSUPPORT_STATIC_ALLOCATION 1
|
||||
#define configSUPPORT_DYNAMIC_ALLOCATION 1
|
||||
|
||||
/* Include the query-heap CLI command to query the free heap space. */
|
||||
|
@ -1 +1 @@
|
||||
target_sources(${TARGET_NAME} PRIVATE interfaces.c)
|
||||
target_sources(${TARGET_NAME} PRIVATE interfaces.c uart.c)
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "interface_access.h"
|
||||
#include "interface_fds.h"
|
||||
#include "uart.h"
|
||||
|
||||
int compare_string_chars(const char *c_string, const char *chars,
|
||||
size_t chars_len) {
|
||||
@ -19,8 +20,10 @@ int compare_string_chars(const char *c_string, const char *chars,
|
||||
return 1;
|
||||
}
|
||||
|
||||
//TODO no dual open
|
||||
int hw_device_open(const char *path, size_t path_len) {
|
||||
if (compare_string_chars("uart0", path, path_len) == 1) {
|
||||
uart0_enable_receiver();
|
||||
return UART_0;
|
||||
}
|
||||
if (compare_string_chars("uart1", path, path_len) == 1) {
|
||||
@ -38,7 +41,7 @@ ssize_t hw_device_transfer(int fd, void *sendbuffer, void *receivebuffer,
|
||||
// we could implement interrupt based nonblocking sending using a queue
|
||||
// like we do receiving (where we need it for the small hw buffer)
|
||||
// but in the end, we do not want too many interrupts, so we do it blocking
|
||||
void send_uart(uint32_t BaseAddress, const char *data, int data_len) {
|
||||
void uart_send(uint32_t BaseAddress, const char *data, int data_len) {
|
||||
int todo;
|
||||
for (todo = 0; todo < data_len; todo++) {
|
||||
XUartPs_SendByte(BaseAddress, *data++);
|
||||
@ -49,10 +52,10 @@ int hw_interface_write(int fd, const char *ptr, int len) {
|
||||
enum InterfaceFileDescriptors fd_enum = fd;
|
||||
switch (fd) {
|
||||
case UART_0:
|
||||
send_uart(XPS_UART0_BASEADDR, ptr, len);
|
||||
uart_send(XPS_UART0_BASEADDR, ptr, len);
|
||||
return len;
|
||||
case UART_1:
|
||||
send_uart(XPS_UART1_BASEADDR, ptr, len);
|
||||
uart_send(XPS_UART1_BASEADDR, ptr, len);
|
||||
return len;
|
||||
}
|
||||
return -1;
|
||||
@ -62,7 +65,7 @@ int hw_interface_read(int fd, char *ptr, int len) {
|
||||
enum InterfaceFileDescriptors fd_enum = fd;
|
||||
switch (fd) {
|
||||
case UART_0:
|
||||
return 0;
|
||||
return uart0_read(ptr,len);
|
||||
case UART_1:
|
||||
return 0;
|
||||
}
|
||||
|
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;
|
||||
}
|
4
bsp_z7/hardware/uart.h
Normal file
4
bsp_z7/hardware/uart.h
Normal file
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
void uart0_enable_receiver();
|
||||
int uart0_read(char *ptr, int len);
|
@ -1,5 +1,34 @@
|
||||
#include "xil_printf.h"
|
||||
#include "xparameters.h"
|
||||
|
||||
#include "../hardware/interface_access.h"
|
||||
#include "../hardware/interface_fds.h"
|
||||
|
||||
int _read(int file, char *ptr, int len) {
|
||||
return 0;
|
||||
// newlib offers a (weak) write implementation which
|
||||
// is reentrant by calling _read_r which in turn
|
||||
// relies on _read which we implement here.
|
||||
// This way, we get a global, reentrant read implementation
|
||||
// NOTE: This might be architecture dependent, so check your
|
||||
// newlib implementation!
|
||||
int _read(int fd, char *ptr, int len) {
|
||||
if (ptr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 0 is stdin, TODO: do we support it?
|
||||
if (fd < 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// stdout and stderr
|
||||
if (fd < 3) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fd < INTERFACE_FDS_NEXT) {
|
||||
return hw_interface_read(fd, ptr, len);
|
||||
}
|
||||
|
||||
// we do not have dynamic fds, so fd is invalid
|
||||
return -1;
|
||||
}
|
@ -22,7 +22,7 @@ int _write(int fd, const char *ptr, int len) {
|
||||
}
|
||||
// we only support a single debug UART, so
|
||||
// stdout and stderr are the same and go to the xiling stdout UART
|
||||
// TODO switch to a hw_interface_write() instead?
|
||||
// We output directely to avoid loops and allow debugging (not via a write)
|
||||
if (fd < 3) {
|
||||
int todo;
|
||||
|
||||
|
@ -31,8 +31,8 @@ target_sources(${TARGET_NAME} PUBLIC
|
||||
src/getentropy.c
|
||||
src/xil_testmem.c
|
||||
src/isatty.c
|
||||
src/read.c
|
||||
src/inbyte.c
|
||||
#src/read.c
|
||||
#src/inbyte.c
|
||||
src/close.c
|
||||
src/xil_sleeptimer.c
|
||||
src/print.c
|
||||
|
110
bsp_z7/testIp.c
110
bsp_z7/testIp.c
@ -160,71 +160,71 @@ static const uint16_t stackSizeWords = 512;
|
||||
StaticTask_t xTaskBuffer;
|
||||
StackType_t xStack[512];
|
||||
|
||||
// void testIp() {
|
||||
void testIp() {
|
||||
|
||||
// uartIsrQueue =
|
||||
// xQueueCreateStatic(QUEUE_LENGTH, 1, ucQueueStorageArea, &xStaticQueue);
|
||||
uartIsrQueue =
|
||||
xQueueCreateStatic(QUEUE_LENGTH, 1, ucQueueStorageArea, &xStaticQueue);
|
||||
|
||||
// lwip_init();
|
||||
lwip_init();
|
||||
|
||||
// ip4_addr_t slip_addr = {PP_HTONL(LWIP_MAKEU32(10, 0, 0, 32))},
|
||||
// slip_mask = {PP_HTONL(LWIP_MAKEU32(255, 255, 255, 0))},
|
||||
// slip_gw = {PP_HTONL(LWIP_MAKEU32(10, 0, 0, 1))};
|
||||
ip4_addr_t slip_addr = {PP_HTONL(LWIP_MAKEU32(10, 0, 0, 32))},
|
||||
slip_mask = {PP_HTONL(LWIP_MAKEU32(255, 255, 255, 0))},
|
||||
slip_gw = {PP_HTONL(LWIP_MAKEU32(10, 0, 0, 1))};
|
||||
|
||||
// netif_add(&netif, &slip_addr, &slip_mask, &slip_gw, NULL, slipif_init,
|
||||
// netif_input);
|
||||
netif_add(&netif, &slip_addr, &slip_mask, &slip_gw, NULL, slipif_init,
|
||||
netif_input);
|
||||
|
||||
// netif_set_default(&netif);
|
||||
// // should be done by driver, which does not do it, so we do it here
|
||||
// netif_set_link_up(&netif);
|
||||
// netif_set_up(&netif);
|
||||
netif_set_default(&netif);
|
||||
// should be done by driver, which does not do it, so we do it here
|
||||
netif_set_link_up(&netif);
|
||||
netif_set_up(&netif);
|
||||
|
||||
// udpecho_raw_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
|
||||
// if (udpecho_raw_pcb != NULL) {
|
||||
// err_t err;
|
||||
udpecho_raw_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
|
||||
if (udpecho_raw_pcb != NULL) {
|
||||
err_t err;
|
||||
|
||||
// err = udp_bind(udpecho_raw_pcb, IP_ANY_TYPE, 7);
|
||||
// if (err == ERR_OK) {
|
||||
// udp_recv(udpecho_raw_pcb, udpecho_raw_recv, NULL);
|
||||
// } else {
|
||||
// /* TODO */
|
||||
// }
|
||||
// } else {
|
||||
// /* TODO */
|
||||
// }
|
||||
err = udp_bind(udpecho_raw_pcb, IP_ANY_TYPE, 7);
|
||||
if (err == ERR_OK) {
|
||||
udp_recv(udpecho_raw_pcb, udpecho_raw_recv, NULL);
|
||||
} else {
|
||||
/* TODO */
|
||||
}
|
||||
} else {
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
// /* Install the UART Interrupt handler. */
|
||||
// BaseType_t xStatus =
|
||||
// XScuGic_Connect(&xInterruptController, STDIN_INT_NR,
|
||||
// (Xil_ExceptionHandler)handleUARTInt, NULL);
|
||||
// configASSERT(xStatus == XST_SUCCESS);
|
||||
// (void)xStatus; /* Remove compiler warning if configASSERT() is not defined. */
|
||||
/* Install the UART Interrupt handler. */
|
||||
BaseType_t xStatus =
|
||||
XScuGic_Connect(&xInterruptController, STDIN_INT_NR,
|
||||
(Xil_ExceptionHandler)handleUARTInt, 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(STDIN_BASEADDRESS, XUARTPS_RXWM_OFFSET, 62);
|
||||
// Set trigger level to 62 of 64 bytes, giving interrupt some time to react
|
||||
XUartPs_WriteReg(STDIN_BASEADDRESS, XUARTPS_RXWM_OFFSET, 62);
|
||||
|
||||
// // Setting the rx timeout to n*4 -1 bits
|
||||
// XUartPs_WriteReg(STDIN_BASEADDRESS, XUARTPS_RXTOUT_OFFSET, 50);
|
||||
// Setting the rx timeout to n*4 -1 bits
|
||||
XUartPs_WriteReg(STDIN_BASEADDRESS, 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(STDIN_BASEADDRESS, XUARTPS_IER_OFFSET, mask);
|
||||
// /* Write the inverse of the Mask to the IDR register */
|
||||
// XUartPs_WriteReg(STDIN_BASEADDRESS, XUARTPS_IDR_OFFSET, (~mask));
|
||||
// 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(STDIN_BASEADDRESS, XUARTPS_IER_OFFSET, mask);
|
||||
/* Write the inverse of the Mask to the IDR register */
|
||||
XUartPs_WriteReg(STDIN_BASEADDRESS, XUARTPS_IDR_OFFSET, (~mask));
|
||||
|
||||
// /* Enable the interrupt for the UART1 in the interrupt controller. */
|
||||
// XScuGic_Enable(&xInterruptController, STDIN_INT_NR);
|
||||
/* Enable the interrupt for the UART1 in the interrupt controller. */
|
||||
XScuGic_Enable(&xInterruptController, STDIN_INT_NR);
|
||||
|
||||
// // Start lwip task
|
||||
// xTaskCreateStatic(
|
||||
// lwip_main, /* The function that implements the task. */
|
||||
// "lwip", /* The text name assigned to the task - for debug
|
||||
// only as it is not used by the kernel. */
|
||||
// stackSizeWords, /* The size of the stack to allocate to the task. */
|
||||
// NULL, /* The parameter passed to the task - not used in this
|
||||
// simple case. */
|
||||
// 4, /* The priority assigned to the task. */
|
||||
// xStack, &xTaskBuffer);
|
||||
// }
|
||||
// Start lwip task
|
||||
xTaskCreateStatic(
|
||||
lwip_main, /* The function that implements the task. */
|
||||
"lwip", /* The text name assigned to the task - for debug
|
||||
only as it is not used by the kernel. */
|
||||
stackSizeWords, /* The size of the stack to allocate to the task. */
|
||||
NULL, /* The parameter passed to the task - not used in this
|
||||
simple case. */
|
||||
4, /* The priority assigned to the task. */
|
||||
xStack, &xTaskBuffer);
|
||||
}
|
@ -9,6 +9,24 @@
|
||||
|
||||
void rust_main();
|
||||
|
||||
#include <hardware/interfaces.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void test_hardware() {
|
||||
int fd0 = hw_device_open("uart0", 5);
|
||||
write(fd0, "uart0\n", 6);
|
||||
int fd1 = hw_device_open("uart1", 5);
|
||||
write(fd1, "uart1\n", 6);
|
||||
|
||||
vTaskDelay(3000 / portTICK_PERIOD_MS);
|
||||
|
||||
uint8_t buffer[100];
|
||||
int read_bytes = read(fd0, buffer, sizeof(buffer));
|
||||
write(1, buffer, read_bytes);
|
||||
read_bytes = read(fd1, buffer, sizeof(buffer));
|
||||
write(1, buffer, read_bytes);
|
||||
}
|
||||
|
||||
// called to stop execution (either a panic or program ended)
|
||||
// to be implemented by bsp (do not return from it!)
|
||||
void done();
|
||||
@ -16,6 +34,8 @@ void done();
|
||||
void init_task(void *) {
|
||||
// printf("Starting Mission\n");
|
||||
|
||||
test_hardware();
|
||||
|
||||
rust_main();
|
||||
|
||||
// printf("Started Tasks, deleting init task\n");
|
||||
@ -25,14 +45,9 @@ void init_task(void *) {
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
#include <unistd.h>
|
||||
#include <hardware/interfaces.h>
|
||||
|
||||
|
||||
void mission(void) {
|
||||
int fd0 = hw_device_open("uart0", 5);
|
||||
write(fd0, "uart0\n", 6);
|
||||
int fd1 = hw_device_open("uart1", 5);
|
||||
write(fd1, "uart1\n", 6);
|
||||
|
||||
int taskParameters = 0;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user