X-Git-Url: http://rtime.felk.cvut.cz/gitweb/pes-rpp/rpp-lib.git/blobdiff_plain/ce401f9930e9c2ee1d69985fd38fd879b4a09586..6069f08dacbf9777736448efd22eb635e765e885:/rpp/src/rpp/sdr.c diff --git a/rpp/src/rpp/sdr.c b/rpp/src/rpp/sdr.c index e8c5693..8dd8ce7 100644 --- a/rpp/src/rpp/sdr.c +++ b/rpp/src/rpp/sdr.c @@ -1,24 +1,32 @@ -/* Copyright (C) 2013 Czech Technical University in Prague +/* Copyright (C) 2013, 2014, 2015 Czech Technical University in Prague * * Authors: * - Carlos Jenkins * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * 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: * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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. * * File : sdr.c * Abstract: - * SD-RAN logging RPP API implementation file. + * SD-RAM logging RPP API implementation file. * * References: * sdr.h @@ -27,30 +35,56 @@ #include "rpp/rpp.h" - -#if rppCONFIG_INCLUDE_SDR == 1 #include // vsnprintf() #include // isprint() #include // strncmp() #include // va_start, va_end -#if rppCONFIG_DRV == 1 +#ifndef FREERTOS_POSIX #include "drv/drv.h" -#elif defined(FREERTOS_POSIX) -#include // malloc() -#include "lib/os/rpp_support.c" +#define echo(x) rpp_sci_putc(x) +#else +#define echo(x) (void)(x) #endif -static const char* prompt = "--> "; -static const char* newline = "\r\n"; +static const char *prompt = "--> "; +static const char *newline = "\r\n"; + +// extern this semaphore to wait for cmdproc to exit +xSemaphoreHandle rpp_sdr_cmdproc_semaphore; /// Memory management variables ------------------------------------------------ static xSemaphoreHandle memory_mutex; static uint32_t memory_size = 0; -static uint8_t* memory_start = NULL; -static uint8_t* memory_end = NULL; -static uint8_t* memory_current = NULL; +static uint8_t *memory_start = NULL; +static uint8_t *memory_end = NULL; +static uint8_t *memory_current = NULL; + + + +/// Tasks control -------------------------------------------------------------- +// Task handle for command processor task +static xTaskHandle cmdproc_handle; + +// Task handle for log show task +static xTaskHandle show_handle; + +// Flag the request the tasks to stop +static boolean_t stop_tasks = FALSE; + +// Number of tasks running +static uint8_t tasks_running = 0; + +// Force context change to other tasks until all +// the tasks created by this module are deleted. +static void wait_tasks_to_finish() +{ + stop_tasks = TRUE; + while (tasks_running > 0) + taskYIELD(); + stop_tasks = FALSE; +} @@ -64,36 +98,42 @@ static boolean_t show_flushing = FALSE; // Show log task void rpp_sdr_showtask(void *p) { - uint8_t* current; - uint8_t byte; - - while(TRUE) { - - // Wait semaphore to start - xSemaphoreTake(show_semaphore, portMAX_DELAY); - current = memory_start; - - // Iterate until the end of the log - while(show_flushing && - (current != memory_current) && - (current < memory_end)) { // Just in case - - // Print characters in this memory location. - // Ignores non-printable characters except \r and \n - byte = *current; - if((byte == '\r') || (byte == '\n') || isprint(byte)) { - rpp_sci_putc(byte); - } - current++; - } - - // If user waited to finish - if(show_flushing) { - rpp_sci_printf((const char*)"%s", newline); - rpp_sci_printf((const char*)"%s", prompt); - show_flushing = FALSE; - } - } + uint8_t *current; + uint8_t byte; + + while (!stop_tasks) { + + // Wait semaphore to start + if (xSemaphoreTake(show_semaphore, 1) != pdTRUE) + // This will wake up each tick to check if + // deletion of this task was requested. + continue; + current = memory_start; + + // Iterate until the end of the log + while (show_flushing && + (current != memory_current) && + (current < memory_end)) { // Just in case + + // Print characters in this memory location. + // Ignores non-printable characters except \r and \n + byte = *current; + if ((byte == '\r') || (byte == '\n') || isprint(byte)) + rpp_sci_putc(byte); + current++; + } + + // If user waited to finish + if (show_flushing) { + rpp_sci_printf((const char *)"%s", newline); + rpp_sci_printf((const char *)"%s", prompt); + show_flushing = FALSE; + } + } + + // Delete myself + tasks_running--; + vTaskDelete(NULL); } @@ -107,112 +147,150 @@ static char in_buffer[BUF_SIZE]; // SCI log command processor task void rpp_sdr_cmdproc(void *p) { - rpp_sci_printf( - (const char*)"Log control: %dkB available.\r\n", - (rpp_sdr_available() / 1024) - ); - rpp_sci_printf( - (const char*)"========================================\r\n" - ); - rpp_sci_printf((const char*)"%s", prompt); - - uint8_t input = 0; - uint8_t buff_index = 0; - boolean_t flush = FALSE; - while(TRUE) { - - // Get one character from the user - if(rpp_sci_read_nb(1, &input) != SUCCESS) { - vTaskDelay(100 / portTICK_RATE_MS); - continue; - } - - // Stop flushing if one character is received - if(show_flushing) { - rpp_sdr_show(FALSE); - vTaskDelay(100 / portTICK_RATE_MS); - rpp_sci_printf("%s", newline); - rpp_sci_printf("%s", prompt); - continue; - } - - // Backspace and Delete - if(input == 8 || input == 127) { - if(buff_index > 0) { - buff_index--; - } - - // Line feed or Carriage return - } else if(input == 10 || input == 13) { - flush = TRUE; - - // If is any printable character - } else if(isprint(input)) { - - // Store character and increment buffer index - in_buffer[buff_index] = input; - buff_index++; - - // Check if buffer is full and force flush - if(buff_index == BUF_SIZE - 1) { - flush = TRUE; - } - } - // All other character are ignored - - // Flush buffer - if(flush) { - - // Terminate string - in_buffer[buff_index] = '\0'; - - - // Re-prompt - if(buff_index == 0) { - rpp_sci_printf("%s", newline); - rpp_sci_printf("%s", prompt); - - // Help command - } else if(strncmp(in_buffer, "help", BUF_SIZE) == 0) { - rpp_sci_printf((const char*) - "Available commands: \r\n" - " log\r\n" - " clear\r\n" - " available\r\n" - ); - - // Log command - } else if(strncmp(in_buffer, "log", BUF_SIZE) == 0) { - rpp_sdr_show(TRUE); - - // Clear command - } else if(strncmp(in_buffer, "clear", BUF_SIZE) == 0) { - rpp_sdr_clear(); - rpp_sci_printf((const char*)"Done.\r\n"); - rpp_sci_printf("%s", prompt); - - // Available command - } else if(strncmp(in_buffer, "available", BUF_SIZE) == 0) { - rpp_sci_printf( - (const char*)"%d kB of %d kB available.\r\n", - rpp_sdr_available() / 1024, - memory_size / 1024 - ); - - // Unknown command, print buffer back - } else { - rpp_sci_printf( - (const char*)"ERROR: Unknown command \"%s\"\r\n", - (char*)&in_buffer); - rpp_sci_printf("%s", prompt); - } - - // Reset variables - rpp_sci_flush(TRUE); - buff_index = 0; - flush = FALSE; - } - } + rpp_sci_printf((const char *) + "Log control: %dkB available.\r\n", + (rpp_sdr_available() / 1024) + ); + rpp_sci_printf((const char *) + "===========================================================\r\n" + ); + rpp_sci_printf((const char *)"%s", prompt); + + uint8_t input = 0; + uint8_t buff_index = 0; + boolean_t flush = FALSE; + while (!stop_tasks) { + + // Get one character from the user + if (rpp_sci_read_nb(1, &input) != SUCCESS) { + if (!stop_tasks) + vTaskDelay(50 / portTICK_RATE_MS); + continue; + } + + // Stop flushing if one character is received + if (show_flushing) { + rpp_sdr_show(FALSE); + vTaskDelay(100 / portTICK_RATE_MS); + rpp_sci_printf("%s", newline); + rpp_sci_printf("%s", prompt); + continue; + } + + // Backspace and Delete + if (input == 8 || input == 127) { + if (buff_index > 0) { + buff_index--; + echo('\b'); + echo(' ' ); + echo('\b'); + } + + // Line feed or Carriage return + } + else if (input == 10 || input == 13) { + flush = TRUE; + echo('\r'); + echo('\n'); + + // If is any printable character + } + else if (isprint(input)) { + + // Store character and increment buffer index + in_buffer[buff_index] = input; + buff_index++; + echo(input); + + // Check if buffer is full and force flush + if (buff_index == BUF_SIZE - 1) + flush = TRUE; + } + // All other character are ignored + + // Flush buffer + if (flush) { + + // Terminate string + in_buffer[buff_index] = '\0'; + + + // Re-prompt + if (buff_index == 0) { + rpp_sci_printf((const char *)"%s", newline); + rpp_sci_printf((const char *)"%s", prompt); + + } + // Help command + else if (strncmp(in_buffer, "help", BUF_SIZE) == 0) { + + rpp_sci_printf((const char *) + "Available commands:\r\n" + ); + rpp_sci_printf((const char *) + "\tlog - Show the log.\r\n" + ); + rpp_sci_printf((const char *) + "\tclear - Clear the log.\r\n" + ); + rpp_sci_printf((const char *) + "\tavailable - Display amount of memory left.\r\n" + ); + rpp_sci_printf((const char *) + "\texit - Exit this command processor.\r\n" + ); + + rpp_sci_printf((const char *)"%s", newline); + rpp_sci_printf((const char *)"%s", prompt); + } + // Log command + else if (strncmp(in_buffer, "log", BUF_SIZE) == 0) + rpp_sdr_show(TRUE); + + // Clear command + else if (strncmp(in_buffer, "clear", BUF_SIZE) == 0) { + rpp_sdr_clear(); + rpp_sci_printf((const char *)"Done.\r\n"); + rpp_sci_printf((const char *)"%s", newline); + rpp_sci_printf((const char *)"%s", prompt); + + } + // Available command + else if (strncmp(in_buffer, "available", BUF_SIZE) == 0) { + rpp_sci_printf( + (const char *)"%d kB of %d kB available.\r\n", + rpp_sdr_available() / 1024, + memory_size / 1024 + ); + rpp_sci_printf((const char *)"%s", newline); + rpp_sci_printf((const char *)"%s", prompt); + + } + // Exit command + else if (strncmp(in_buffer, "exit", BUF_SIZE) == 0) { + xSemaphoreGive(rpp_sdr_cmdproc_semaphore); + tasks_running--; + vTaskDelete(NULL); + + } + // Unknown command, print buffer back + else { + rpp_sci_printf( + (const char *)"ERROR: Unknown command \"%s\"\r\n", + (char *)&in_buffer); + rpp_sci_printf((const char *)"%s", prompt); + } + + // Reset variables + rpp_sci_flush(TRUE); + buff_index = 0; + flush = FALSE; + } + } + + // Delete myself + tasks_running--; + vTaskDelete(NULL); } @@ -221,226 +299,224 @@ void rpp_sdr_cmdproc(void *p) // Flag to check if SDR module is initialized static boolean_t initialized = FALSE; +// Memory for Simulation only +#ifdef FREERTOS_POSIX +static uint8_t memory_simulation[1024*1024]; // Allocate 1MB for test +#endif + // Initialize SDR module int8_t rpp_sdr_init() { - if(initialized) { - return FAILURE; - } - initialized = TRUE; - - // Create memory write mutex - memory_mutex = xSemaphoreCreateMutex(); - - // Create log show semaphore - vSemaphoreCreateBinary(show_semaphore); - - // Define memory bounds - #if rppCONFIG_DRV == 1 - memory_size = RPP_SDR_ADDR_END - RPP_SDR_ADDR_START + 1; - memory_start = (uint8_t*)RPP_SDR_ADDR_START; - memory_end = (uint8_t*)RPP_SDR_ADDR_END; - #elif defined(FREERTOS_POSIX) - memory_size = 1024*1024; // Allocate 1MB for test - memory_start = (uint8_t*)malloc(memory_size); - memory_end = (uint8_t*)(memory_start + memory_size - 1); - #endif - memory_current = memory_start; - - // Low level init - #if rppCONFIG_DRV == 1 - emif_SDRAMInit(); - #endif - - return SUCCESS; + if (initialized) + return FAILURE; + initialized = TRUE; + + // Create memory write mutex + memory_mutex = xSemaphoreCreateMutex(); + + // Create log show semaphore + vSemaphoreCreateBinary(show_semaphore); + xSemaphoreTake(show_semaphore, 0); + + // Create semaphore for outer applications to wait cmdproc to exit. + // Non static! The symbol should be exported, so use the full prefix. + vSemaphoreCreateBinary(rpp_sdr_cmdproc_semaphore); + xSemaphoreTake(rpp_sdr_cmdproc_semaphore, 0); + + // Define memory bounds +#ifndef FREERTOS_POSIX + memory_size = RPP_SDR_ADDR_END - RPP_SDR_ADDR_START + 1; + memory_start = (uint8_t *)RPP_SDR_ADDR_START; + memory_end = (uint8_t *)RPP_SDR_ADDR_END; +#else + memory_size = sizeof(memory_simulation); + memory_start = (uint8_t *)&memory_simulation; + memory_end = (uint8_t *)(memory_start + memory_size - 1); +#endif + memory_current = memory_start; + + // Low level init +#ifndef FREERTOS_POSIX + emif_SDRAMInit(); +#endif + + return SUCCESS; } // General flag to check if logging is enabled static boolean_t log_enabled = FALSE; -// Task handle for command processor task -static xTaskHandle cmdproc_handle; - -// Task handle for log show task -static xTaskHandle show_handle; - // Enable/Disable logging int8_t rpp_sdr_setup(boolean_t enable) { - // Just in case user ignore everything - if(!initialized) { - return FAILURE; - } - - // No change, ignore - if(log_enabled == enable) { - return FAILURE; - } - - // Shut down is requested - if(log_enabled && !enable) { - // Disable logging - log_enabled = FALSE; - // Stop show task if running - rpp_sdr_show(FALSE); - // Delete tasks - vTaskDelete(cmdproc_handle); - vTaskDelete(show_handle); - - // Startup is requested - } else { - log_enabled = TRUE; - xTaskCreate(rpp_sdr_cmdproc , (const signed char*)"rpp_sdr_cmdproc" , - 512, NULL, 2, &cmdproc_handle); - xTaskCreate(rpp_sdr_showtask, (const signed char*)"rpp_sdr_showtask", - 512, NULL, 2, &show_handle); - } - - return SUCCESS; + // Just in case user ignore everything + if (!initialized) + return FAILURE; + + // No change, ignore + if (log_enabled == enable) + return FAILURE; + + // Shut down is requested + if (log_enabled && !enable) { + // Stop show task if running + rpp_sdr_show(FALSE); + // Delete tasks + wait_tasks_to_finish(); + // Disable logging + log_enabled = FALSE; + + // Startup is requested + } + else { + if (xTaskCreate(rpp_sdr_showtask, + "rpp_sdr_showtask", + 256, NULL, 2, &show_handle) != pdPASS) + return FAILURE; + tasks_running++; + + if (xTaskCreate(rpp_sdr_cmdproc, + "rpp_sdr_cmdproc", + 512, NULL, 2, &cmdproc_handle) != pdPASS) { + wait_tasks_to_finish(); + return FAILURE; + } + tasks_running++; + + log_enabled = TRUE; + } + + return SUCCESS; } // Memory available uint32_t rpp_sdr_available() { - if(!log_enabled) { - return 0; - } - return (uint32_t)(memory_end - memory_current + 1); + return (uint32_t)(memory_end - memory_current + 1); } // Store something to the log, if logging is enabled -int32_t rpp_sdr_printf(const char* format, ...) +int32_t rpp_sdr_printf(const char *format, ...) { - if(!log_enabled) { - return FAILURE; - } + if (!log_enabled) + return FAILURE; - // Don't even try if memory is full - if(memory_current == memory_end) { - return FAILURE; - } + // Don't even try if memory is full + if (memory_current == memory_end) + return FAILURE; - /// Format user string - char str[MAX_BUFFER_LEN]; - int length = -1; + /// Format user string + char str[MAX_BUFFER_LEN]; + int length = -1; - va_list argList; - va_start(argList, format); + va_list argList; + va_start(argList, format); - length = vsnprintf(str, sizeof(str), format, argList); + length = vsnprintf(str, sizeof(str), format, argList); - va_end(argList); + va_end(argList); - if(length < 1) { - return length; - } + if (length < 1) + return length; - /// Format header - // uint32_t max value is 4294967295 (10 digits) + [] + ' ' + '\0' = 14 - char hdr[14]; - int hdr_length = -1; - hdr_length = sprintf(hdr, (const char*)"[%10d] ", xTaskGetTickCount()); + /// Format header + // uint32_t max value is 4294967295 (10 digits) + [] + ' ' + '\0' = 14 + char hdr[14]; + int hdr_length = -1; + hdr_length = sprintf(hdr, (const char *)"[%10d] ", xTaskGetTickCount()); - if(hdr_length < 1) { - return hdr_length; - } + if (hdr_length < 1) + return hdr_length; - /// Write header - uint32_t cnt = 0; - int i = 0; - xSemaphoreTake(memory_mutex, portMAX_DELAY); - while((memory_current != memory_end) && (i < hdr_length)) { + /// Write header + uint32_t cnt = 0; + int i = 0; + xSemaphoreTake(memory_mutex, portMAX_DELAY); + while ((memory_current != memory_end) && (i < hdr_length)) { - *memory_current = hdr[i]; + *memory_current = hdr[i]; - memory_current++; - cnt++; - i++; - } + memory_current++; + cnt++; + i++; + } - /// Write user string - i = 0; - while((memory_current != memory_end) && (i < length)) { + /// Write user string + i = 0; + if (length > sizeof(str)) + length = sizeof(str); + while ((memory_current != memory_end) && (i < length)) { - *memory_current = str[i]; + *memory_current = str[i]; - memory_current++; - cnt++; - i++; - } + memory_current++; + cnt++; + i++; + } - /// Write trailer - static const char trl[2] = {'\r', '\n'}; - i = 0; - while((memory_current != memory_end) && (i < sizeof(trl))) { + /// Write trailer + static const char trl[2] = {'\r', '\n'}; + i = 0; + while ((memory_current != memory_end) && (i < sizeof(trl))) { - *memory_current = trl[i]; + *memory_current = trl[i]; - memory_current++; - cnt++; - i++; - } + memory_current++; + cnt++; + i++; + } - xSemaphoreGive(memory_mutex); - return cnt; + xSemaphoreGive(memory_mutex); + return cnt; } // Clears log. Will also stop the show task int8_t rpp_sdr_clear() { - if(!log_enabled) { - return FAILURE; - } + if (!log_enabled) + return FAILURE; - // Stop log show flushing if running - if(show_flushing) { - rpp_sdr_show(FALSE); - } + // Stop log show flushing if running + if (show_flushing) + rpp_sdr_show(FALSE); - // Check if log is already empty - if(memory_current == memory_start) { - return FAILURE; - } + // Check if log is already empty + if (memory_current == memory_start) + return FAILURE; - // Reset memory pointer - memory_current = memory_start; + // Reset memory pointer + memory_current = memory_start; - return SUCCESS; + return SUCCESS; } // Starts/Stops the task that sends the log to the SCI int8_t rpp_sdr_show(boolean_t start) { - if(!log_enabled) { - return FAILURE; - } - - // No change, ignore - if(start == show_flushing) { - return FAILURE; - } - - // Log flush stop requested - if(show_flushing && !start) { - show_flushing = FALSE; - - // Log flush start requested - } else { - show_flushing = TRUE; - xSemaphoreGive(show_semaphore); - } - - return SUCCESS; -} + if (!log_enabled) + return FAILURE; + + // No change, ignore + if (start == show_flushing) + return FAILURE; + // Log flush stop requested + if (show_flushing && !start) + show_flushing = FALSE; -#endif /* rppCONFIG_INCLUDE_SDR */ + // Log flush start requested + else { + show_flushing = TRUE; + xSemaphoreGive(show_semaphore); + } + return SUCCESS; +}