1 /* Copyright (C) 2013, 2014, 2015 Czech Technical University in Prague
4 * - Carlos Jenkins <carlos@jenkins.co.cr>
6 * This document contains proprietary information belonging to Czech
7 * Technical University in Prague. Passing on and copying of this
8 * document, and communication of its contents is not permitted
9 * without prior written authorization.
13 * SD-RAM logging RPP API implementation file.
17 * RPP API documentation.
22 #include <stdio.h> // vsnprintf()
23 #include <ctype.h> // isprint()
24 #include <string.h> // strncmp()
25 #include <stdarg.h> // va_start, va_end
27 #ifndef FREERTOS_POSIX
29 #define echo(x) rpp_sci_putc(x)
31 #define echo(x) (void)(x)
34 static const char *prompt = "--> ";
35 static const char *newline = "\r\n";
37 // extern this semaphore to wait for cmdproc to exit
38 xSemaphoreHandle rpp_sdr_cmdproc_semaphore;
41 /// Memory management variables ------------------------------------------------
42 static xSemaphoreHandle memory_mutex;
43 static uint32_t memory_size = 0;
44 static uint8_t *memory_start = NULL;
45 static uint8_t *memory_end = NULL;
46 static uint8_t *memory_current = NULL;
50 /// Tasks control --------------------------------------------------------------
51 // Task handle for command processor task
52 static xTaskHandle cmdproc_handle;
54 // Task handle for log show task
55 static xTaskHandle show_handle;
57 // Flag the request the tasks to stop
58 static boolean_t stop_tasks = FALSE;
60 // Number of tasks running
61 static uint8_t tasks_running = 0;
63 // Force context change to other tasks until all
64 // the tasks created by this module are deleted.
65 static void wait_tasks_to_finish()
68 while (tasks_running > 0)
75 /// Show log task --------------------------------------------------------------
76 // Semaphore to order the show task to start flushing the log
77 static xSemaphoreHandle show_semaphore;
79 // Flag to check if log show task is flushing the log
80 static boolean_t show_flushing = FALSE;
83 void rpp_sdr_showtask(void *p)
90 // Wait semaphore to start
91 if (xSemaphoreTake(show_semaphore, 1) != pdTRUE)
92 // This will wake up each tick to check if
93 // deletion of this task was requested.
95 current = memory_start;
97 // Iterate until the end of the log
98 while (show_flushing &&
99 (current != memory_current) &&
100 (current < memory_end)) { // Just in case
102 // Print characters in this memory location.
103 // Ignores non-printable characters except \r and \n
105 if ((byte == '\r') || (byte == '\n') || isprint(byte))
110 // If user waited to finish
112 rpp_sci_printf((const char *)"%s", newline);
113 rpp_sci_printf((const char *)"%s", prompt);
114 show_flushing = FALSE;
125 /// Command processor task -----------------------------------------------------
128 // Buffer to store incomming command
129 static char in_buffer[BUF_SIZE];
131 // SCI log command processor task
132 void rpp_sdr_cmdproc(void *p)
134 rpp_sci_printf((const char *)
135 "Log control: %dkB available.\r\n",
136 (rpp_sdr_available() / 1024)
138 rpp_sci_printf((const char *)
139 "===========================================================\r\n"
141 rpp_sci_printf((const char *)"%s", prompt);
144 uint8_t buff_index = 0;
145 boolean_t flush = FALSE;
146 while (!stop_tasks) {
148 // Get one character from the user
149 if (rpp_sci_read_nb(1, &input) != SUCCESS) {
151 vTaskDelay(50 / portTICK_RATE_MS);
155 // Stop flushing if one character is received
158 vTaskDelay(100 / portTICK_RATE_MS);
159 rpp_sci_printf("%s", newline);
160 rpp_sci_printf("%s", prompt);
164 // Backspace and Delete
165 if (input == 8 || input == 127) {
166 if (buff_index > 0) {
173 // Line feed or Carriage return
175 else if (input == 10 || input == 13) {
180 // If is any printable character
182 else if (isprint(input)) {
184 // Store character and increment buffer index
185 in_buffer[buff_index] = input;
189 // Check if buffer is full and force flush
190 if (buff_index == BUF_SIZE - 1)
193 // All other character are ignored
199 in_buffer[buff_index] = '\0';
203 if (buff_index == 0) {
204 rpp_sci_printf((const char *)"%s", newline);
205 rpp_sci_printf((const char *)"%s", prompt);
209 else if (strncmp(in_buffer, "help", BUF_SIZE) == 0) {
211 rpp_sci_printf((const char *)
212 "Available commands:\r\n"
214 rpp_sci_printf((const char *)
215 "\tlog - Show the log.\r\n"
217 rpp_sci_printf((const char *)
218 "\tclear - Clear the log.\r\n"
220 rpp_sci_printf((const char *)
221 "\tavailable - Display amount of memory left.\r\n"
223 rpp_sci_printf((const char *)
224 "\texit - Exit this command processor.\r\n"
227 rpp_sci_printf((const char *)"%s", newline);
228 rpp_sci_printf((const char *)"%s", prompt);
231 else if (strncmp(in_buffer, "log", BUF_SIZE) == 0)
235 else if (strncmp(in_buffer, "clear", BUF_SIZE) == 0) {
237 rpp_sci_printf((const char *)"Done.\r\n");
238 rpp_sci_printf((const char *)"%s", newline);
239 rpp_sci_printf((const char *)"%s", prompt);
243 else if (strncmp(in_buffer, "available", BUF_SIZE) == 0) {
245 (const char *)"%d kB of %d kB available.\r\n",
246 rpp_sdr_available() / 1024,
249 rpp_sci_printf((const char *)"%s", newline);
250 rpp_sci_printf((const char *)"%s", prompt);
254 else if (strncmp(in_buffer, "exit", BUF_SIZE) == 0) {
255 xSemaphoreGive(rpp_sdr_cmdproc_semaphore);
260 // Unknown command, print buffer back
263 (const char *)"ERROR: Unknown command \"%s\"\r\n",
265 rpp_sci_printf((const char *)"%s", prompt);
282 /// Public API -----------------------------------------------------------------
283 // Flag to check if SDR module is initialized
284 static boolean_t initialized = FALSE;
286 // Memory for Simulation only
287 #ifdef FREERTOS_POSIX
288 static uint8_t memory_simulation[1024*1024]; // Allocate 1MB for test
291 // Initialize SDR module
292 int8_t rpp_sdr_init()
298 // Create memory write mutex
299 memory_mutex = xSemaphoreCreateMutex();
301 // Create log show semaphore
302 vSemaphoreCreateBinary(show_semaphore);
303 xSemaphoreTake(show_semaphore, 0);
305 // Create semaphore for outer applications to wait cmdproc to exit.
306 // Non static! The symbol should be exported, so use the full prefix.
307 vSemaphoreCreateBinary(rpp_sdr_cmdproc_semaphore);
308 xSemaphoreTake(rpp_sdr_cmdproc_semaphore, 0);
310 // Define memory bounds
311 #ifndef FREERTOS_POSIX
312 memory_size = RPP_SDR_ADDR_END - RPP_SDR_ADDR_START + 1;
313 memory_start = (uint8_t *)RPP_SDR_ADDR_START;
314 memory_end = (uint8_t *)RPP_SDR_ADDR_END;
316 memory_size = sizeof(memory_simulation);
317 memory_start = (uint8_t *)&memory_simulation;
318 memory_end = (uint8_t *)(memory_start + memory_size - 1);
320 memory_current = memory_start;
323 #ifndef FREERTOS_POSIX
331 // General flag to check if logging is enabled
332 static boolean_t log_enabled = FALSE;
334 // Enable/Disable logging
335 int8_t rpp_sdr_setup(boolean_t enable)
337 // Just in case user ignore everything
342 if (log_enabled == enable)
345 // Shut down is requested
346 if (log_enabled && !enable) {
347 // Stop show task if running
350 wait_tasks_to_finish();
354 // Startup is requested
357 if (xTaskCreate(rpp_sdr_showtask,
359 256, NULL, 2, &show_handle) != pdPASS)
363 if (xTaskCreate(rpp_sdr_cmdproc,
365 512, NULL, 2, &cmdproc_handle) != pdPASS) {
366 wait_tasks_to_finish();
379 uint32_t rpp_sdr_available()
381 return (uint32_t)(memory_end - memory_current + 1);
385 // Store something to the log, if logging is enabled
386 int32_t rpp_sdr_printf(const char *format, ...)
391 // Don't even try if memory is full
392 if (memory_current == memory_end)
395 /// Format user string
396 char str[MAX_BUFFER_LEN];
400 va_start(argList, format);
402 length = vsnprintf(str, sizeof(str), format, argList);
411 // uint32_t max value is 4294967295 (10 digits) + [] + ' ' + '\0' = 14
414 hdr_length = sprintf(hdr, (const char *)"[%10d] ", xTaskGetTickCount());
423 xSemaphoreTake(memory_mutex, portMAX_DELAY);
424 while ((memory_current != memory_end) && (i < hdr_length)) {
426 *memory_current = hdr[i];
434 /// Write user string
436 if (length > sizeof(str))
437 length = sizeof(str);
438 while ((memory_current != memory_end) && (i < length)) {
440 *memory_current = str[i];
448 static const char trl[2] = {'\r', '\n'};
450 while ((memory_current != memory_end) && (i < sizeof(trl))) {
452 *memory_current = trl[i];
459 xSemaphoreGive(memory_mutex);
464 // Clears log. Will also stop the show task
465 int8_t rpp_sdr_clear()
470 // Stop log show flushing if running
474 // Check if log is already empty
475 if (memory_current == memory_start)
478 // Reset memory pointer
479 memory_current = memory_start;
485 // Starts/Stops the task that sends the log to the SCI
486 int8_t rpp_sdr_show(boolean_t start)
492 if (start == show_flushing)
495 // Log flush stop requested
496 if (show_flushing && !start)
497 show_flushing = FALSE;
499 // Log flush start requested
501 show_flushing = TRUE;
502 xSemaphoreGive(show_semaphore);