1 /* Copyright (C) 2013 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) {
76 /// Show log task --------------------------------------------------------------
77 // Semaphore to order the show task to start flushing the log
78 static xSemaphoreHandle show_semaphore;
80 // Flag to check if log show task is flushing the log
81 static boolean_t show_flushing = FALSE;
84 void rpp_sdr_showtask(void *p)
91 // Wait semaphore to start
92 if(xSemaphoreTake(show_semaphore, 1) != pdTRUE) {
93 // This will wake up each tick to check if
94 // deletion of this task was requested.
97 current = memory_start;
99 // Iterate until the end of the log
100 while(show_flushing &&
101 (current != memory_current) &&
102 (current < memory_end)) { // Just in case
104 // Print characters in this memory location.
105 // Ignores non-printable characters except \r and \n
107 if((byte == '\r') || (byte == '\n') || isprint(byte)) {
113 // If user waited to finish
115 rpp_sci_printf((const char*)"%s", newline);
116 rpp_sci_printf((const char*)"%s", prompt);
117 show_flushing = FALSE;
128 /// Command processor task -----------------------------------------------------
131 // Buffer to store incomming command
132 static char in_buffer[BUF_SIZE];
134 // SCI log command processor task
135 void rpp_sdr_cmdproc(void *p)
137 rpp_sci_printf((const char*)
138 "Log control: %dkB available.\r\n",
139 (rpp_sdr_available() / 1024)
141 rpp_sci_printf((const char*)
142 "===========================================================\r\n"
144 rpp_sci_printf((const char*)"%s", prompt);
147 uint8_t buff_index = 0;
148 boolean_t flush = FALSE;
151 // Get one character from the user
152 if(rpp_sci_read_nb(1, &input) != SUCCESS) {
154 vTaskDelay(50 / portTICK_RATE_MS);
159 // Stop flushing if one character is received
162 vTaskDelay(100 / portTICK_RATE_MS);
163 rpp_sci_printf("%s", newline);
164 rpp_sci_printf("%s", prompt);
168 // Backspace and Delete
169 if(input == 8 || input == 127) {
177 // Line feed or Carriage return
178 } else if(input == 10 || input == 13) {
183 // If is any printable character
184 } else if(isprint(input)) {
186 // Store character and increment buffer index
187 in_buffer[buff_index] = input;
191 // Check if buffer is full and force flush
192 if(buff_index == BUF_SIZE - 1) {
196 // All other character are ignored
202 in_buffer[buff_index] = '\0';
206 if(buff_index == 0) {
207 rpp_sci_printf((const char*)"%s", newline);
208 rpp_sci_printf((const char*)"%s", prompt);
211 } else if(strncmp(in_buffer, "help", BUF_SIZE) == 0) {
213 rpp_sci_printf((const char*)
214 "Available commands:\r\n"
216 rpp_sci_printf((const char*)
217 "\tlog - Show the log.\r\n"
219 rpp_sci_printf((const char*)
220 "\tclear - Clear the log.\r\n"
222 rpp_sci_printf((const char*)
223 "\tavailable - Display amount of memory left.\r\n"
225 rpp_sci_printf((const char*)
226 "\texit - Exit this command processor.\r\n"
229 rpp_sci_printf((const char*)"%s", newline);
230 rpp_sci_printf((const char*)"%s", prompt);
233 } else if(strncmp(in_buffer, "log", BUF_SIZE) == 0) {
237 } else if(strncmp(in_buffer, "clear", BUF_SIZE) == 0) {
239 rpp_sci_printf((const char*)"Done.\r\n");
240 rpp_sci_printf((const char*)"%s", newline);
241 rpp_sci_printf((const char*)"%s", prompt);
244 } else if(strncmp(in_buffer, "available", BUF_SIZE) == 0) {
246 (const char*)"%d kB of %d kB available.\r\n",
247 rpp_sdr_available() / 1024,
250 rpp_sci_printf((const char*)"%s", newline);
251 rpp_sci_printf((const char*)"%s", prompt);
254 } else if(strncmp(in_buffer, "exit", BUF_SIZE) == 0) {
255 xSemaphoreGive(rpp_sdr_cmdproc_semaphore);
259 // Unknown command, print buffer back
262 (const char*)"ERROR: Unknown command \"%s\"\r\n",
264 rpp_sci_printf((const char*)"%s", prompt);
281 /// Public API -----------------------------------------------------------------
282 // Flag to check if SDR module is initialized
283 static boolean_t initialized = FALSE;
285 // Memory for Simulation only
286 #ifdef FREERTOS_POSIX
287 static uint8_t memory_simulation[1024*1024]; // Allocate 1MB for test
290 // Initialize SDR module
291 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
343 if(log_enabled == enable) {
347 // Shut down is requested
348 if(log_enabled && !enable) {
349 // Stop show task if running
352 wait_tasks_to_finish();
356 // Startup is requested
358 if(xTaskCreate(rpp_sdr_showtask,
359 (const signed char*)"rpp_sdr_showtask",
360 256, NULL, 2, &show_handle) != pdPASS) {
365 if(xTaskCreate(rpp_sdr_cmdproc ,
366 (const signed char*)"rpp_sdr_cmdproc" ,
367 512, NULL, 2, &cmdproc_handle) != pdPASS) {
368 wait_tasks_to_finish();
381 uint32_t rpp_sdr_available()
383 return (uint32_t)(memory_end - memory_current + 1);
387 // Store something to the log, if logging is enabled
388 int32_t rpp_sdr_printf(const char* format, ...)
394 // Don't even try if memory is full
395 if(memory_current == memory_end) {
399 /// Format user string
400 char str[MAX_BUFFER_LEN];
404 va_start(argList, format);
406 length = vsnprintf(str, sizeof(str), format, argList);
416 // uint32_t max value is 4294967295 (10 digits) + [] + ' ' + '\0' = 14
419 hdr_length = sprintf(hdr, (const char*)"[%10d] ", xTaskGetTickCount());
429 xSemaphoreTake(memory_mutex, portMAX_DELAY);
430 while((memory_current != memory_end) && (i < hdr_length)) {
432 *memory_current = hdr[i];
440 /// Write user string
442 if(length > sizeof(str)) {
443 length = sizeof(str);
445 while((memory_current != memory_end) && (i < length)) {
447 *memory_current = str[i];
455 static const char trl[2] = {'\r', '\n'};
457 while((memory_current != memory_end) && (i < sizeof(trl))) {
459 *memory_current = trl[i];
466 xSemaphoreGive(memory_mutex);
471 // Clears log. Will also stop the show task
472 int8_t rpp_sdr_clear()
478 // Stop log show flushing if running
483 // Check if log is already empty
484 if(memory_current == memory_start) {
488 // Reset memory pointer
489 memory_current = memory_start;
495 // Starts/Stops the task that sends the log to the SCI
496 int8_t rpp_sdr_show(boolean_t start)
503 if(start == show_flushing) {
507 // Log flush stop requested
508 if(show_flushing && !start) {
509 show_flushing = FALSE;
511 // Log flush start requested
513 show_flushing = TRUE;
514 xSemaphoreGive(show_semaphore);