diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2019-06-29 18:48:05 +0200 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2019-06-29 18:48:05 +0200 |
commit | cc0301784156543c7c9bec36b6f42df1d2adba28 (patch) | |
tree | 02b0d45518bfc53bafdf011320d4309b7f218ba0 /src/common/GPIO/usart.c | |
parent | f19631d2a66d01c0cdd85134c5eb63a1da42b34a (diff) | |
download | glutte-o-matic-cc0301784156543c7c9bec36b6f42df1d2adba28.tar.gz glutte-o-matic-cc0301784156543c7c9bec36b6f42df1d2adba28.tar.bz2 glutte-o-matic-cc0301784156543c7c9bec36b6f42df1d2adba28.zip |
Change common/ folder structure
Diffstat (limited to 'src/common/GPIO/usart.c')
-rw-r--r-- | src/common/GPIO/usart.c | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/src/common/GPIO/usart.c b/src/common/GPIO/usart.c new file mode 100644 index 0000000..8bcd80a --- /dev/null +++ b/src/common/GPIO/usart.c @@ -0,0 +1,171 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Matthias P. Braendli, Maximilien Cuony + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. +*/ + +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <inttypes.h> +#include "Core/common.h" +#include "GPIO/usart.h" +#include "GPIO/analog.h" +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +// The ISR writes into this buffer +static char nmea_sentence[MAX_NMEA_SENTENCE_LEN]; +static int nmea_sentence_last_written = 0; + + +// Once a completed NMEA sentence is received in the ISR, +// it is appended to this queue +static QueueHandle_t usart_nmea_queue; + +void usart_gps_init() { + usart_nmea_queue = xQueueCreate(15, MAX_NMEA_SENTENCE_LEN); + if (usart_nmea_queue == 0) { + while(1); /* fatal error */ + } + + usart_gps_specific_init(); + +} + +void usart_gps_puts(const char* str) { + vTaskSuspendAll(); + usart_puts(USART3, str); + xTaskResumeAll(); +} + +#define MAX_MSG_LEN 80 +static char usart_debug_message[MAX_MSG_LEN]; + +void usart_debug_timestamp() { + // Don't call printf here, to reduce stack usage + uint64_t now = timestamp_now(); + if (now == 0) { + usart_puts(USART2, "[0] "); + } + else { + char ts_str[64]; + int i = 63; + + ts_str[i--] = '\0'; + ts_str[i--] = ' '; + ts_str[i--] = ']'; + + while (now > 0 && i >= 0) { + ts_str[i--] = '0' + (now % 10); + now /= 10; + } + ts_str[i] = '['; + + usart_puts(USART2, &ts_str[i]); + } +} + +void usart_debug(const char *format, ...) { + va_list list; + va_start(list, format); + vsnprintf(usart_debug_message, MAX_MSG_LEN-1, format, list); + + vTaskSuspendAll(); + usart_debug_timestamp(); + usart_puts(USART2, usart_debug_message); + xTaskResumeAll(); + + va_end(list); +} + +void usart_debug_puts(const char* str) { +#ifdef SIMULATOR + fprintf(stderr, "DEBUG: %s", str); +#endif + vTaskSuspendAll(); + usart_debug_timestamp(); + usart_puts(USART2, str); + xTaskResumeAll(); +} + +void usart_debug_puts_header(const char* hdr, const char* str) { + vTaskSuspendAll(); + usart_debug_timestamp(); + usart_puts(USART2, hdr); + usart_puts(USART2, str); + usart_puts(USART2, "\r\n"); + xTaskResumeAll(); +} + +int usart_get_nmea_sentence(char* nmea) { + return xQueueReceive(usart_nmea_queue, nmea, portMAX_DELAY); +} + + +static void usart_clear_nmea_buffer(void) { + for (int i = 0; i < MAX_NMEA_SENTENCE_LEN; i++) { + nmea_sentence[i] = '\0'; + } + nmea_sentence_last_written = 0; +} + +void usart_process_char(char c) { +// Warning: running in interrupt context + usart_debug("Unknown command %c\r\n", c); +} + +void usart_gps_process_char(char c) +{ + BaseType_t require_context_switch = pdFALSE; + + if (nmea_sentence_last_written == 0) { + if (c == '$') { + // Likely new start of sentence + nmea_sentence[nmea_sentence_last_written] = c; + nmea_sentence_last_written++; + } + } + else if (nmea_sentence_last_written < MAX_NMEA_SENTENCE_LEN) { + nmea_sentence[nmea_sentence_last_written] = c; + nmea_sentence_last_written++; + + if (c == '\n') { + int success = xQueueSendToBackFromISR( + usart_nmea_queue, + nmea_sentence, + &require_context_switch); + + if (success == pdFALSE) { + trigger_fault(FAULT_SOURCE_USART); + } + + usart_clear_nmea_buffer(); + } + } + else { + // Buffer overrun without a meaningful NMEA message. + usart_clear_nmea_buffer(); + } + + portYIELD_FROM_ISR(require_context_switch); +} |