diff --git a/bsp_linux/CMakeLists.txt b/bsp_linux/CMakeLists.txt index 43c1760..86fefb8 100644 --- a/bsp_linux/CMakeLists.txt +++ b/bsp_linux/CMakeLists.txt @@ -1 +1,3 @@ +add_subdirectory(hardware) + target_sources(${TARGET_NAME} PRIVATE main.c) \ No newline at end of file diff --git a/bsp_linux/hardware/CMakeLists.txt b/bsp_linux/hardware/CMakeLists.txt new file mode 100644 index 0000000..8ca523c --- /dev/null +++ b/bsp_linux/hardware/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${TARGET_NAME} PRIVATE hardware.c) \ No newline at end of file diff --git a/bsp_linux/hardware/hardware.c b/bsp_linux/hardware/hardware.c new file mode 100644 index 0000000..973dcd6 --- /dev/null +++ b/bsp_linux/hardware/hardware.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +extern const char *device_root; + +int hw_device_open(const char *path, size_t path_len) { + int sock; + if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { + perror(NULL); + exit(-1); + } + struct sockaddr_un address; + address.sun_family = AF_UNIX; + snprintf(address.sun_path, sizeof(address.sun_path), "%s%.*s", device_root, + path_len, path); + if (connect(sock, (struct sockaddr *)&address, sizeof(address)) != 0) { + perror(NULL); + exit(-1); + } + return sock; +} \ No newline at end of file diff --git a/bsp_linux/main.c b/bsp_linux/main.c index d884385..4b81135 100644 --- a/bsp_linux/main.c +++ b/bsp_linux/main.c @@ -1,25 +1,52 @@ -#include +#include +#include #include +#include #include +#include +#include +#include +#include + +const char *device_root = "./"; void mission(void); +int get_descriptor_rw() { return 1; } + void done() { - printf("done."); + printf("done.\n"); exit(0); } +int test_socket(); + // Don't ask me, it makes the linker happy and does not seem // to break anything ¯\_(ツ)_/¯ -void rust_eh_personality() { - puts("eh_personality"); -} +void rust_eh_personality() { puts("eh_personality"); } -void outbyte(uint8_t byte){ - printf("%c", byte); -} - -int main(void) { - mission(); - return 0; +int main(int argc, char **argv) { + static struct option long_options[] = { + /* NAME ARGUMENT FLAG SHORTNAME */ + {"device-root", required_argument, NULL, 'd'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0}}; + int c; + int option_index = 0; + while ((c = getopt_long(argc, argv, "hd:", long_options, &option_index)) != + -1) { + switch (c) { + case 'd': + if (optarg != NULL) { + device_root = optarg; + break; + default: + fprintf(stderr, "Usage: %s -d device-root\n", argv[0]); + exit(EXIT_FAILURE); + } + } + } + + mission(); + return 0; } \ No newline at end of file diff --git a/bsp_z7/CMakeLists.txt b/bsp_z7/CMakeLists.txt index b6edbd2..c3ab00e 100644 --- a/bsp_z7/CMakeLists.txt +++ b/bsp_z7/CMakeLists.txt @@ -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) diff --git a/bsp_z7/freeRTOS/FreeRTOSConfig.h b/bsp_z7/freeRTOS/FreeRTOSConfig.h index e667c02..8c01db6 100644 --- a/bsp_z7/freeRTOS/FreeRTOSConfig.h +++ b/bsp_z7/freeRTOS/FreeRTOSConfig.h @@ -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. */ diff --git a/bsp_z7/hardware/CMakeLists.txt b/bsp_z7/hardware/CMakeLists.txt new file mode 100644 index 0000000..e7befc2 --- /dev/null +++ b/bsp_z7/hardware/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${TARGET_NAME} PRIVATE interfaces.c uart.c) \ No newline at end of file diff --git a/bsp_z7/hardware/interface_access.h b/bsp_z7/hardware/interface_access.h new file mode 100644 index 0000000..5578958 --- /dev/null +++ b/bsp_z7/hardware/interface_access.h @@ -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); \ No newline at end of file diff --git a/bsp_z7/hardware/interface_fds.h b/bsp_z7/hardware/interface_fds.h new file mode 100644 index 0000000..d0ff4a9 --- /dev/null +++ b/bsp_z7/hardware/interface_fds.h @@ -0,0 +1,7 @@ +#pragma once + +enum InterfaceFileDescriptors { + UART_0 = 3, + UART_1, + INTERFACE_FDS_NEXT +}; \ No newline at end of file diff --git a/bsp_z7/hardware/interfaces.c b/bsp_z7/hardware/interfaces.c new file mode 100644 index 0000000..165ad14 --- /dev/null +++ b/bsp_z7/hardware/interfaces.c @@ -0,0 +1,73 @@ +#include +#include +#include +#include + +#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; +} \ No newline at end of file diff --git a/bsp_z7/hardware/uart.c b/bsp_z7/hardware/uart.c new file mode 100644 index 0000000..bfec1f1 --- /dev/null +++ b/bsp_z7/hardware/uart.c @@ -0,0 +1,91 @@ +#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; +} \ No newline at end of file diff --git a/bsp_z7/hardware/uart.h b/bsp_z7/hardware/uart.h new file mode 100644 index 0000000..f1da8f7 --- /dev/null +++ b/bsp_z7/hardware/uart.h @@ -0,0 +1,4 @@ +#pragma once + +void uart0_enable_receiver(); +int uart0_read(char *ptr, int len); \ No newline at end of file diff --git a/bsp_z7/main.c b/bsp_z7/main.c index 0dbb160..39cf8d6 100644 --- a/bsp_z7/main.c +++ b/bsp_z7/main.c @@ -47,6 +47,10 @@ XScuGic xInterruptController; extern SemaphoreHandle_t malloc_mutex; +int get_descriptor_rw() { + return 1; +} + /*-----------------------------------------------------------*/ void mission(void); diff --git a/bsp_z7/newlib/CMakeLists.txt b/bsp_z7/newlib/CMakeLists.txt new file mode 100644 index 0000000..d8479a2 --- /dev/null +++ b/bsp_z7/newlib/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${TARGET_NAME} PRIVATE close.c read.c write.c) \ No newline at end of file diff --git a/bsp_z7/newlib/close.c b/bsp_z7/newlib/close.c new file mode 100644 index 0000000..e69de29 diff --git a/bsp_z7/newlib/read.c b/bsp_z7/newlib/read.c new file mode 100644 index 0000000..c76c6d9 --- /dev/null +++ b/bsp_z7/newlib/read.c @@ -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; +} \ No newline at end of file diff --git a/bsp_z7/newlib/write.c b/bsp_z7/newlib/write.c new file mode 100644 index 0000000..e388653 --- /dev/null +++ b/bsp_z7/newlib/write.c @@ -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; +} \ No newline at end of file diff --git a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/CMakeLists.txt b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/CMakeLists.txt index 416de1f..daa92ab 100644 --- a/bsp_z7/ps7_cortexa9_0/libsrc/standalone/CMakeLists.txt +++ b/bsp_z7/ps7_cortexa9_0/libsrc/standalone/CMakeLists.txt @@ -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 diff --git a/bsp_z7/testIp.c b/bsp_z7/testIp.c index 250b35e..786918b 100644 --- a/bsp_z7/testIp.c +++ b/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); -// } \ No newline at end of file + // 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); +} \ No newline at end of file diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index f513753..e76b650 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -1,3 +1 @@ -target_sources( - ${TARGET_NAME} PRIVATE - printChar.c) \ No newline at end of file +target_include_directories(${TARGET_NAME} PRIVATE include) \ No newline at end of file diff --git a/common/include/hardware/interfaces.h b/common/include/hardware/interfaces.h new file mode 100644 index 0000000..c01f920 --- /dev/null +++ b/common/include/hardware/interfaces.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include + +/** + * Access to hardware interfaces local to the machine the code is running on. + * + * The file descriptor returned by hw_decvice_open() is to be used by the standard + * read/write calls and to be closed by close(). + * + * For some specific hardware interfaces specific transactional calls are provided here + * to increase realtime performance. + * + * So far the only example is an SPI interface, which performs synchronous transfers of + * n bytes in, n bytes out. If a write call is performed on such an interface, the number + * of bytes transfered equals the size of the hardware send buffer. For a read() call, the + * bytes contained in the hardware's receive buffer are returned. + */ + +/** + * open a hardware device + * + * if successful, returns a file descriptor to be used with read/write/transfer/close calls + * otherwise returns -1 + */ +int hw_device_open(const char * path, size_t path_len); + +/** + * Perform a transfer of buffer_len bytes in and out. + * + * sendbuffer and receivebuffer may be equal, where received bytes overwrite + * send bytes. + * + * returns actual number of bytes transfered + */ +ssize_t hw_device_transfer(int fd, void* sendbuffer, void* receivebuffer, size_t buffer_len); \ No newline at end of file diff --git a/common/printChar.c b/common/printChar.c deleted file mode 100644 index d5cc34c..0000000 --- a/common/printChar.c +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include - -void printChar(const char* character, bool errStream) { - if (errStream) { - fprintf(stderr, "%c", *character); - } else { - printf("%c", *character); - } -} diff --git a/mission/mission.c b/mission/mission.c index 76617b9..ce14781 100644 --- a/mission/mission.c +++ b/mission/mission.c @@ -9,6 +9,24 @@ void rust_main(); +#include +#include + +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,6 +45,8 @@ void init_task(void *) { vTaskDelete(NULL); } + + void mission(void) { int taskParameters = 0; diff --git a/mission_rust/Cargo.toml b/mission_rust/Cargo.toml index d39fbfe..78f6b6b 100644 --- a/mission_rust/Cargo.toml +++ b/mission_rust/Cargo.toml @@ -10,8 +10,4 @@ crate-type = ["staticlib"] panic = 'abort' [profile.release] -panic = 'abort' - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] +panic = 'abort' \ No newline at end of file diff --git a/mission_rust/src/fsrc/sif.rs b/mission_rust/src/fsrc/sif.rs index f56438b..ec31dc1 100644 --- a/mission_rust/src/fsrc/sif.rs +++ b/mission_rust/src/fsrc/sif.rs @@ -1,37 +1,76 @@ // TODO this is platform specific -pub struct Outbytes {} +pub struct Stdout {} +pub struct Stderr {} use core::fmt::{Error, Write}; -impl Write for Outbytes { +extern "C" { + pub fn write(fd: core::ffi::c_int, buffer: *const core::ffi::c_void, count: usize) -> core::ffi::c_int; +} + +impl Write for Stdout { fn write_str(&mut self, s: &str) -> Result<(), Error> { - for c in s.as_bytes() { - unsafe { - crate::fsrc::osal::outbyte(*c); - } + + // Safe because write will only read the pointer an then return + let result = unsafe { + write( + 1, + s.as_bytes().as_ptr() as *const core::ffi::c_void, + s.as_bytes().len(), + ) + }; + // We do not retry incomplete writes, this is stdout after all... + let safe_count: i32 = match s.as_bytes().len().try_into() { + Ok(count)=> count, + Err(_) => return Err(Error) + }; + if result < safe_count { + Err(Error) + } else { + Ok(()) + } + } +} + +impl Write for Stderr { + fn write_str(&mut self, s: &str) -> Result<(), Error> { + + // Safe because write will only read the pointer an then return + let result = unsafe { + write( + 2, + s.as_bytes().as_ptr() as *const core::ffi::c_void, + s.as_bytes().len(), + ) + }; + // We do not retry incomplete writes, this is stdout after all... + let safe_count: i32 = match s.as_bytes().len().try_into() { + Ok(count)=> count, + Err(_) => return Err(Error) + }; + if result < safe_count { + Err(Error) + } else { + Ok(()) } - Ok(()) } } #[macro_export] macro_rules! sifln { ($(,)?) => ( - let mut stdout = Outbytes {}; - writeln!(stdout); + //let mut stdout = Outbytes {}; + writeln!(Stdout {}); ); ($($arg:tt)*) => ( - let mut stdout = crate::fsrc::sif::Outbytes {}; - let _alwaysok = writeln!(stdout, $($arg)*); + let _alwaysok = writeln!(crate::fsrc::sif::Stdout {}, $($arg)*); ); } #[macro_export] macro_rules! sif { ($($arg:tt)*) => ( - let mut stdout = crate::fsrc::sif::Outbytes {}; - let _alwaysok = write!(stdout, $($arg)*); + let _alwaysok = write!(crate::fsrc::sif::Stdout {}, $($arg)*); ); } - diff --git a/mission_rust/src/lib.rs b/mission_rust/src/lib.rs index c566f70..9737506 100644 --- a/mission_rust/src/lib.rs +++ b/mission_rust/src/lib.rs @@ -20,9 +20,9 @@ fn panic(panic: &PanicInfo<'_>) -> ! { unsafe { osal::stop_it(); } - // TODO: Make this unicode-safe - sifln!(""); - sif!("in task \""); + // TODO: Make this unicode-safe + _ = writeln!(crate::fsrc::sif::Stderr {},""); + _ = write!(crate::fsrc::sif::Stderr {},"in task \""); unsafe { //TODO is from_ptr safe enough? let task_name = core::ffi::CStr::from_ptr(osal::get_task_name()); @@ -32,12 +32,12 @@ fn panic(panic: &PanicInfo<'_>) -> ! { sif!("{}", string); } Err(_) => { - sif!("Schei� Encoding"); + _ = writeln!(crate::fsrc::sif::Stderr {},"Schei� Encoding"); } } } - sifln!("\":"); - sifln!("{}", panic); + _ = writeln!(crate::fsrc::sif::Stderr {},"\":"); + _ = writeln!(crate::fsrc::sif::Stderr {},"{}", panic); //TODO: stop RTOS, exit if hosted unsafe { done() }; loop {} @@ -59,7 +59,7 @@ extern "C" fn rust_assert_called(ptr: *const core::ffi::c_char, line: core::ffi: } }; - panic!("assertion failed at {file_name}:{}", line); + panic!("assertion failed at {file_name}:{line}"); } #[no_mangle]