-/* Copyright (C) 2013 Czech Technical University in Prague
+/* Copyright (C) 2013, 2014, 2015 Czech Technical University in Prague
*
* Authors:
* - Carlos Jenkins <carlos@jenkins.co.cr>
*
- * 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 <http://www.gnu.org/licenses/>.
+ * 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
#include "rpp/rpp.h"
-
-#if rppCONFIG_INCLUDE_SDR == 1
#include <stdio.h> // vsnprintf()
#include <ctype.h> // isprint()
#include <string.h> // strncmp()
#include <stdarg.h> // va_start, va_end
-#if rppCONFIG_DRV == 1
+#ifndef FREERTOS_POSIX
#include "drv/drv.h"
-#elif defined(FREERTOS_POSIX)
-#include <stdlib.h> // 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;
+}
// 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);
}
// 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);
}
// 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;
+}