diff --git a/applications/examples/uart_write.c b/applications/examples/uart_write.c index c660212394b..1025eeaaa87 100644 --- a/applications/examples/uart_write.c +++ b/applications/examples/uart_write.c @@ -19,7 +19,7 @@ void application_uart_write(void* p) { while(1) { // continously write it to UART - fuprintf(log, "counter: %d\n", counter); + printf("counter: %d\n", counter); counter++; // flash at every send diff --git a/core/tty_uart.c b/core/tty_uart.c index 4e10e880e20..e4e729d72a9 100644 --- a/core/tty_uart.c +++ b/core/tty_uart.c @@ -1,3 +1,5 @@ +#define _GNU_SOURCE +#include #include "furi.h" #include "main.h" @@ -7,14 +9,46 @@ void handle_uart_write(const void* data, size_t size, void* ctx) { HAL_UART_Transmit(&DEBUG_UART, (uint8_t*)data, (uint16_t)size, HAL_MAX_DELAY); } +static ssize_t stdout_write(void *_cookie, const char *buf, size_t n) { + FuriRecordSubscriber *log = pvTaskGetThreadLocalStoragePointer(NULL, 0); + if (log == NULL) { + log = furi_open("tty", false, false, NULL, NULL, NULL); + if (log == NULL) { + return -1; + } + vTaskSetThreadLocalStoragePointer(NULL, 0, log); + } + if (buf == 0) { + /* + * This means that we should flush internal buffers. Since we + * don't we just return. (Remember, "handle" == -1 means that all + * handles should be flushed.) + */ + return 0; + } + + furi_write(log, buf, n); + + return n; +} + bool register_tty_uart() { if(!furi_create("tty", NULL, 0)) { return false; } - + if(furi_open("tty", false, false, handle_uart_write, NULL, NULL) == NULL) { return false; } + FILE* fp = fopencookie(NULL, "w", (cookie_io_functions_t) { + .read = NULL, + .write = stdout_write, + .seek = NULL, + .close = NULL, + }); + setvbuf(fp, NULL, _IONBF, 0); + stdout = fp; + return true; -} \ No newline at end of file +} diff --git a/target_f1/Inc/FreeRTOSConfig.h b/target_f1/Inc/FreeRTOSConfig.h index 7b29e66cea0..085eb0c7977 100644 --- a/target_f1/Inc/FreeRTOSConfig.h +++ b/target_f1/Inc/FreeRTOSConfig.h @@ -68,6 +68,7 @@ #define configQUEUE_REGISTRY_SIZE 8 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #define configUSE_COUNTING_SEMAPHORES 1 +#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 1 /* Co-routine definitions. */ #define configUSE_CO_ROUTINES 0 diff --git a/target_f2/Inc/FreeRTOSConfig.h b/target_f2/Inc/FreeRTOSConfig.h index 7b29e66cea0..085eb0c7977 100644 --- a/target_f2/Inc/FreeRTOSConfig.h +++ b/target_f2/Inc/FreeRTOSConfig.h @@ -68,6 +68,7 @@ #define configQUEUE_REGISTRY_SIZE 8 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #define configUSE_COUNTING_SEMAPHORES 1 +#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 1 /* Co-routine definitions. */ #define configUSE_CO_ROUTINES 0 diff --git a/target_lo/Inc/cmsis_os.h b/target_lo/Inc/cmsis_os.h index e4bc7b66115..985e0e8bf09 100644 --- a/target_lo/Inc/cmsis_os.h +++ b/target_lo/Inc/cmsis_os.h @@ -74,3 +74,6 @@ BaseType_t xQueueSend( ); BaseType_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait); + +void* pvTaskGetThreadLocalStoragePointer(TaskHandle_t xTaskToQuery, BaseType_t xIndex); +void vTaskSetThreadLocalStoragePointer(TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue); diff --git a/target_lo/Src/lo_os.c b/target_lo/Src/lo_os.c index 240139f03ed..14d79f0ac97 100644 --- a/target_lo/Src/lo_os.c +++ b/target_lo/Src/lo_os.c @@ -195,4 +195,48 @@ BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore) { xSemaphore->give_counter++; return pdTRUE; -} \ No newline at end of file +} + +#define TLS_ITEM_COUNT 1 +static pthread_key_t tls_keys[TLS_ITEM_COUNT]; +static pthread_once_t tls_keys_once = PTHREAD_ONCE_INIT; + +static void create_tls_keys() { + for (size_t i = 0; i < TLS_ITEM_COUNT; i++) { + pthread_key_create(&tls_keys[i], NULL); + } +} + +void* pvTaskGetThreadLocalStoragePointer( + TaskHandle_t xTaskToQuery, BaseType_t xIndex +) { + // Non-current task TLS access is not allowed + if (xTaskToQuery != NULL) { + return NULL; + } + + if (xIndex >= TLS_ITEM_COUNT) { + return NULL; + } + + pthread_once(&tls_keys_once, create_tls_keys); + + return pthread_getspecific(tls_keys[xIndex]); +} + +void vTaskSetThreadLocalStoragePointer( + TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue +) { + // Non-current task TLS access is not allowed + if (xTaskToSet != NULL) { + return; + } + + if (xIndex >= TLS_ITEM_COUNT) { + return; + } + + pthread_once(&tls_keys_once, create_tls_keys); + + pthread_setspecific(tls_keys[xIndex], pvValue); +}