Merge remote-tracking branch 'origin/mohr/rust' into nehlich/ffs

This commit is contained in:
paul nehlich
2024-07-26 12:53:39 +02:00
26 changed files with 513 additions and 110 deletions

View File

@ -1,4 +1,6 @@
add_subdirectory(freeRTOS)
add_subdirectory(ps7_cortexa9_0)
add_subdirectory(newlib)
add_subdirectory(hardware)
target_sources(${TARGET_NAME} PRIVATE main.c)

View File

@ -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. */

View File

@ -0,0 +1 @@
target_sources(${TARGET_NAME} PRIVATE interfaces.c uart.c)

View File

@ -0,0 +1,5 @@
#pragma once
int hw_interface_write(int fd, const char *ptr, int len);
int hw_interface_read(int fd, char *ptr, int len);

View File

@ -0,0 +1,7 @@
#pragma once
enum InterfaceFileDescriptors {
UART_0 = 3,
UART_1,
INTERFACE_FDS_NEXT
};

View File

@ -0,0 +1,73 @@
#include <hardware/interfaces.h>
#include <xparameters_ps.h>
#include <xuartps.h>
#include <stdint.h>
#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) {
for(int i = 0; i < chars_len; i++) {
if (c_string[i] == 0) {
return 0;
}
if (c_string[i] != chars[i]) {;
return 0;
}
}
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) {
return UART_1;
}
return -1;
}
ssize_t hw_device_transfer(int fd, void *sendbuffer, void *receivebuffer,
size_t buffer_len) {
return -1;
}
// 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 uart_send(uint32_t BaseAddress, const char *data, int data_len) {
int todo;
for (todo = 0; todo < data_len; todo++) {
XUartPs_SendByte(BaseAddress, *data++);
}
}
int hw_interface_write(int fd, const char *ptr, int len) {
enum InterfaceFileDescriptors fd_enum = fd;
switch (fd) {
case UART_0:
uart_send(XPS_UART0_BASEADDR, ptr, len);
return len;
case UART_1:
uart_send(XPS_UART1_BASEADDR, ptr, len);
return len;
}
return -1;
}
int hw_interface_read(int fd, char *ptr, int len) {
enum InterfaceFileDescriptors fd_enum = fd;
switch (fd) {
case UART_0:
return uart0_read(ptr,len);
case UART_1:
return 0;
}
return -1;
}

91
bsp_z7/hardware/uart.c Normal file
View 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
View File

@ -0,0 +1,4 @@
#pragma once
void uart0_enable_receiver();
int uart0_read(char *ptr, int len);

View File

@ -47,6 +47,10 @@ XScuGic xInterruptController;
extern SemaphoreHandle_t malloc_mutex;
int get_descriptor_rw() {
return 1;
}
/*-----------------------------------------------------------*/
void mission(void);

View File

@ -0,0 +1 @@
target_sources(${TARGET_NAME} PRIVATE close.c read.c write.c)

0
bsp_z7/newlib/close.c Normal file
View File

34
bsp_z7/newlib/read.c Normal file
View File

@ -0,0 +1,34 @@
#include "xil_printf.h"
#include "xparameters.h"
#include "../hardware/interface_access.h"
#include "../hardware/interface_fds.h"
// 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;
}

41
bsp_z7/newlib/write.c Normal file
View File

@ -0,0 +1,41 @@
#include "xil_printf.h"
#include "xparameters.h"
#include "../hardware/interface_access.h"
#include "../hardware/interface_fds.h"
// newlib offers a (weak) write implementation which
// is reentrant by calling _write_r which in turn
// relies on _write which we implement here.
// This way, we get a global, reentrant write implementation
// NOTE: This might be architecture dependent, so check your
// newlib implementation!
int _write(int fd, const char *ptr, int len) {
if (ptr == NULL) {
return 0;
}
// 0 is stdin, do not write to it
if (fd < 1) {
return -1; // TODO error
}
// we only support a single debug UART, so
// stdout and stderr are the same and go to the xiling stdout UART
// We output directely to avoid loops and allow debugging (not via a write)
if (fd < 3) {
int todo;
for (todo = 0; todo < len; todo++) {
outbyte(*ptr++);
}
return len;
}
if (fd < INTERFACE_FDS_NEXT) {
return hw_interface_write(fd, ptr, len);
}
// we do not have dynamic fds, so fd is invalid
return -1;
}

View File

@ -22,7 +22,7 @@ target_sources(${TARGET_NAME} PUBLIC
src/xil_testio.c
src/xplatform_info.c
src/getpid.c
src/write.c
#src/write.c
src/xil_mem.c
src/kill.c
src/xil_mmu.c
@ -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

View File

@ -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);
}