diff --git a/sdk/FreeRTOS-Kernel b/sdk/FreeRTOS-Kernel index c0ce7252..0452603a 160000 --- a/sdk/FreeRTOS-Kernel +++ b/sdk/FreeRTOS-Kernel @@ -1 +1 @@ -Subproject commit c0ce725293bb8cf9b30626a8bba173af33163533 +Subproject commit 0452603a943e13d27e7117f7112c4dd000748705 diff --git a/sdk/app_cpu1/common/sys/commands.c b/sdk/app_cpu1/common/sys/commands.c deleted file mode 100644 index 12a48af8..00000000 --- a/sdk/app_cpu1/common/sys/commands.c +++ /dev/null @@ -1,579 +0,0 @@ -#include "sys/commands.h" -#include "drv/encoder.h" -#include "drv/uart.h" -#include "sys/cmd/cmd_help.h" -#include "sys/debug.h" -#include "sys/defines.h" -#include "sys/icc.h" -#include "sys/icc_tx.h" -#include "sys/log.h" -#include "sys/scheduler.h" -#include "sys/serial.h" -#include "sys/util.h" -#include -#include -#include -#include - -#define RECV_BUFFER_LENGTH (4 * 1024) - -typedef enum cmd_parsing_state_e { - BEGIN = 0, - LOOKING_FOR_SPACE, - LOOKING_FOR_CHAR, -} cmd_parsing_state_e; - -#define CMD_MAX_ARGC (16) // # of args accepted -#define CMD_MAX_ARG_LENGTH (32) // max chars of any arg -typedef struct pending_cmd_t { - int argc; - char *argv[CMD_MAX_ARGC]; - - // Used by parser to keep track of how - // long the argument is. If too long, - // throws an error! - int curr_arg_length; - - // Error flag set by parser task - int err; - - // Set to 1 to indicate ready to execute, - // 0 means not valid - int ready; -} pending_cmd_t; - -// Note, this must be >= 2. -// -// We always need a buffer to be filling while we -// execute the previous command -// -#define MAX_PENDING_CMDS (8) - -typedef struct { - cmd_parsing_state_e state; - - // Store parsed cmds - pending_cmd_t pending_cmds[MAX_PENDING_CMDS]; - int pending_cmd_write_idx; - int pending_cmd_read_idx; - - // Store rx chars - char recv_buffer[RECV_BUFFER_LENGTH]; - int recv_buffer_idx; -} sm_parse_ascii_cmd_ctx_t; - -static sm_parse_ascii_cmd_ctx_t ctx_uart; -static sm_parse_ascii_cmd_ctx_t ctx_eth; - -static int _command_handler(int argc, char **argv); - -static void commands_callback_parse_uart(void *arg); -static void commands_callback_parse_eth(void *arg); -static void commands_callback_exec(void *arg); - -// Head of linked list of commands -static command_entry_t *cmds = NULL; - -static task_control_block_t tcb_parse_uart; -static task_control_block_t tcb_parse_eth; -static task_control_block_t tcb_exec_uart; -static task_control_block_t tcb_exec_eth; - -// The command response data should either go out UART or ETH, -// depending on the command source. Therefore, we'll define -// global general command response functions which users will -// use for their cmd response. This "commands" module will -// update these functions to target the correct stream. - -typedef enum cmd_src_e { - CMD_SRC_UART = 0, - CMD_SRC_ETH, -} cmd_src_e; - -static cmd_src_e current_cmd_source = CMD_SRC_UART; - -void cmd_resp_write(char *msg, int len) -{ - if (current_cmd_source == CMD_SRC_UART) { - serial_write(msg, len); - } else { - for (int i = 0; i < len; i++) { - icc_tx_append_char_to_fifo(msg[i]); - } - } -} - -void cmd_resp_print(char *msg) -{ - if (current_cmd_source == CMD_SRC_UART) { - debug_print(msg); - } else { - cmd_resp_write(msg, strlen(msg)); - } -} - -#define PRINTF_BUFFER_LENGTH (1024) -static char buffer[PRINTF_BUFFER_LENGTH] = { 0 }; -void cmd_resp_printf(const char *format, ...) -{ - va_list vargs; - va_start(vargs, format); - vsnprintf(buffer, PRINTF_BUFFER_LENGTH, format, vargs); - cmd_resp_print(buffer); - va_end(vargs); -} - -void commands_init(void) -{ - printf("CMD:\tInitializing command tasks...\n"); - - // Command parse task (UART) - scheduler_tcb_init( - &tcb_parse_uart, commands_callback_parse_uart, &ctx_uart, "command_parse_uart", COMMANDS_INTERVAL_USEC); - scheduler_tcb_register(&tcb_parse_uart); - - // Command parse task (ETH) - scheduler_tcb_init( - &tcb_parse_eth, commands_callback_parse_eth, &ctx_eth, "command_parse_eth", COMMANDS_INTERVAL_USEC); - scheduler_tcb_register(&tcb_parse_eth); - - // Command exec task (UART) - scheduler_tcb_init(&tcb_exec_uart, commands_callback_exec, &ctx_uart, "command_exec_uart", COMMANDS_INTERVAL_USEC); - scheduler_tcb_register(&tcb_exec_uart); - - // Command exec task (ETH) - scheduler_tcb_init(&tcb_exec_eth, commands_callback_exec, &ctx_eth, "command_exec_eth", COMMANDS_INTERVAL_USEC); - scheduler_tcb_register(&tcb_exec_eth); - - cmd_help_register(); -} - -// Set if we should echo back characters to sender: -// - 0: when EXECUTING the pending command -// - 1: when PROCESSING the incoming chars -// -// Both have pros and cons... For slow comms, we want -// to echo AS the chars come in since the user is likely -// using a UART terminal and wants to see a response to -// their inputs. -// -// For fast comms (i.e. Ethernet), we should only echo -// when the command is executed since the host could send -// a burst of multiple command strings in short time, -// before we have time to actually run the command. -// -// We will choose when PROCESSING the incoming chars and -// limit the command through-put from the host to: -// <= 1 command string per 100 usec time slice -// This will ensure we process the pending command before -// the next set of chars appears. -#define ECHO_BACK_WHEN_PROCESSING_INCOMING_CHARS (1) - -static void _create_pending_cmds(sm_parse_ascii_cmd_ctx_t *ctx, char *buffer, int length) -{ - // Get current pending cmd slot - pending_cmd_t *p = &ctx->pending_cmds[ctx->pending_cmd_write_idx]; - - for (int i = 0; i < length; i++) { - char c = buffer[i]; - - if (ctx->state != BEGIN && (c == '\n' || c == '\r')) { - // End of a command! - - // Set error flag if this arg was too long - if (p->curr_arg_length > CMD_MAX_ARG_LENGTH) { - p->err = CMD_INPUT_TOO_LONG; - } - - // Put a NULL at the end of the last cmd arg - // (replaces a \r or \n, so nbd - buffer[i] = 0; - -#if ECHO_BACK_WHEN_PROCESSING_INCOMING_CHARS == 1 - // Make console go to beginning of next line - if (ctx == &ctx_uart) { - debug_print("\r\n"); - } else { - icc_tx_append_char_to_fifo('\r'); - icc_tx_append_char_to_fifo('\n'); - } -#endif - - p->ready = 1; - - // Update current pending cmd slot - if (++ctx->pending_cmd_write_idx >= MAX_PENDING_CMDS) { - ctx->pending_cmd_write_idx = 0; - } - p = &ctx->pending_cmds[ctx->pending_cmd_write_idx]; - p->ready = 0; - - // Move on to next char, which starts - // next command sequence - ctx->state = BEGIN; - continue; - } - -#if ECHO_BACK_WHEN_PROCESSING_INCOMING_CHARS == 1 - // Echo character back to host - if (ctx == &ctx_uart) { - serial_write(&c, 1); - } else { - icc_tx_append_char_to_fifo(c); - } -#endif - - // Process incoming char `c` - switch (ctx->state) { - case BEGIN: - if (!isspace(c)) { - // Populate first argument - p->argc = 1; - p->argv[0] = &buffer[i]; - p->err = CMD_SUCCESS; // Assume the parsing will work! - p->curr_arg_length = 1; - ctx->state = LOOKING_FOR_SPACE; - } - break; - - case LOOKING_FOR_SPACE: - if (c != ' ') { - p->curr_arg_length++; - } - - if (c == ' ') { - // End of chars for the arg - - // Set error flag if this arg was too long - if (p->curr_arg_length > CMD_MAX_ARG_LENGTH) { - p->err = CMD_INPUT_TOO_LONG; - } - - // Put NULL at end of arg (replaces ' ') - buffer[i] = 0; - - ctx->state = LOOKING_FOR_CHAR; - } - break; - - case LOOKING_FOR_CHAR: - if (c != ' ') { - p->argv[p->argc] = &buffer[i]; - p->argc++; - - // Check if argc too big! - if (p->argc > CMD_MAX_ARGC) { - p->err = CMD_INPUT_TOO_LONG; - - // Put argc back to zero... - // NOTE: this ensure no buffer overruns, - // but, screws up previous args. - // This is okay as we are going to - // throw away this pending cmd! - p->argc = 0; - } - - p->curr_arg_length = 1; - ctx->state = LOOKING_FOR_SPACE; - } - break; - - default: - // Impossible! - HANG; - break; - } - } -} - -static void commands_callback_parse_uart(void *arg) -{ - sm_parse_ascii_cmd_ctx_t *ctx = (sm_parse_ascii_cmd_ctx_t *) arg; - - // Read in bounded chunk of new chars - // - // NOTE: careful not to try and read too much! - // would cause a buffer overrun! - // - int try_to_read = MIN(UART_RX_FIFO_LENGTH, RECV_BUFFER_LENGTH - ctx->recv_buffer_idx); - int num_bytes = uart_recv(&ctx->recv_buffer[ctx->recv_buffer_idx], try_to_read); - - // Run state machine to create pending cmds to execute - _create_pending_cmds(ctx, &ctx->recv_buffer[ctx->recv_buffer_idx], num_bytes); - - // Move along in recv buffer - ctx->recv_buffer_idx += num_bytes; - if (ctx->recv_buffer_idx >= RECV_BUFFER_LENGTH) { - ctx->recv_buffer_idx = 0; - } -} - -static void commands_callback_parse_eth(void *arg) -{ - sm_parse_ascii_cmd_ctx_t *ctx = (sm_parse_ascii_cmd_ctx_t *) arg; - - static const int MAX_NUM_BYTES_TO_TRY = 128; - - // Try to pull out the oldest MAX_NUM_BYTES_TO_TRY bytes from the shared FIFO from CPU0 - // - // If there are less than MAX_NUM_BYTES_TO_TRY bytes in the FIFO, this code will simply - // pull out everything and return. - for (int i = 0; i < MAX_NUM_BYTES_TO_TRY; i++) { - // Check if there are any bytes in the FIFO - if (ICC_CPU0to1_CH0__GET_ProduceCount - ICC_CPU0to1_CH0__GET_ConsumeCount == 0) { - // Shared buffer is empty - return; - } - - // Read the oldest byte available - uint8_t *sharedBuffer = ICC_CPU0to1_CH0__BufferBaseAddr; - uint8_t c = sharedBuffer[ICC_CPU0to1_CH0__GET_ConsumeCount % ICC_BUFFER_SIZE]; - - // Increment the consume count - ICC_CPU0to1_CH0__SET_ConsumeCount(ICC_CPU0to1_CH0__GET_ConsumeCount + 1); - - // ===================== - // Process incoming char - // ===================== - - char c_char = (char) c; - - // Push the new byte into the rx buffer - ctx->recv_buffer[ctx->recv_buffer_idx] = c_char; - - // Run state machine to create pending cmds to execute - _create_pending_cmds(ctx, &ctx->recv_buffer[ctx->recv_buffer_idx], 1); - - // Move along in recv buffer - ctx->recv_buffer_idx += 1; - if (ctx->recv_buffer_idx >= RECV_BUFFER_LENGTH) { - ctx->recv_buffer_idx = 0; - } - } -} - -static void commands_callback_exec(void *arg) -{ - sm_parse_ascii_cmd_ctx_t *ctx = (sm_parse_ascii_cmd_ctx_t *) arg; - - // Get current pending cmd slot - pending_cmd_t *p = &ctx->pending_cmds[ctx->pending_cmd_read_idx]; - - if (p->ready) { - // Run me! - - // Change current cmd source - if (ctx == &ctx_uart) { - current_cmd_source = CMD_SRC_UART; - } else if (ctx == &ctx_eth) { - current_cmd_source = CMD_SRC_ETH; - } else { - // unreachable - } - -#if ECHO_BACK_WHEN_PROCESSING_INCOMING_CHARS == 0 - // Echo back command to sender - for (int i = 0; i < p->argc; i++) { - cmd_resp_printf("%s", p->argv[i]); - - if (i + 1 < p->argc) { - cmd_resp_print(" "); - } - } - cmd_resp_print("\r\n"); -#endif - - // Don't run a cmd that has errors - int err = p->err; - if (err == CMD_SUCCESS) { - err = _command_handler(p->argc, p->argv); - } - - // Display command status to user - switch (err) { - case CMD_SUCCESS_QUIET: - // Don't print anything - break; - - case CMD_SUCCESS: - cmd_resp_printf("SUCCESS\r\n\n"); - break; - - case CMD_FAILURE: - cmd_resp_printf("FAILURE\r\n\n"); - break; - - case CMD_INVALID_ARGUMENTS: - cmd_resp_printf("INVALID ARGUMENTS\r\n\n"); - break; - - case CMD_INPUT_TOO_LONG: - cmd_resp_printf("INPUT TOO LONG\r\n\n"); - break; - - case CMD_UNKNOWN_CMD: - cmd_resp_printf("UNKNOWN CMD\r\n\n"); - break; - - default: - cmd_resp_printf("UNKNOWN ERROR\r\n\n"); - break; - } - - p->ready = 0; - - // Update READ index - if (++ctx->pending_cmd_read_idx >= MAX_PENDING_CMDS) { - ctx->pending_cmd_read_idx = 0; - } - } -} - -void commands_cmd_init(command_entry_t *cmd_entry, - const char *cmd, - const char *desc, - command_help_t *help, - int num_help_cmds, - int (*cmd_function)(int, char **)) -{ - cmd_entry->cmd = cmd; - cmd_entry->desc = desc; - cmd_entry->help = help; - cmd_entry->num_help_cmds = num_help_cmds; - cmd_entry->cmd_function = cmd_function; - cmd_entry->next = NULL; -} - -void commands_cmd_register(command_entry_t *cmd_entry) -{ - // Base case: there are no tasks in linked list - if (cmds == NULL) { - cmds = cmd_entry; - cmds->next = NULL; - return; - } - - // Find end of list - command_entry_t *curr = cmds; - while (curr->next != NULL) - curr = curr->next; - - // Append new cmd to end of list - curr->next = cmd_entry; - cmd_entry->next = NULL; -} - -void commands_start_msg(void) -{ - cmd_resp_printf("\r\n"); - commands_display_help(); -} - -// _command_handler -// -// Takes `argc` and `argv` and finds -// the command function to call. -// -int _command_handler(int argc, char **argv) -{ - command_entry_t *c = cmds; - - while (c != NULL) { - if (strcmp(argv[0], c->cmd) == 0) { - // Found command to run! - return c->cmd_function(argc, argv); - } - - c = c->next; - } - - return CMD_UNKNOWN_CMD; -} - -// **************** -// State Machine -// which outputs -// the help messages -// **************** - -typedef enum sm_states_e { TITLE1 = 1, TITLE2, TITLE3, CMD_HEADER, SUB_CMD, REMOVE_TASK } sm_states_e; - -typedef struct sm_ctx_t { - sm_states_e state; - command_entry_t *curr; - int sub_cmd_idx; - task_control_block_t tcb; -} sm_ctx_t; - -#define SM_UPDATES_PER_SEC (10000) -#define SM_INTERVAL_USEC (USEC_IN_SEC / SM_UPDATES_PER_SEC) - -void help_state_machine_callback(void *arg) -{ - sm_ctx_t *ctx = (sm_ctx_t *) arg; - - switch (ctx->state) { - case TITLE1: - cmd_resp_printf("\r\n"); - - ctx->curr = cmds; - ctx->state = TITLE2; - break; - - case TITLE2: - cmd_resp_printf("Available commands:\r\n"); - ctx->state = TITLE3; - break; - - case TITLE3: - cmd_resp_printf("-------------------\r\n"); - ctx->state = CMD_HEADER; - break; - - case CMD_HEADER: - if (ctx->curr == NULL) { - // DONE! - cmd_resp_printf("\r\n"); - ctx->state = REMOVE_TASK; - } else { - cmd_resp_printf("%s -- %s\r\n", ctx->curr->cmd, ctx->curr->desc); - ctx->sub_cmd_idx = 0; - ctx->state = SUB_CMD; - } - break; - - case SUB_CMD: - if (ctx->sub_cmd_idx >= ctx->curr->num_help_cmds) { - ctx->curr = ctx->curr->next; - ctx->state = CMD_HEADER; - } else { - command_help_t *h = &ctx->curr->help[ctx->sub_cmd_idx++]; - cmd_resp_printf("\t%s -- %s\r\n", h->subcmd, h->desc); - } - break; - - case REMOVE_TASK: - cmd_resp_printf("SUCCESS\r\n\n"); - scheduler_tcb_unregister(&ctx->tcb); - break; - - default: - // Can't happen - HANG; - break; - } -} - -static sm_ctx_t ctx; - -void commands_display_help(void) -{ - // Initialize the state machine context - ctx.state = TITLE1; - ctx.curr = cmds; - ctx.sub_cmd_idx = 0; - - // Initialize the state machine callback tcb - scheduler_tcb_init(&ctx.tcb, help_state_machine_callback, &ctx, "help_sm", SM_INTERVAL_USEC); - scheduler_tcb_register(&ctx.tcb); -} diff --git a/sdk/app_cpu1/common/sys/util.c b/sdk/app_cpu1/common/sys/util.c deleted file mode 100644 index d9ff16b3..00000000 --- a/sdk/app_cpu1/common/sys/util.c +++ /dev/null @@ -1 +0,0 @@ -#include "sys/util.h" diff --git a/sdk/app_cpu1/user/usr/blink/task_blink.c b/sdk/app_cpu1/user/usr/blink/task_blink.c deleted file mode 100644 index 38836bf9..00000000 --- a/sdk/app_cpu1/user/usr/blink/task_blink.c +++ /dev/null @@ -1,78 +0,0 @@ -#ifdef APP_BLINK - -#include "usr/blink/task_blink.h" -#include "drv/led.h" -#include "sys/scheduler.h" -#include - -// Hold LED animation state -static uint8_t led_pos = 0; -static uint8_t led_color_idx = 0; -#define NUM_LED_COLORS (7) -static led_color_t led_colors[NUM_LED_COLORS] = { - LED_COLOR_RED, // - LED_COLOR_GREEN, // - LED_COLOR_BLUE, // - LED_COLOR_YELLOW, // - LED_COLOR_CYAN, // - LED_COLOR_MAGENTA, // - LED_COLOR_WHITE, // -}; - -// Scheduler TCB which holds task "context" -static task_control_block_t tcb; - -int task_blink_init(void) -{ - if (scheduler_tcb_is_registered(&tcb)) { - return FAILURE; - } - - // Fill TCB with parameters - scheduler_tcb_init(&tcb, task_blink_callback, NULL, "blink", TASK_BLINK_INTERVAL_USEC); - - // Register task with scheduler - return scheduler_tcb_register(&tcb); -} - -int task_blink_deinit(void) -{ - // Turn off all LEDs - for (uint8_t i = 0; i < NUM_LEDS; i++) { - led_set_color(i, LED_COLOR_BLACK); - } - - // Reset state - led_pos = 0; - led_color_idx = 0; - - // Unregister task with scheduler - return scheduler_tcb_unregister(&tcb); -} - -void task_blink_callback(void *arg) -{ - for (uint8_t i = 0; i < NUM_LEDS; i++) { - led_set_color(i, led_pos == i ? led_colors[led_color_idx] : LED_COLOR_BLACK); - } - - if (++led_pos == NUM_LEDS) { - led_pos = 0; - - if (++led_color_idx >= NUM_LED_COLORS) { - led_color_idx = 0; - } - } -} - -void task_blink_stats_print(void) -{ - task_stats_print(&tcb.stats); -} - -void task_blink_stats_reset(void) -{ - task_stats_reset(&tcb.stats); -} - -#endif // APP_BLINK diff --git a/sdk/app_cpu1/user/usr/blink/task_vsi.c b/sdk/app_cpu1/user/usr/blink/task_vsi.c deleted file mode 100644 index 2dfd7780..00000000 --- a/sdk/app_cpu1/user/usr/blink/task_vsi.c +++ /dev/null @@ -1,55 +0,0 @@ -#ifdef APP_BLINK - -#include "usr/blink/task_vsi.h" -#include "drv/led.h" -#include "sys/scheduler.h" -#include -#include - -// Scheduler TCB which holds task "context" -static task_control_block_t tcb; - -// Example logging variables for testing -int LOG_task_vsi_runs = 0; -double LOG_vsi_a = 0; -float LOG_vsi_b = 0; -int LOG_vsi_c = 0; - -static double Ts = 1.0 / 10000.0; // [sec] -static double theta = 0.0; // [rad] -static double omega = 10.0; // [rad/s] -static double Do = 0.75; // [--] - -void task_vsi_init(void) -{ - if (scheduler_tcb_is_registered(&tcb)) { - return; - } - - // Fill TCB with parameters - scheduler_tcb_init(&tcb, task_vsi_callback, NULL, "vsi", TASK_VSI_INTERVAL_USEC); - - // Register task with scheduler - scheduler_tcb_register(&tcb); -} - -void task_vsi_callback(void *arg) -{ - LOG_task_vsi_runs += 1; - - // Update theta - theta += (Ts * omega); - theta = fmod(theta, 2.0 * M_PI); // Wrap to 2*pi - - // Calculate desired duty ratios - double vsi_a = Do * cos(theta); - double vsi_b = Do * cos(theta + 2.0 * M_PI / 3.0); - double vsi_c = Do * cos(theta + 4.0 * M_PI / 3.0); - - // Update logging variables - LOG_vsi_a = (double) (10e3 * vsi_a); - LOG_vsi_b = (float) (10e3 * vsi_b); - LOG_vsi_c = (int) (10e3 * vsi_c); -} - -#endif // APP_BLINK diff --git a/sdk/app_cpu1/user/usr/blink/task_vsi.h b/sdk/app_cpu1/user/usr/blink/task_vsi.h deleted file mode 100644 index 130e6212..00000000 --- a/sdk/app_cpu1/user/usr/blink/task_vsi.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef TASK_VSI_H -#define TASK_VSI_H - -#include "sys/scheduler.h" - -#define TASK_VSI_UPDATES_PER_SEC (10000) -#define TASK_VSI_INTERVAL_USEC (USEC_IN_SEC / TASK_VSI_UPDATES_PER_SEC) - -void task_vsi_init(void); - -void task_vsi_callback(void *arg); - -#endif // TASK_VSI_H diff --git a/sdk/freertos_app_cpu0/.cproject b/sdk/freertos_app_cpu0/.cproject index 12744bde..99b90ffa 100644 --- a/sdk/freertos_app_cpu0/.cproject +++ b/sdk/freertos_app_cpu0/.cproject @@ -1,198 +1,265 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/freertos_app_cpu0/.project b/sdk/freertos_app_cpu0/.project index 23ac0f12..1cd1942e 100644 --- a/sdk/freertos_app_cpu0/.project +++ b/sdk/freertos_app_cpu0/.project @@ -1,38 +1,38 @@ - - - freertos_app_cpu0 - Created by SDK v2019.1. amdc_freertos_bsp_cpu0 - ps7_cortexa9_0 - - amdc_freertos_bsp_cpu0 - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - - - FreeRTOS-Kernel - 2 - S:/School/WEMPEC/firmware-rtos-e/sdk/FreeRTOS-Kernel - - - shared - 2 - S:/School/WEMPEC/firmware-rtos-e/sdk/shared - - - + + + freertos_app_cpu0 + Created by SDK v2019.1. amdc_freertos_bsp_cpu0 - ps7_cortexa9_0 + + amdc_freertos_bsp_cpu0 + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + FreeRTOS-Kernel + 2 + C:/Users/srich008/Information/gitMistakes/freertos-singlecore-temp/sdk/FreeRTOS-Kernel + + + shared + 2 + C:/Users/srich008/Information/gitMistakes/freertos-singlecore-temp/sdk/shared + + + diff --git a/sdk/freertos_app_cpu0/src/FreeRTOSConfig.h b/sdk/freertos_app_cpu0/src/FreeRTOSConfig.h index b92d6969..bc1fbfd4 100644 --- a/sdk/freertos_app_cpu0/src/FreeRTOSConfig.h +++ b/sdk/freertos_app_cpu0/src/FreeRTOSConfig.h @@ -82,7 +82,7 @@ #define configCPU_CLOCK_HZ 100000000UL #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #define configUSE_TICKLESS_IDLE 0 -#define configTICK_RATE_HZ ((TickType_t) 1000) +#define configTICK_RATE_HZ ((TickType_t) 10000) #define configPERIPHERAL_CLOCK_HZ (33333000UL) #define configUSE_PREEMPTION 1 #define configUSE_IDLE_HOOK 0 // TODO: For low-power, set 1 and implement vApplicationIdleHook() @@ -149,18 +149,16 @@ to exclude the API function. */ format the raw data provided by the uxTaskGetSystemState() function in to human readable ASCII form. See the notes in the implementation of vTaskList() within FreeRTOS/Source/tasks.c for limitations. */ -#define configUSE_STATS_FORMATTING_FUNCTIONS 0 +#define configUSE_STATS_FORMATTING_FUNCTIONS 1 -/* The private watchdog is used to generate run time stats. */ -/* +/* A separate timer is used to generate run time stats. */ #include "xscuwdt.h" -extern XScuWdt xWatchDogInstance; -extern void vInitialiseTimerForRunTimeStats( void ); +extern XScuWdt xTimerStats; +extern void vInitialiseTimerForRunTimeStats(void); #define configGENERATE_RUN_TIME_STATS 1 #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vInitialiseTimerForRunTimeStats() -#define portGET_RUN_TIME_COUNTER_VALUE() ( ( 0xffffffffUL - XScuWdt_ReadReg( xWatchDogInstance.Config.BaseAddr, -XSCUWDT_COUNTER_OFFSET ) ) >> 1 ) -*/ +#define portGET_RUN_TIME_COUNTER_VALUE() ((0xffffffffUL - XScuWdt_ReadReg(xTimerStats.Config.BaseAddr, XSCUWDT_COUNTER_OFFSET)) >> 1) + /* The size of the global output buffer that is available for use when there are multiple command interpreters running at once (for example, one on a UART @@ -244,4 +242,8 @@ line interface. */ #define configNET_MASK2 255 #define configNET_MASK3 0 +/* MS to tick macros */ +#define pdMS_TO_TICKS(xTimeInMs) ((TickType_t) (((xTimeInMs) * (uint64_t) configTICK_RATE_HZ) / (uint64_t) 1000U)) +#define pdTICKS_TO_MS(xTimeInTicks) (((xTimeInTicks) * (uint64_t) 1000U) / (double) configTICK_RATE_HZ) + #endif /* FREERTOS_CONFIG_H */ diff --git a/sdk/freertos_app_cpu0/src/main.c b/sdk/freertos_app_cpu0/src/main.c index 9a77b434..61b22a1c 100644 --- a/sdk/freertos_app_cpu0/src/main.c +++ b/sdk/freertos_app_cpu0/src/main.c @@ -45,6 +45,11 @@ /* Begin User Includes */ #include "drv/led.h" +#include "drv/uart.h" +#include "sys/serial.h" +#include "sys/commands.h" +#include "sys/cmd/cmd_counter.h" +#include "usr/user_apps.h" /* End User Includes */ #define TIMER_ID 1 @@ -58,6 +63,9 @@ static void prvTxTask(void *pvParameters); static void prvRxTask(void *pvParameters); static void prvBlinkyTask(void *pvParameters); static void vTimerCallback(TimerHandle_t pxTimer); + +#define DELAY_1_SECOND 1000UL +#define INTC_HANDLER XScuGic_InterruptHandler /*-----------------------------------------------------------*/ /* This project has configSUPPORT_STATIC_ALLOCATION set to 1 (for Inter-Core Communication) so @@ -91,6 +99,7 @@ extern void vPortInstallFreeRTOSVectorTable(void); #define QUEUE_LENGTH 10 #define ITEM_SIZE sizeof(uint32_t) + static TaskHandle_t xTxTaskHandle; static TaskHandle_t xRxTaskHandle; static TaskHandle_t xBlinkyTaskHandle; @@ -135,6 +144,7 @@ int main(void) __asm__("sev"); #endif + Xil_ExceptionInit(); intr_init(); icc_init(); @@ -144,11 +154,27 @@ int main(void) // BEGIN USER CODE HERE // ///////////////////////// + /* setup interrupts */ + led_init(); + uart_init(); + serial_init(); + commands_init(); - const TickType_t x10seconds = pdMS_TO_TICKS(DELAY_10_SECONDS); + /* command sets */ + cmd_counter_register(); - xil_printf("CPU0 - Hello from FreeRTOS example main()!\r\n"); + /* user apps */ + user_apps_init(); + + xil_printf("CPU0 - freertos game!\r\n"); +// xil_printf("1 millisecond is %d ticks\n", pdMS_TO_TICKS(1)); +// xil_printf("0.1 milliseconds is %d ticks\n", pdMS_TO_TICKS(0.1)); +// +// xil_printf("10 ticks is %d milliseconds\n", pdTICKS_TO_MS(10)); +// xil_printf("1 ticks is %d microseconds\n", (int) (pdTICKS_TO_MS(1) * 1000)); + + const TickType_t x10seconds = pdMS_TO_TICKS(DELAY_10_SECONDS); /* Create the three tasks */ xTaskCreate(prvTxTask, /* The function that implements the task. */ @@ -211,6 +237,7 @@ int main(void) to be created. See the memory management section on the FreeRTOS web site for more details. */ for (;;) { + xil_printf("IF YOU'RE READING THIS THEN HEAP MEMORY HAS RUN OUT!\n"); } } @@ -410,3 +437,39 @@ void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, * configMINIMAL_STACK_SIZE is specified in words, not bytes. */ *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; } + +/*******************************************************************************/ +/* S E T U P I N T E R R U P T S Y S T E M */ +/*******************************************************************************/ +int SetupInterruptSystem(XScuGic *IntcInstancePtr) { + int Result; + + XScuGic_Config *IntcConfig; + + // Initialize the interrupt controller driver so that it is ready to use. + + IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);//ELS -- this is misleading! there is only one XScuGic device (0) + if (NULL == IntcConfig) { + return XST_FAILURE; + } + + Result = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig, + IntcConfig->CpuBaseAddress); + if (Result != XST_SUCCESS) { + return XST_FAILURE; + } + + // Initialize the exception table and register the interrupt + // controller handler with the exception table + + Xil_ExceptionInit(); + + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler) INTC_HANDLER, IntcInstancePtr); + + // Enable non-critical exceptions + + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} diff --git a/sdk/app_cpu1/user/usr/blink/README.md b/sdk/freertos_app_cpu0/src/usr/blink/README.md similarity index 100% rename from sdk/app_cpu1/user/usr/blink/README.md rename to sdk/freertos_app_cpu0/src/usr/blink/README.md diff --git a/sdk/app_cpu1/user/usr/blink/app_blink.c b/sdk/freertos_app_cpu0/src/usr/blink/app_blink.c similarity index 100% rename from sdk/app_cpu1/user/usr/blink/app_blink.c rename to sdk/freertos_app_cpu0/src/usr/blink/app_blink.c diff --git a/sdk/app_cpu1/user/usr/blink/app_blink.h b/sdk/freertos_app_cpu0/src/usr/blink/app_blink.h similarity index 100% rename from sdk/app_cpu1/user/usr/blink/app_blink.h rename to sdk/freertos_app_cpu0/src/usr/blink/app_blink.h diff --git a/sdk/app_cpu1/user/usr/blink/cmd/cmd_blink.c b/sdk/freertos_app_cpu0/src/usr/blink/cmd/cmd_blink.c similarity index 100% rename from sdk/app_cpu1/user/usr/blink/cmd/cmd_blink.c rename to sdk/freertos_app_cpu0/src/usr/blink/cmd/cmd_blink.c diff --git a/sdk/app_cpu1/user/usr/blink/cmd/cmd_blink.h b/sdk/freertos_app_cpu0/src/usr/blink/cmd/cmd_blink.h similarity index 100% rename from sdk/app_cpu1/user/usr/blink/cmd/cmd_blink.h rename to sdk/freertos_app_cpu0/src/usr/blink/cmd/cmd_blink.h diff --git a/sdk/freertos_app_cpu0/src/usr/blink/task_blink.c b/sdk/freertos_app_cpu0/src/usr/blink/task_blink.c new file mode 100644 index 00000000..eaedb4ae --- /dev/null +++ b/sdk/freertos_app_cpu0/src/usr/blink/task_blink.c @@ -0,0 +1,93 @@ +#ifdef APP_BLINK + +/* FreeRTOS includes */ +#include "FreeRTOS.h" +#include "task.h" +/* other includes */ +#include "usr/blink/task_blink.h" +#include "drv/led.h" +#include "sys/defines.h" +#include "sys/task_priority.h" +#include + +// Hold LED animation state +static uint8_t led_pos = 0; +static uint8_t led_color_idx = 0; +#define NUM_LED_COLORS (7) +static led_color_t led_colors[NUM_LED_COLORS] = { + LED_COLOR_RED, // + LED_COLOR_GREEN, // + LED_COLOR_BLUE, // + LED_COLOR_YELLOW, // + LED_COLOR_CYAN, // + LED_COLOR_MAGENTA, // + LED_COLOR_WHITE, // +}; + +// Scheduler TCB which holds task "context" +static TaskHandle_t tcb; +static uint8_t taskExists = 0; // extra data to ensure tasks don't get duplicated or double free'd + +int task_blink_init(void) +{ + if (taskExists) { + return FAILURE; + } + // Fill TCB with parameters + xTaskCreate(task_blink, (const char *) "blink", configMINIMAL_STACK_SIZE, + NULL, BLINK_TASK_PRIORITY, &tcb); + taskExists = 1; + return SUCCESS; +} + +int task_blink_deinit(void) +{ + if (taskExists == 0) { + return FAILURE; + } + // Turn off all LEDs + for (uint8_t i = 0; i < NUM_LEDS; i++) { + led_set_color(i, LED_COLOR_BLACK); + } + + // Reset state + led_pos = 0; + led_color_idx = 0; + + // Unregister task with scheduler + vTaskDelete(tcb); + taskExists = 0; + return SUCCESS; +} + +void task_blink(void *arg) +{ + for (;;) { + vTaskDelay(TASK_BLINK_INTERVAL_TICKS); + for (uint8_t i = 0; i < NUM_LEDS; i++) { + led_set_color(i, led_pos == i ? led_colors[led_color_idx] : LED_COLOR_BLACK); + } + + if (++led_pos == NUM_LEDS) { + led_pos = 0; + + if (++led_color_idx >= NUM_LED_COLORS) { + led_color_idx = 0; + } + } + } +} + +void task_blink_stats_print(void) +{ + char statsBuffer[configSTATS_BUFFER_MAX_LENGTH]; + vTaskGetRunTimeStats(statsBuffer); + xil_printf("%s\n", statsBuffer); +} + +void task_blink_stats_reset(void) +{ + /* currently does nothing */ +} + +#endif // APP_BLINK diff --git a/sdk/app_cpu1/user/usr/blink/task_blink.h b/sdk/freertos_app_cpu0/src/usr/blink/task_blink.h similarity index 82% rename from sdk/app_cpu1/user/usr/blink/task_blink.h rename to sdk/freertos_app_cpu0/src/usr/blink/task_blink.h index ddb8bf9e..f1e78872 100644 --- a/sdk/app_cpu1/user/usr/blink/task_blink.h +++ b/sdk/freertos_app_cpu0/src/usr/blink/task_blink.h @@ -1,7 +1,9 @@ #ifndef TASK_BLINK_H #define TASK_BLINK_H -#include "sys/scheduler.h" +/* FreeRTOS includes */ +#include "FreeRTOS.h" +#include "task.h" // Frequency that this task is called (in Hz) // @@ -14,14 +16,14 @@ // // This is what scheduler actually uses to run task, // but is generated via define above -#define TASK_BLINK_INTERVAL_USEC (USEC_IN_SEC / TASK_BLINK_UPDATES_PER_SEC) +#define TASK_BLINK_INTERVAL_TICKS (pdMS_TO_TICKS(1000.0 / TASK_BLINK_UPDATES_PER_SEC)) // Called in app init function to set up task (or via command) int task_blink_init(void); int task_blink_deinit(void); // Callback function which scheduler calls periodically -void task_blink_callback(void *arg); +void task_blink(void *arg); // Print the statistics gathered by the scheduler void task_blink_stats_print(void); diff --git a/sdk/freertos_app_cpu0/src/usr/blink/task_vsi.c b/sdk/freertos_app_cpu0/src/usr/blink/task_vsi.c new file mode 100644 index 00000000..7371f0d3 --- /dev/null +++ b/sdk/freertos_app_cpu0/src/usr/blink/task_vsi.c @@ -0,0 +1,56 @@ +#ifdef APP_BLINK +/* FreeRTOS includes */ +#include "FreeRTOS.h" +#include "task.h" +/* other includes */ +#include "usr/blink/task_vsi.h" +#include "drv/led.h" +#include "sys/defines.h" +#include "sys/task_priority.h" +#include +#include + +// Scheduler TCB which holds task "context" +static TaskHandle_t tcb; + +// Example logging variables for testing +int LOG_task_vsi_runs = 0; +double LOG_vsi_a = 0; +float LOG_vsi_b = 0; +int LOG_vsi_c = 0; + +static double Ts = 1.0 / 10000.0; // [sec] +static double theta = 0.0; // [rad] +static double omega = 10.0; // [rad/s] +static double Do = 0.75; // [--] + +void task_vsi_init(void) +{ + // Fill TCB with parameters + xTaskCreate(task_vsi, (const char *) "vsi", configMINIMAL_STACK_SIZE, + NULL, VSI_TASK_PRIORITY, &tcb); +} + +void task_vsi(void *arg) +{ + for (;;) { + vTaskDelay(TASK_VSI_INTERVAL_TICKS); + LOG_task_vsi_runs += 1; + + // Update theta + theta += (Ts * omega); + theta = fmod(theta, 2.0 * M_PI); // Wrap to 2*pi + + // Calculate desired duty ratios + double vsi_a = Do * cos(theta); + double vsi_b = Do * cos(theta + 2.0 * M_PI / 3.0); + double vsi_c = Do * cos(theta + 4.0 * M_PI / 3.0); + + // Update logging variables + LOG_vsi_a = (double) (10e3 * vsi_a); + LOG_vsi_b = (float) (10e3 * vsi_b); + LOG_vsi_c = (int) (10e3 * vsi_c); + } +} + +#endif // APP_BLINK diff --git a/sdk/freertos_app_cpu0/src/usr/blink/task_vsi.h b/sdk/freertos_app_cpu0/src/usr/blink/task_vsi.h new file mode 100644 index 00000000..c401d6f4 --- /dev/null +++ b/sdk/freertos_app_cpu0/src/usr/blink/task_vsi.h @@ -0,0 +1,15 @@ +#ifndef TASK_VSI_H +#define TASK_VSI_H + +/* FreeRTOS includes */ +#include "FreeRTOS.h" +#include "task.h" + +#define TASK_VSI_UPDATES_PER_SEC (10000) +#define TASK_VSI_INTERVAL_TICKS (pdMS_TO_TICKS(1000.0 / TASK_VSI_UPDATES_PER_SEC)) + +void task_vsi_init(void); + +void task_vsi(void *arg); + +#endif // TASK_VSI_H diff --git a/sdk/app_cpu1/user/usr/user_apps.c b/sdk/freertos_app_cpu0/src/usr/user_apps.c similarity index 100% rename from sdk/app_cpu1/user/usr/user_apps.c rename to sdk/freertos_app_cpu0/src/usr/user_apps.c diff --git a/sdk/app_cpu1/user/usr/user_apps.h b/sdk/freertos_app_cpu0/src/usr/user_apps.h similarity index 100% rename from sdk/app_cpu1/user/usr/user_apps.h rename to sdk/freertos_app_cpu0/src/usr/user_apps.h diff --git a/sdk/app_cpu1/user/usr/user_config.h b/sdk/freertos_app_cpu0/src/usr/user_config.h similarity index 84% rename from sdk/app_cpu1/user/usr/user_config.h rename to sdk/freertos_app_cpu0/src/usr/user_config.h index 53b3c8b8..6f448c47 100644 --- a/sdk/app_cpu1/user/usr/user_config.h +++ b/sdk/freertos_app_cpu0/src/usr/user_config.h @@ -9,14 +9,6 @@ // Specify hardware revision (i.e. REV E, REV F, etc) #define USER_CONFIG_HARDWARE_TARGET (AMDC_REV_F) -// Override the default scheduler elementary frequency by defining SYS_TICK_FREQ here. -// System uses 10kHz by default -//#define SYS_TICK_FREQ (20000) // Hz - -// Enforce time quantum limits -// set to 1 for enabled, 0 for disabled -#define USER_CONFIG_ENABLE_TIME_QUANTUM_CHECKING (1) - // Enable task statistic collection by default // NOTE: The user can still go and enable the stats themselves if this is set to 0! // set to 1 for enabled, 0 for disabled diff --git a/sdk/freertos_app_cpu1/.cproject b/sdk/freertos_app_cpu1/.cproject index f04ca3b5..fdd09b8f 100644 --- a/sdk/freertos_app_cpu1/.cproject +++ b/sdk/freertos_app_cpu1/.cproject @@ -1,197 +1,274 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/freertos_app_cpu1/.project b/sdk/freertos_app_cpu1/.project index 0e6c64d2..cb5c2c83 100644 --- a/sdk/freertos_app_cpu1/.project +++ b/sdk/freertos_app_cpu1/.project @@ -1,38 +1,43 @@ - - - freertos_app_cpu1 - Created by SDK v2019.1. amdc_freertos_bsp_cpu1 - ps7_cortexa9_1 - - amdc_freertos_bsp_cpu1 - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - - - FreeRTOS-Kernel - 2 - S:/School/WEMPEC/firmware-rtos-e/sdk/FreeRTOS-Kernel - - - shared - 2 - S:/School/WEMPEC/firmware-rtos-e/sdk/shared - - - + + + freertos_app_cpu1 + Created by SDK v2019.1. amdc_freertos_bsp_cpu1 - ps7_cortexa9_1 + + amdc_bsp_cpu1 + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + FreeRTOS-Kernel + 2 + C:/Users/srich008/Information/v2-staging/sdk/FreeRTOS-Kernel + + + MemMang + 2 + C:/Users/srich008/Information/v2-staging/sdk/FreeRTOS-Kernel/portable/MemMang + + + shared + 2 + C:/Users/srich008/Information/v2-staging/sdk/shared + + + diff --git a/sdk/shared/drv/timer_stats.c b/sdk/shared/drv/timer_stats.c new file mode 100644 index 00000000..e0b62443 --- /dev/null +++ b/sdk/shared/drv/timer_stats.c @@ -0,0 +1,50 @@ +#include "drv/timer_stats.h" +#include "xparameters.h" +#include "xscugic.h" +#include "xscutimer.h" + +/* timer.h also uses TIMER_0_DEVICE_ID, meaning that it probably can't coexist with this timer. This should be changed (or they should be merged) */ +#define TIMER_DEVICE_ID XPAR_XSCUTIMER_0_DEVICE_ID +#define TIMER_LOAD_VALUE(period_usec) ((period_usec * 333.333) - 1) + +XScuTimer xTimerStats; + +// Cortex A9 Scu Private Timer Instance + +static void fatalError(char *str) +{ + xil_printf("TIMER ERROR: %s\n", str); + while (1) { + } +} + +void vInitialiseTimerForRunTimeStats() { + int Status; + XScuTimer_Config *ConfigPtr; + + // Initialize the Scu Private Timer driver + ConfigPtr = XScuTimer_LookupConfig(TIMER_DEVICE_ID); + + // This is where the virtual address would be used, this example uses physical address + Status = XScuTimer_CfgInitialize(&xTimerStats, ConfigPtr, ConfigPtr->BaseAddr); + if (Status != XST_SUCCESS) { + fatalError("Error 1"); + return; + } + + // Perform a self-test to ensure that the hardware was built correctly + Status = XScuTimer_SelfTest(&xTimerStats); + if (Status != XST_SUCCESS) { + fatalError("Error 2"); + return; + } + + // Enable Auto reload mode + XScuTimer_EnableAutoReload(&xTimerStats); + + // Load the timer counter register + XScuTimer_LoadTimer(&xTimerStats, TIMER_LOAD_VALUE(TIMER_STATS_USEC)); + + // Start the timer counter + XScuTimer_Start(&xTimerStats); +} diff --git a/sdk/shared/drv/timer_stats.h b/sdk/shared/drv/timer_stats.h new file mode 100644 index 00000000..db46d268 --- /dev/null +++ b/sdk/shared/drv/timer_stats.h @@ -0,0 +1,17 @@ +/* + * timer_stats.h + * + * Created on: Jul 11, 2024 + * Author: Ryan Srichai + * Notes: The timer described in + * https://www.freertos.org/rtos-run-time-stats.html + */ + +#ifndef DRV_TIMER_STATS_H_ +#define DRV_TIMER_STATS_H_ + +#define TIMER_STATS_USEC 10 // timer is 10x faster than FreeRTOS tick rate (which is set to 10000 ticks a second). This stats timer runs at 100KHz + +void vInitialiseTimerForRunTimeStats(); + +#endif /* DRV_TIMER_STATS_H_ */ diff --git a/sdk/app_cpu1/common/drv/uart.c b/sdk/shared/drv/uart.c similarity index 99% rename from sdk/app_cpu1/common/drv/uart.c rename to sdk/shared/drv/uart.c index 933f936b..58784b5b 100644 --- a/sdk/app_cpu1/common/drv/uart.c +++ b/sdk/shared/drv/uart.c @@ -1,4 +1,4 @@ -#include "drv/uart.h" +#include "uart.h" #include "sys/defines.h" #include "xparameters.h" #include "xuartps.h" diff --git a/sdk/app_cpu1/common/drv/uart.h b/sdk/shared/drv/uart.h similarity index 100% rename from sdk/app_cpu1/common/drv/uart.h rename to sdk/shared/drv/uart.h diff --git a/sdk/app_cpu1/common/sys/cmd/cmd_counter.c b/sdk/shared/sys/cmd/cmd_counter.c similarity index 100% rename from sdk/app_cpu1/common/sys/cmd/cmd_counter.c rename to sdk/shared/sys/cmd/cmd_counter.c diff --git a/sdk/app_cpu1/common/sys/cmd/cmd_counter.h b/sdk/shared/sys/cmd/cmd_counter.h similarity index 100% rename from sdk/app_cpu1/common/sys/cmd/cmd_counter.h rename to sdk/shared/sys/cmd/cmd_counter.h diff --git a/sdk/app_cpu1/common/sys/cmd/cmd_help.c b/sdk/shared/sys/cmd/cmd_help.c similarity index 100% rename from sdk/app_cpu1/common/sys/cmd/cmd_help.c rename to sdk/shared/sys/cmd/cmd_help.c diff --git a/sdk/app_cpu1/common/sys/cmd/cmd_help.h b/sdk/shared/sys/cmd/cmd_help.h similarity index 100% rename from sdk/app_cpu1/common/sys/cmd/cmd_help.h rename to sdk/shared/sys/cmd/cmd_help.h diff --git a/sdk/shared/sys/commands.c b/sdk/shared/sys/commands.c new file mode 100644 index 00000000..88902ffe --- /dev/null +++ b/sdk/shared/sys/commands.c @@ -0,0 +1,663 @@ +/* FreeRTOS includes */ +#include "FreeRTOS.h" +#include "task.h" +/* other includes */ +#include "sys/commands.h" +// #include "drv/encoder.h" +#include "drv/uart.h" +#include "sys/cmd/cmd_help.h" +#include "sys/debug.h" +#include "sys/defines.h" +#include "sys/icc.h" +// #include "sys/icc_tx.h" +// #include "sys/log.h" +// #include "sys/scheduler.h" +#include "sys/serial.h" +#include "sys/util.h" +#include "sys/task_priority.h" +#include +#include +#include +#include + +#define RECV_BUFFER_LENGTH (4 * 1024) + +typedef enum cmd_parsing_state_e { + BEGIN = 0, + LOOKING_FOR_SPACE, + LOOKING_FOR_CHAR, +} cmd_parsing_state_e; + +#define CMD_MAX_ARGC (16) // # of args accepted +#define CMD_MAX_ARG_LENGTH (32) // max chars of any arg +typedef struct pending_cmd_t { + int argc; + char *argv[CMD_MAX_ARGC]; + + // Used by parser to keep track of how + // long the argument is. If too long, + // throws an error! + int curr_arg_length; + + // Error flag set by parser task + int err; + + // Set to 1 to indicate ready to execute, + // 0 means not valid + int ready; +} pending_cmd_t; + +// Note, this must be >= 2. +// +// We always need a buffer to be filling while we +// execute the previous command +// +#define MAX_PENDING_CMDS (8) + +typedef struct { + cmd_parsing_state_e state; + + // Store parsed cmds + pending_cmd_t pending_cmds[MAX_PENDING_CMDS]; + int pending_cmd_write_idx; + int pending_cmd_read_idx; + + // Store rx chars + char recv_buffer[RECV_BUFFER_LENGTH]; + int recv_buffer_idx; +} sm_parse_ascii_cmd_ctx_t; + +static sm_parse_ascii_cmd_ctx_t ctx_uart; +static sm_parse_ascii_cmd_ctx_t ctx_eth; + +static int _command_handler(int argc, char **argv); + +static void commands_main_uart(void *arg); +//static void commands_callback_parse_eth(void *arg); +//static void commands_callback_exec(void *arg); + +// Head of linked list of commands +static command_entry_t *cmds = NULL; + +static TaskHandle_t tcb_parse_uart; +//static TaskHandle_t tcb_parse_eth; +//static TaskHandle_t tcb_exec_uart; +//static TaskHandle_t tcb_exec_eth; + +// The command response data should either go out UART or ETH, +// depending on the command source. Therefore, we'll define +// global general command response functions which users will +// use for their cmd response. This "commands" module will +// update these functions to target the correct stream. + +typedef enum cmd_src_e { + CMD_SRC_UART = 0, + CMD_SRC_ETH, +} cmd_src_e; + +static cmd_src_e current_cmd_source = CMD_SRC_UART; + +//void cmd_resp_write(char *msg, int len) +//{ +// if (current_cmd_source == CMD_SRC_UART) { +// serial_write(msg, len); +// } else { +// for (int i = 0; i < len; i++) { +// icc_tx_append_char_to_fifo(msg[i]); +// } +// } +//} + +void cmd_resp_print(char *msg) +{ + if (current_cmd_source == CMD_SRC_UART) { + debug_print(msg); + } else { +// cmd_resp_write(msg, strlen(msg)); + } +} + +#define PRINTF_BUFFER_LENGTH (1024) +static char buffer[PRINTF_BUFFER_LENGTH] = { 0 }; +void cmd_resp_printf(const char *format, ...) +{ + va_list vargs; + va_start(vargs, format); + vsnprintf(buffer, PRINTF_BUFFER_LENGTH, format, vargs); + cmd_resp_print(buffer); + va_end(vargs); +} + +void commands_init(void) +{ + printf("CMD:\tInitializing command tasks...\n"); + + // Command parse & exec task (UART) + xTaskCreate(commands_main_uart, (const char *) "command_parse_uart", configMINIMAL_STACK_SIZE, + NULL, CMD_UART_TASK_PRIORITY, &tcb_parse_uart); + +// // Command parse task (ETH) +// scheduler_tcb_init( +// &tcb_parse_eth, commands_callback_parse_eth, &ctx_eth, "command_parse_eth", COMMANDS_INTERVAL_USEC); +// scheduler_tcb_register(&tcb_parse_eth); +// +// // Command exec task (UART) +// scheduler_tcb_init(&tcb_exec_uart, commands_callback_exec, &ctx_uart, "command_exec_uart", COMMANDS_INTERVAL_USEC); +// scheduler_tcb_register(&tcb_exec_uart); +// +// // Command exec task (ETH) +// scheduler_tcb_init(&tcb_exec_eth, commands_callback_exec, &ctx_eth, "command_exec_eth", COMMANDS_INTERVAL_USEC); +// scheduler_tcb_register(&tcb_exec_eth); + + cmd_help_register(); +} + +// Set if we should echo back characters to sender: +// - 0: when EXECUTING the pending command +// - 1: when PROCESSING the incoming chars +// +// Both have pros and cons... For slow comms, we want +// to echo AS the chars come in since the user is likely +// using a UART terminal and wants to see a response to +// their inputs. +// +// For fast comms (i.e. Ethernet), we should only echo +// when the command is executed since the host could send +// a burst of multiple command strings in short time, +// before we have time to actually run the command. +// +// We will choose when PROCESSING the incoming chars and +// limit the command through-put from the host to: +// <= 1 command string per 100 usec time slice +// This will ensure we process the pending command before +// the next set of chars appears. +#define ECHO_BACK_WHEN_PROCESSING_INCOMING_CHARS (1) + +static void _create_pending_cmds(sm_parse_ascii_cmd_ctx_t *ctx, char *buffer, int length) +{ + // Get current pending cmd slot + pending_cmd_t *p = &ctx->pending_cmds[ctx->pending_cmd_write_idx]; + + for (int i = 0; i < length; i++) { + char c = buffer[i]; + + if (ctx->state != BEGIN && (c == '\n' || c == '\r')) { + // End of a command! + + // Set error flag if this arg was too long + if (p->curr_arg_length > CMD_MAX_ARG_LENGTH) { + p->err = CMD_INPUT_TOO_LONG; + } + + // Put a NULL at the end of the last cmd arg + // (replaces a \r or \n, so nbd + buffer[i] = 0; + +#if ECHO_BACK_WHEN_PROCESSING_INCOMING_CHARS == 1 + // Make console go to beginning of next line + if (ctx == &ctx_uart) { + debug_print("\r\n"); + } else { +// icc_tx_append_char_to_fifo('\r'); +// icc_tx_append_char_to_fifo('\n'); + } +#endif + + p->ready = 1; + + // Update current pending cmd slot + if (++ctx->pending_cmd_write_idx >= MAX_PENDING_CMDS) { + ctx->pending_cmd_write_idx = 0; + } + p = &ctx->pending_cmds[ctx->pending_cmd_write_idx]; + p->ready = 0; + + // Move on to next char, which starts + // next command sequence + ctx->state = BEGIN; + continue; + } + +#if ECHO_BACK_WHEN_PROCESSING_INCOMING_CHARS == 1 + // Echo character back to host + if (ctx == &ctx_uart) { + serial_write(&c, 1); + } else { +// icc_tx_append_char_to_fifo(c); + } +#endif + + // Process incoming char `c` + switch (ctx->state) { + case BEGIN: + if (!isspace(c)) { + // Populate first argument + p->argc = 1; + p->argv[0] = &buffer[i]; + p->err = CMD_SUCCESS; // Assume the parsing will work! + p->curr_arg_length = 1; + ctx->state = LOOKING_FOR_SPACE; + } + break; + + case LOOKING_FOR_SPACE: + if (c != ' ') { + p->curr_arg_length++; + } + + if (c == ' ') { + // End of chars for the arg + + // Set error flag if this arg was too long + if (p->curr_arg_length > CMD_MAX_ARG_LENGTH) { + p->err = CMD_INPUT_TOO_LONG; + } + + // Put NULL at end of arg (replaces ' ') + buffer[i] = 0; + + ctx->state = LOOKING_FOR_CHAR; + } + break; + + case LOOKING_FOR_CHAR: + if (c != ' ') { + p->argv[p->argc] = &buffer[i]; + p->argc++; + + // Check if argc too big! + if (p->argc > CMD_MAX_ARGC) { + p->err = CMD_INPUT_TOO_LONG; + + // Put argc back to zero... + // NOTE: this ensure no buffer overruns, + // but, screws up previous args. + // This is okay as we are going to + // throw away this pending cmd! + p->argc = 0; + } + + p->curr_arg_length = 1; + ctx->state = LOOKING_FOR_SPACE; + } + break; + + default: + // Impossible! + HANG; + break; + } + } +} + +static void commands_main_uart(void *arg) +{ + sm_parse_ascii_cmd_ctx_t *ctx = &ctx_uart; + for (;;) { + vTaskDelay(COMMANDS_INTERVAL_TICKS); + + // Read in bounded chunk of new chars + // + // NOTE: careful not to try and read too much! + // would cause a buffer overrun! + // + int try_to_read = MIN(UART_RX_FIFO_LENGTH, RECV_BUFFER_LENGTH - ctx->recv_buffer_idx); + int num_bytes = uart_recv(&ctx->recv_buffer[ctx->recv_buffer_idx], try_to_read); + + // Run state machine to create pending cmds to execute + _create_pending_cmds(ctx, &ctx->recv_buffer[ctx->recv_buffer_idx], num_bytes); + + // Move along in recv buffer + ctx->recv_buffer_idx += num_bytes; + if (ctx->recv_buffer_idx >= RECV_BUFFER_LENGTH) { + ctx->recv_buffer_idx = 0; + } + + + + + // Get current pending cmd slot + pending_cmd_t *p = &ctx->pending_cmds[ctx->pending_cmd_read_idx]; + + if (p->ready) { + // Run me! + + // Change current cmd source + if (ctx == &ctx_uart) { + current_cmd_source = CMD_SRC_UART; + } else if (ctx == &ctx_eth) { + current_cmd_source = CMD_SRC_ETH; + } else { + // unreachable + } + + #if ECHO_BACK_WHEN_PROCESSING_INCOMING_CHARS == 0 + // Echo back command to sender + for (int i = 0; i < p->argc; i++) { + cmd_resp_printf("%s", p->argv[i]); + + if (i + 1 < p->argc) { + cmd_resp_print(" "); + } + } + cmd_resp_print("\r\n"); + #endif + + // Don't run a cmd that has errors + int err = p->err; + if (err == CMD_SUCCESS) { + err = _command_handler(p->argc, p->argv); + } + + // Display command status to user + switch (err) { + case CMD_SUCCESS_QUIET: + // Don't print anything + break; + + case CMD_SUCCESS: + cmd_resp_printf("SUCCESS\r\n\n"); + break; + + case CMD_FAILURE: + cmd_resp_printf("FAILURE\r\n\n"); + break; + + case CMD_INVALID_ARGUMENTS: + cmd_resp_printf("INVALID ARGUMENTS\r\n\n"); + break; + + case CMD_INPUT_TOO_LONG: + cmd_resp_printf("INPUT TOO LONG\r\n\n"); + break; + + case CMD_UNKNOWN_CMD: + cmd_resp_printf("UNKNOWN CMD\r\n\n"); + break; + + default: + cmd_resp_printf("UNKNOWN ERROR\r\n\n"); + break; + } + + p->ready = 0; + + // Update READ index + if (++ctx->pending_cmd_read_idx >= MAX_PENDING_CMDS) { + ctx->pending_cmd_read_idx = 0; + } + } + } +} + +//static void commands_callback_parse_eth(void *arg) +//{ +// sm_parse_ascii_cmd_ctx_t *ctx = (sm_parse_ascii_cmd_ctx_t *) arg; +// +// static const int MAX_NUM_BYTES_TO_TRY = 128; +// +// // Try to pull out the oldest MAX_NUM_BYTES_TO_TRY bytes from the shared FIFO from CPU0 +// // +// // If there are less than MAX_NUM_BYTES_TO_TRY bytes in the FIFO, this code will simply +// // pull out everything and return. +// for (int i = 0; i < MAX_NUM_BYTES_TO_TRY; i++) { +// // Check if there are any bytes in the FIFO +// if (ICC_CPU0to1_CH0__GET_ProduceCount - ICC_CPU0to1_CH0__GET_ConsumeCount == 0) { +// // Shared buffer is empty +// return; +// } +// +// // Read the oldest byte available +// uint8_t *sharedBuffer = ICC_CPU0to1_CH0__BufferBaseAddr; +// uint8_t c = sharedBuffer[ICC_CPU0to1_CH0__GET_ConsumeCount % ICC_BUFFER_SIZE]; +// +// // Increment the consume count +// ICC_CPU0to1_CH0__SET_ConsumeCount(ICC_CPU0to1_CH0__GET_ConsumeCount + 1); +// +// // ===================== +// // Process incoming char +// // ===================== +// +// char c_char = (char) c; +// +// // Push the new byte into the rx buffer +// ctx->recv_buffer[ctx->recv_buffer_idx] = c_char; +// +// // Run state machine to create pending cmds to execute +// _create_pending_cmds(ctx, &ctx->recv_buffer[ctx->recv_buffer_idx], 1); +// +// // Move along in recv buffer +// ctx->recv_buffer_idx += 1; +// if (ctx->recv_buffer_idx >= RECV_BUFFER_LENGTH) { +// ctx->recv_buffer_idx = 0; +// } +// } +//} + +//static void commands_callback_exec(void *arg) +//{ +// sm_parse_ascii_cmd_ctx_t *ctx = (sm_parse_ascii_cmd_ctx_t *) arg; +// +// // Get current pending cmd slot +// pending_cmd_t *p = &ctx->pending_cmds[ctx->pending_cmd_read_idx]; +// +// if (p->ready) { +// // Run me! +// +// // Change current cmd source +// if (ctx == &ctx_uart) { +// current_cmd_source = CMD_SRC_UART; +// } else if (ctx == &ctx_eth) { +// current_cmd_source = CMD_SRC_ETH; +// } else { +// // unreachable +// } +// +//#if ECHO_BACK_WHEN_PROCESSING_INCOMING_CHARS == 0 +// // Echo back command to sender +// for (int i = 0; i < p->argc; i++) { +// cmd_resp_printf("%s", p->argv[i]); +// +// if (i + 1 < p->argc) { +// cmd_resp_print(" "); +// } +// } +// cmd_resp_print("\r\n"); +//#endif +// +// // Don't run a cmd that has errors +// int err = p->err; +// if (err == CMD_SUCCESS) { +// err = _command_handler(p->argc, p->argv); +// } +// +// // Display command status to user +// switch (err) { +// case CMD_SUCCESS_QUIET: +// // Don't print anything +// break; +// +// case CMD_SUCCESS: +// cmd_resp_printf("SUCCESS\r\n\n"); +// break; +// +// case CMD_FAILURE: +// cmd_resp_printf("FAILURE\r\n\n"); +// break; +// +// case CMD_INVALID_ARGUMENTS: +// cmd_resp_printf("INVALID ARGUMENTS\r\n\n"); +// break; +// +// case CMD_INPUT_TOO_LONG: +// cmd_resp_printf("INPUT TOO LONG\r\n\n"); +// break; +// +// case CMD_UNKNOWN_CMD: +// cmd_resp_printf("UNKNOWN CMD\r\n\n"); +// break; +// +// default: +// cmd_resp_printf("UNKNOWN ERROR\r\n\n"); +// break; +// } +// +// p->ready = 0; +// +// // Update READ index +// if (++ctx->pending_cmd_read_idx >= MAX_PENDING_CMDS) { +// ctx->pending_cmd_read_idx = 0; +// } +// } +//} + +void commands_cmd_init(command_entry_t *cmd_entry, + const char *cmd, + const char *desc, + command_help_t *help, + int num_help_cmds, + int (*cmd_function)(int, char **)) +{ + cmd_entry->cmd = cmd; + cmd_entry->desc = desc; + cmd_entry->help = help; + cmd_entry->num_help_cmds = num_help_cmds; + cmd_entry->cmd_function = cmd_function; + cmd_entry->next = NULL; +} + +void commands_cmd_register(command_entry_t *cmd_entry) +{ + // Base case: there are no tasks in linked list + if (cmds == NULL) { + cmds = cmd_entry; + cmds->next = NULL; + return; + } + + // Find end of list + command_entry_t *curr = cmds; + while (curr->next != NULL) + curr = curr->next; + + // Append new cmd to end of list + curr->next = cmd_entry; + cmd_entry->next = NULL; +} + +void commands_start_msg(void) +{ + cmd_resp_printf("\r\n"); + commands_display_help(); +} + +// _command_handler +// +// Takes `argc` and `argv` and finds +// the command function to call. +// +int _command_handler(int argc, char **argv) +{ + command_entry_t *c = cmds; + + while (c != NULL) { + if (strcmp(argv[0], c->cmd) == 0) { + // Found command to run! + return c->cmd_function(argc, argv); + } + + c = c->next; + } + + return CMD_UNKNOWN_CMD; +} + +// ***************** +// State Machine +// which outputs +// the help messages +// ***************** + +typedef enum sm_states_e { TITLE1 = 1, TITLE2, TITLE3, CMD_HEADER, SUB_CMD, REMOVE_TASK } sm_states_e; + +typedef struct sm_ctx_t { + sm_states_e state; + command_entry_t *curr; + int sub_cmd_idx; + TaskHandle_t tcb; +} sm_ctx_t; + +static sm_ctx_t ctxG; + +#define SM_UPDATES_PER_SEC (10000) +#define SM_INTERVAL_TICKS (pdMS_TO_TICKS(1000.0 / SM_UPDATES_PER_SEC)) + +void help_state_machine(void *arg) +{ + sm_ctx_t *ctx = &ctxG; + for (;;) { + vTaskDelay(SM_INTERVAL_TICKS); + switch (ctx->state) { + case TITLE1: + cmd_resp_printf("\r\n"); + + ctx->curr = cmds; + ctx->state = TITLE2; + break; + + case TITLE2: + cmd_resp_printf("Available commands:\r\n"); + ctx->state = TITLE3; + break; + + case TITLE3: + cmd_resp_printf("-------------------\r\n"); + ctx->state = CMD_HEADER; + break; + + case CMD_HEADER: + if (ctx->curr == NULL) { + // DONE! + cmd_resp_printf("\r\n"); + ctx->state = REMOVE_TASK; + } else { + cmd_resp_printf("%s -- %s\r\n", ctx->curr->cmd, ctx->curr->desc); + ctx->sub_cmd_idx = 0; + ctx->state = SUB_CMD; + } + break; + + case SUB_CMD: + if (ctx->sub_cmd_idx >= ctx->curr->num_help_cmds) { + ctx->curr = ctx->curr->next; + ctx->state = CMD_HEADER; + } else { + command_help_t *h = &ctx->curr->help[ctx->sub_cmd_idx++]; + cmd_resp_printf("\t%s -- %s\r\n", h->subcmd, h->desc); + } + break; + + case REMOVE_TASK: + cmd_resp_printf("SUCCESS\r\n\n"); + vTaskDelete(ctx->tcb); + break; + + default: + // Can't happen + HANG; + break; + } + } +} + +void commands_display_help(void) +{ + // Initialize the state machine context + ctxG.state = TITLE1; + ctxG.curr = cmds; + ctxG.sub_cmd_idx = 0; + + // Initialize the state machine callback tcb (with high priority) + xTaskCreate(help_state_machine, (const char *) "command_help", configMINIMAL_STACK_SIZE, + NULL, configMAX_PRIORITIES - 1, &ctxG.tcb); +} diff --git a/sdk/app_cpu1/common/sys/commands.h b/sdk/shared/sys/commands.h similarity index 94% rename from sdk/app_cpu1/common/sys/commands.h rename to sdk/shared/sys/commands.h index 239a22c9..652e6151 100644 --- a/sdk/app_cpu1/common/sys/commands.h +++ b/sdk/shared/sys/commands.h @@ -1,10 +1,10 @@ #ifndef COMMANDS_H #define COMMANDS_H -#include "sys/scheduler.h" +#include "projdefs.h" #define COMMANDS_UPDATES_PER_SEC (10000) -#define COMMANDS_INTERVAL_USEC (USEC_IN_SEC / COMMANDS_UPDATES_PER_SEC) +#define COMMANDS_INTERVAL_TICKS (pdMS_TO_TICKS(1000.0 / COMMANDS_UPDATES_PER_SEC)) // Supported command handler return codes // diff --git a/sdk/app_cpu1/common/sys/debug.c b/sdk/shared/sys/debug.c similarity index 100% rename from sdk/app_cpu1/common/sys/debug.c rename to sdk/shared/sys/debug.c diff --git a/sdk/app_cpu1/common/sys/debug.h b/sdk/shared/sys/debug.h similarity index 100% rename from sdk/app_cpu1/common/sys/debug.h rename to sdk/shared/sys/debug.h diff --git a/sdk/app_cpu1/common/sys/defines.h b/sdk/shared/sys/defines.h similarity index 100% rename from sdk/app_cpu1/common/sys/defines.h rename to sdk/shared/sys/defines.h diff --git a/sdk/shared/sys/intr.c b/sdk/shared/sys/intr.c index 253dcbbc..8110b806 100644 --- a/sdk/shared/sys/intr.c +++ b/sdk/shared/sys/intr.c @@ -21,6 +21,8 @@ * See sys/icc.c for more info. */ +XScuGic InterruptController; + int intr_init() { int Status = XST_FAILURE; diff --git a/sdk/shared/sys/intr.h b/sdk/shared/sys/intr.h index 137771a4..ab0a1164 100644 --- a/sdk/shared/sys/intr.h +++ b/sdk/shared/sys/intr.h @@ -34,7 +34,7 @@ // Interrupt Controller Instance // Defined here to be accessable in sys/icc.c -static XScuGic InterruptController; +extern XScuGic InterruptController; int intr_init(); diff --git a/sdk/app_cpu1/common/sys/serial.c b/sdk/shared/sys/serial.c similarity index 50% rename from sdk/app_cpu1/common/sys/serial.c rename to sdk/shared/sys/serial.c index cd9d07c9..a8743a01 100644 --- a/sdk/app_cpu1/common/sys/serial.c +++ b/sdk/shared/sys/serial.c @@ -1,7 +1,11 @@ +/* FreeRTOS includes */ +#include "FreeRTOS.h" +#include "task.h" +/* Other includes */ #include "sys/serial.h" #include "drv/uart.h" -#include "sys/scheduler.h" #include "sys/util.h" +#include "sys/task_priority.h" #include #define OUTPUT_BUFFER_LENGTH (32 * 1024) @@ -18,38 +22,42 @@ static int print_idx = -1; // Amount of chars we need to print at the moment static int print_amount = 0; -static task_control_block_t tcb; +/* task handle */ +static TaskHandle_t xSerialTaskHandle; void serial_init(void) { - printf("DB:\tInitializing serial task...\n"); - scheduler_tcb_init(&tcb, serial_callback, NULL, "serial", SERIAL_INTERVAL_USEC); - scheduler_tcb_register(&tcb); + // Create serial task + xTaskCreate(serial_main, (const char *) "uartSerial", configMINIMAL_STACK_SIZE, + NULL, SERIAL_TASK_PRIORITY, &xSerialTaskHandle); } -void serial_callback(void *arg) +void serial_main(void *arg) { - if (print_amount > 0) { - // Have work to do! - - // Determine amount of chars to print before buffer wrap - int try_to_send = MIN(print_amount, OUTPUT_BUFFER_LENGTH - print_idx); - - // Try to send that amount of chars to the UART - int bytes_sent = uart_send(&output_buffer[print_idx], try_to_send); - print_amount -= bytes_sent; - - // UART TX FIFO might have been full, so didn't print all we tried - print_idx += bytes_sent; - if (print_idx >= OUTPUT_BUFFER_LENGTH) { - print_idx = 0; - } - - // Check if done outputting data - if (print_amount == 0) { - print_idx = -1; - } - } + for (;;) { + vTaskDelay(SERIAL_INTERVAL_TICKS); + if (print_amount > 0) { + // Have work to do! + + // Determine amount of chars to print before buffer wrap + int try_to_send = MIN(print_amount, OUTPUT_BUFFER_LENGTH - print_idx); + + // Try to send that amount of chars to the UART + int bytes_sent = uart_send(&output_buffer[print_idx], try_to_send); + print_amount -= bytes_sent; + + // UART TX FIFO might have been full, so didn't print all we tried + print_idx += bytes_sent; + if (print_idx >= OUTPUT_BUFFER_LENGTH) { + print_idx = 0; + } + + // Check if done outputting data + if (print_amount == 0) { + print_idx = -1; + } + } + } } static void _append_to_output_buffer(char c) diff --git a/sdk/app_cpu1/common/sys/serial.h b/sdk/shared/sys/serial.h similarity index 54% rename from sdk/app_cpu1/common/sys/serial.h rename to sdk/shared/sys/serial.h index bcf9e646..a0d56aa0 100644 --- a/sdk/app_cpu1/common/sys/serial.h +++ b/sdk/shared/sys/serial.h @@ -1,13 +1,11 @@ #ifndef SERIAL_H #define SERIAL_H -#include "sys/scheduler.h" - #define SERIAL_UPDATES_PER_SEC (10000) -#define SERIAL_INTERVAL_USEC (USEC_IN_SEC / SERIAL_UPDATES_PER_SEC) +#define SERIAL_INTERVAL_TICKS (pdMS_TO_TICKS(1000.0 / SERIAL_UPDATES_PER_SEC)) void serial_init(void); -void serial_callback(void *arg); +void serial_main(void *arg); void serial_write(char *msg, int len); diff --git a/sdk/shared/sys/task_priority.h b/sdk/shared/sys/task_priority.h new file mode 100644 index 00000000..61bc24b2 --- /dev/null +++ b/sdk/shared/sys/task_priority.h @@ -0,0 +1,13 @@ +#ifndef TASK_PRIORITY_H +#define TASK_PRIORITY_H + +/* sys tasks */ +#define SERIAL_TASK_PRIORITY tskIDLE_PRIORITY +#define CMD_UART_TASK_PRIORITY tskIDLE_PRIORITY +#define CMD_ETH_TASK_PRIORITY tskIDLE_PRIORITY + +/* blink app */ +#define BLINK_TASK_PRIORITY tskIDLE_PRIORITY +#define VSI_TASK_PRIORITY tskIDLE_PRIORITY + +#endif // TASK_PRIORITY_H diff --git a/sdk/app_cpu1/common/sys/util.h b/sdk/shared/sys/util.h similarity index 100% rename from sdk/app_cpu1/common/sys/util.h rename to sdk/shared/sys/util.h