Explorar o código

Merge pull request #114 from Flipper-Zero/printf

Implement transparent printf support
Vadim Kaushan %!s(int64=5) %!d(string=hai) anos
pai
achega
93cee4c37c

+ 1 - 1
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

+ 36 - 2
core/tty_uart.c

@@ -1,3 +1,5 @@
+#define _GNU_SOURCE
+#include <stdio.h>
 #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;
-}
+}

+ 1 - 0
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

+ 1 - 0
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

+ 3 - 0
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);

+ 45 - 1
target_lo/Src/lo_os.c

@@ -195,4 +195,48 @@ BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore) {
     xSemaphore->give_counter++;
 
     return pdTRUE;
-}
+}
+
+#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);
+}