From e834c5d386278923f9f03c7daae5b5fe8793cdb8 Mon Sep 17 00:00:00 2001 From: Ryan Srichai Date: Wed, 17 Jul 2024 16:23:41 -0500 Subject: [PATCH 01/17] temp branch to reduce file changes --- sdk/FreeRTOS-Kernel | 2 +- sdk/freertos_app_cpu0/.cproject | 456 ++++++------ sdk/freertos_app_cpu0/.project | 76 +- sdk/freertos_app_cpu0/src/FreeRTOSConfig.h | 498 ++++++------- sdk/freertos_app_cpu0/src/Xilinx.spec | 4 +- sdk/freertos_app_cpu0/src/main.c | 305 ++------ sdk/freertos_app_cpu0/src/usr/game/app_game.c | 16 + sdk/freertos_app_cpu0/src/usr/game/app_game.h | 6 + .../src/usr/game/cmd/cmd_game.c | 106 +++ .../src/usr/game/cmd/cmd_game.h | 12 + .../src/usr/game/task_game.c | 140 ++++ .../src/usr/game/task_game.h | 48 ++ sdk/freertos_app_cpu0/src/usr/user_apps.c | 68 ++ sdk/freertos_app_cpu0/src/usr/user_apps.h | 6 + sdk/freertos_app_cpu0/src/usr/user_config.h | 6 + sdk/freertos_app_cpu1/.cproject | 471 +++++++------ sdk/freertos_app_cpu1/.project | 81 ++- sdk/freertos_app_cpu1/src/FreeRTOSConfig.h | 494 ++++++------- sdk/freertos_app_cpu1/src/Xilinx.spec | 4 +- sdk/shared/FreeRTOS_tick_config.c | 276 ++++---- sdk/shared/README.md | 60 +- sdk/shared/drv/uart.c | 115 +++ sdk/shared/drv/uart.h | 14 + sdk/shared/platform_config.h | 12 +- sdk/shared/sys/cmd/cmd_counter.c | 54 ++ sdk/shared/sys/cmd/cmd_counter.h | 8 + sdk/shared/sys/cmd/cmd_help.c | 29 + sdk/shared/sys/cmd/cmd_help.h | 8 + sdk/shared/sys/commands.c | 662 ++++++++++++++++++ sdk/shared/sys/commands.h | 61 ++ sdk/shared/sys/debug.c | 24 + sdk/shared/sys/debug.h | 7 + sdk/shared/sys/defines.h | 28 + sdk/shared/sys/icc.c | 182 ++--- sdk/shared/sys/icc.h | 178 ++--- sdk/shared/sys/intr.c | 228 +++--- sdk/shared/sys/intr.h | 102 +-- sdk/shared/sys/serial.c | 85 +++ sdk/shared/sys/serial.h | 12 + sdk/shared/sys/util.h | 22 + 40 files changed, 3233 insertions(+), 1733 deletions(-) create mode 100644 sdk/freertos_app_cpu0/src/usr/game/app_game.c create mode 100644 sdk/freertos_app_cpu0/src/usr/game/app_game.h create mode 100644 sdk/freertos_app_cpu0/src/usr/game/cmd/cmd_game.c create mode 100644 sdk/freertos_app_cpu0/src/usr/game/cmd/cmd_game.h create mode 100644 sdk/freertos_app_cpu0/src/usr/game/task_game.c create mode 100644 sdk/freertos_app_cpu0/src/usr/game/task_game.h create mode 100644 sdk/freertos_app_cpu0/src/usr/user_apps.c create mode 100644 sdk/freertos_app_cpu0/src/usr/user_apps.h create mode 100644 sdk/freertos_app_cpu0/src/usr/user_config.h create mode 100644 sdk/shared/drv/uart.c create mode 100644 sdk/shared/drv/uart.h create mode 100644 sdk/shared/sys/cmd/cmd_counter.c create mode 100644 sdk/shared/sys/cmd/cmd_counter.h create mode 100644 sdk/shared/sys/cmd/cmd_help.c create mode 100644 sdk/shared/sys/cmd/cmd_help.h create mode 100644 sdk/shared/sys/commands.c create mode 100644 sdk/shared/sys/commands.h create mode 100644 sdk/shared/sys/debug.c create mode 100644 sdk/shared/sys/debug.h create mode 100644 sdk/shared/sys/defines.h create mode 100644 sdk/shared/sys/serial.c create mode 100644 sdk/shared/sys/serial.h create mode 100644 sdk/shared/sys/util.h 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/freertos_app_cpu0/.cproject b/sdk/freertos_app_cpu0/.cproject index 12744bde..0d032b50 100644 --- a/sdk/freertos_app_cpu0/.cproject +++ b/sdk/freertos_app_cpu0/.cproject @@ -1,198 +1,258 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/freertos_app_cpu0/.project b/sdk/freertos_app_cpu0/.project index 23ac0f12..30288dae 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/v2-staging/sdk/FreeRTOS-Kernel + + + shared + 2 + C:/Users/srich008/Information/v2-staging/sdk/shared + + + diff --git a/sdk/freertos_app_cpu0/src/FreeRTOSConfig.h b/sdk/freertos_app_cpu0/src/FreeRTOSConfig.h index b92d6969..4f3c1bd5 100644 --- a/sdk/freertos_app_cpu0/src/FreeRTOSConfig.h +++ b/sdk/freertos_app_cpu0/src/FreeRTOSConfig.h @@ -1,247 +1,251 @@ -/* README!!! - * - * This configuration is copied from the FreeRTOS v10.1.1 - * based example project for the Zynq 7000 platform (for - * compatibility). However, you can add to it. - * - * Another example configuration file is available at - * "sdk/FreeRTOS-Kernel/examples/sample_configuration/FreeRTOSConfig.h" - * Because that example is in the submodule, it may update - * from time-to-time when the submodule is updated. - */ - -/* - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * 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: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * 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. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - -#ifndef FREERTOS_CONFIG_H -#define FREERTOS_CONFIG_H - -#include "xparameters.h" - -/*----------------------------------------------------------- - * Application specific definitions. - * - * These definitions should be adjusted for your particular hardware and - * application requirements. - * - * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE - * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. - * - * See http://www.freertos.org/a00110.html - *----------------------------------------------------------*/ - -/* - * The FreeRTOS Cortex-A port implements a full interrupt nesting model. - * - * Interrupts that are assigned a priority at or below - * configMAX_API_CALL_INTERRUPT_PRIORITY (which counter-intuitively in the ARM - * generic interrupt controller [GIC] means a priority that has a numerical - * value above configMAX_API_CALL_INTERRUPT_PRIORITY) can call FreeRTOS safe API - * functions and will nest. - * - * Interrupts that are assigned a priority above - * configMAX_API_CALL_INTERRUPT_PRIORITY (which in the GIC means a numerical - * value below configMAX_API_CALL_INTERRUPT_PRIORITY) cannot call any FreeRTOS - * API functions, will nest, and will not be masked by FreeRTOS critical - * sections (although it is necessary for interrupts to be globally disabled - * extremely briefly as the interrupt mask is updated in the GIC). - * - * FreeRTOS functions that can be called from an interrupt are those that end in - * "FromISR". FreeRTOS maintains a separate interrupt safe API to enable - * interrupt entry to be shorter, faster, simpler and smaller. - * - * The Zynq implements 256 unique interrupt priorities. For the purpose of - * setting configMAX_API_CALL_INTERRUPT_PRIORITY 255 represents the lowest - * priority. - */ -#define configMAX_API_CALL_INTERRUPT_PRIORITY 18 - -#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 configPERIPHERAL_CLOCK_HZ (33333000UL) -#define configUSE_PREEMPTION 1 -#define configUSE_IDLE_HOOK 0 // TODO: For low-power, set 1 and implement vApplicationIdleHook() -#define configUSE_TICK_HOOK 0 // TODO: Set as 1 if we want to run function every tick -#define configMAX_PRIORITIES (7) -#define configTOTAL_HEAP_SIZE (125 * 1024) -#define configMAX_TASK_NAME_LEN (10) -#define configUSE_TRACE_FACILITY 1 -#define configUSE_16_BIT_TICKS 0 -#define configIDLE_SHOULD_YIELD 1 -#define configUSE_MUTEXES 1 -#define configQUEUE_REGISTRY_SIZE 8 -#define configCHECK_FOR_STACK_OVERFLOW 0 -#define configUSE_RECURSIVE_MUTEXES 1 -#define configUSE_MALLOC_FAILED_HOOK 0 -#define configUSE_APPLICATION_TASK_TAG 0 -#define configUSE_COUNTING_SEMAPHORES 1 -#define configUSE_QUEUE_SETS 1 -#define configSUPPORT_DYNAMIC_ALLOCATION 1 -#define configSUPPORT_STATIC_ALLOCATION 1 - -/* AMDC ADDITION: Need to specify this callback config so we can create message buffers with callbacks - * This is done for Inter-Core Communication (src/sys/icc.c) */ -#define configUSE_SB_COMPLETED_CALLBACK 1 - -/* Include the query-heap CLI command to query the free heap space. */ -#define configINCLUDE_QUERY_HEAP_COMMAND 1 - -/* Co-routine definitions. */ -#define configUSE_CO_ROUTINES 0 -#define configMAX_CO_ROUTINE_PRIORITIES (2) - -/* Software timer definitions. */ -#define configUSE_TIMERS 1 -#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) -#define configTIMER_QUEUE_LENGTH 5 -#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2) - -/* If configUSE_TASK_FPU_SUPPORT is set to 1 (or undefined) then each task will -be created without an FPU context, and a task must call vTaskUsesFPU() before -making use of any FPU registers. If configUSE_TASK_FPU_SUPPORT is set to 2 then -tasks are created with an FPU context by default, and calling vTaskUsesFPU() has -no effect. */ -#define configUSE_TASK_FPU_SUPPORT 2 -#define configMINIMAL_STACK_SIZE ((unsigned short) 250) // Large since all tasks have FPU context - -/* Set the following definitions to 1 to include the API function, or zero -to exclude the API function. */ -#define INCLUDE_vTaskPrioritySet 1 -#define INCLUDE_uxTaskPriorityGet 1 -#define INCLUDE_vTaskDelete 1 -#define INCLUDE_vTaskCleanUpResources 1 -#define INCLUDE_vTaskSuspend 1 -#define INCLUDE_vTaskDelayUntil 1 -#define INCLUDE_vTaskDelay 1 -#define INCLUDE_xTimerPendFunctionCall 1 -#define INCLUDE_eTaskGetState 1 -#define INCLUDE_xTaskAbortDelay 1 -#define INCLUDE_xTaskGetTaskHandle 1 -#define INCLUDE_xTaskGetHandle 1 -#define INCLUDE_xSemaphoreGetMutexHolder 1 - -/* This demo makes use of one or more example stats formatting functions. These -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 - -/* The private watchdog is used to generate run time stats. */ -/* -#include "xscuwdt.h" -extern XScuWdt xWatchDogInstance; -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 ) -*/ - -/* 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 -and one on TCP/IP). This is done to prevent an output buffer being defined by -each implementation - which would waste RAM. In this case, there is only one -command interpreter running. */ -#define configCOMMAND_INT_MAX_OUTPUT_SIZE 2096 - -/* Normal assert() semantics without relying on the provision of an assert.h -header file. */ -void vAssertCalled(const char *pcFile, unsigned long ulLine); - -// Original Implementation -//#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ ); - -#define configASSERT(x) \ - if ((x) == 0) \ - while (1) \ - ; - -/* If configTASK_RETURN_ADDRESS is not defined then a task that attempts to -return from its implementing function will end up in a "task exit error" -function - which contains a call to configASSERT(). However this can give GCC -some problems when it tries to unwind the stack, as the exit error function has -nothing to return to. To avoid this define configTASK_RETURN_ADDRESS to 0. */ -#define configTASK_RETURN_ADDRESS NULL - -/****** Hardware specific settings. *******************************************/ - -/* - * The application must provide a function that configures a peripheral to - * create the FreeRTOS tick interrupt, then define configSETUP_TICK_INTERRUPT() - * in FreeRTOSConfig.h to call the function. This file contains a function - * that is suitable for use on the Zynq MPU. FreeRTOS_Tick_Handler() must - * be installed as the peripheral's interrupt handler. - */ -void vConfigureTickInterrupt(void); -#define configSETUP_TICK_INTERRUPT() vConfigureTickInterrupt() - -void vClearTickInterrupt(void); -#define configCLEAR_TICK_INTERRUPT() vClearTickInterrupt() - -/* The following constant describe the hardware, and are correct for the -Zynq MPU. */ -#define configINTERRUPT_CONTROLLER_BASE_ADDRESS (XPAR_PS7_SCUGIC_0_DIST_BASEADDR) -#define configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET (-0xf00) -#define configUNIQUE_INTERRUPT_PRIORITIES 32 - -/****** Network configuration settings - only used when the lwIP example is -built. See the page that documents this demo on the http://www.FreeRTOS.org -website for more information. ***********************************************/ - -/* The priority for the task that unblocked by the MAC interrupt to process -received packets. */ -#define configMAC_INPUT_TASK_PRIORITY (configMAX_PRIORITIES - 1) - -/* The priority of the task that runs the lwIP stack. */ -#define configLWIP_TASK_PRIORITY (configMAX_PRIORITIES - 2) - -/* The priority of the task that uses lwIP sockets to provide a simple command -line interface. */ -#define configCLI_TASK_PRIORITY (tskIDLE_PRIORITY) - -/* MAC address configuration. */ -#define configMAC_ADDR0 0x00 -#define configMAC_ADDR1 0x13 -#define configMAC_ADDR2 0x14 -#define configMAC_ADDR3 0x15 -#define configMAC_ADDR4 0x15 -#define configMAC_ADDR5 0x16 - -/* IP address configuration. */ -#define configIP_ADDR0 172 -#define configIP_ADDR1 25 -#define configIP_ADDR2 218 -#define configIP_ADDR3 200 - -/* Netmask configuration. */ -#define configNET_MASK0 255 -#define configNET_MASK1 255 -#define configNET_MASK2 255 -#define configNET_MASK3 0 - -#endif /* FREERTOS_CONFIG_H */ +/* README!!! + * + * This configuration is copied from the FreeRTOS v10.1.1 + * based example project for the Zynq 7000 platform (for + * compatibility). However, you can add to it. + * + * Another example configuration file is available at + * "sdk/FreeRTOS-Kernel/examples/sample_configuration/FreeRTOSConfig.h" + * Because that example is in the submodule, it may update + * from time-to-time when the submodule is updated. + */ + +/* + * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#include "xparameters.h" + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html + *----------------------------------------------------------*/ + +/* + * The FreeRTOS Cortex-A port implements a full interrupt nesting model. + * + * Interrupts that are assigned a priority at or below + * configMAX_API_CALL_INTERRUPT_PRIORITY (which counter-intuitively in the ARM + * generic interrupt controller [GIC] means a priority that has a numerical + * value above configMAX_API_CALL_INTERRUPT_PRIORITY) can call FreeRTOS safe API + * functions and will nest. + * + * Interrupts that are assigned a priority above + * configMAX_API_CALL_INTERRUPT_PRIORITY (which in the GIC means a numerical + * value below configMAX_API_CALL_INTERRUPT_PRIORITY) cannot call any FreeRTOS + * API functions, will nest, and will not be masked by FreeRTOS critical + * sections (although it is necessary for interrupts to be globally disabled + * extremely briefly as the interrupt mask is updated in the GIC). + * + * FreeRTOS functions that can be called from an interrupt are those that end in + * "FromISR". FreeRTOS maintains a separate interrupt safe API to enable + * interrupt entry to be shorter, faster, simpler and smaller. + * + * The Zynq implements 256 unique interrupt priorities. For the purpose of + * setting configMAX_API_CALL_INTERRUPT_PRIORITY 255 represents the lowest + * priority. + */ +#define configMAX_API_CALL_INTERRUPT_PRIORITY 18 + +#define configCPU_CLOCK_HZ 100000000UL +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#define configUSE_TICKLESS_IDLE 0 +#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() +#define configUSE_TICK_HOOK 0 // TODO: Set as 1 if we want to run function every tick +#define configMAX_PRIORITIES (7) +#define configTOTAL_HEAP_SIZE (125 * 1024) +#define configMAX_TASK_NAME_LEN (10) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 8 +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_MALLOC_FAILED_HOOK 0 +#define configUSE_APPLICATION_TASK_TAG 0 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_QUEUE_SETS 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 +#define configSUPPORT_STATIC_ALLOCATION 1 + +/* AMDC ADDITION: Need to specify this callback config so we can create message buffers with callbacks + * This is done for Inter-Core Communication (src/sys/icc.c) */ +#define configUSE_SB_COMPLETED_CALLBACK 1 + +/* Include the query-heap CLI command to query the free heap space. */ +#define configINCLUDE_QUERY_HEAP_COMMAND 1 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES (2) + +/* Software timer definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) +#define configTIMER_QUEUE_LENGTH 5 +#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2) + +/* If configUSE_TASK_FPU_SUPPORT is set to 1 (or undefined) then each task will +be created without an FPU context, and a task must call vTaskUsesFPU() before +making use of any FPU registers. If configUSE_TASK_FPU_SUPPORT is set to 2 then +tasks are created with an FPU context by default, and calling vTaskUsesFPU() has +no effect. */ +#define configUSE_TASK_FPU_SUPPORT 2 +#define configMINIMAL_STACK_SIZE ((unsigned short) 250) // Large since all tasks have FPU context + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 1 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xTaskAbortDelay 1 +#define INCLUDE_xTaskGetTaskHandle 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 + +/* This demo makes use of one or more example stats formatting functions. These +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 + +/* The private watchdog is used to generate run time stats. */ +/* +#include "xscuwdt.h" +extern XScuWdt xWatchDogInstance; +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 ) +*/ + +/* 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 +and one on TCP/IP). This is done to prevent an output buffer being defined by +each implementation - which would waste RAM. In this case, there is only one +command interpreter running. */ +#define configCOMMAND_INT_MAX_OUTPUT_SIZE 2096 + +/* Normal assert() semantics without relying on the provision of an assert.h +header file. */ +void vAssertCalled(const char *pcFile, unsigned long ulLine); + +// Original Implementation +//#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ ); + +#define configASSERT(x) \ + if ((x) == 0) \ + while (1) \ + ; + +/* If configTASK_RETURN_ADDRESS is not defined then a task that attempts to +return from its implementing function will end up in a "task exit error" +function - which contains a call to configASSERT(). However this can give GCC +some problems when it tries to unwind the stack, as the exit error function has +nothing to return to. To avoid this define configTASK_RETURN_ADDRESS to 0. */ +#define configTASK_RETURN_ADDRESS NULL + +/****** Hardware specific settings. *******************************************/ + +/* + * The application must provide a function that configures a peripheral to + * create the FreeRTOS tick interrupt, then define configSETUP_TICK_INTERRUPT() + * in FreeRTOSConfig.h to call the function. This file contains a function + * that is suitable for use on the Zynq MPU. FreeRTOS_Tick_Handler() must + * be installed as the peripheral's interrupt handler. + */ +void vConfigureTickInterrupt(void); +#define configSETUP_TICK_INTERRUPT() vConfigureTickInterrupt() + +void vClearTickInterrupt(void); +#define configCLEAR_TICK_INTERRUPT() vClearTickInterrupt() + +/* The following constant describe the hardware, and are correct for the +Zynq MPU. */ +#define configINTERRUPT_CONTROLLER_BASE_ADDRESS (XPAR_PS7_SCUGIC_0_DIST_BASEADDR) +#define configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET (-0xf00) +#define configUNIQUE_INTERRUPT_PRIORITIES 32 + +/****** Network configuration settings - only used when the lwIP example is +built. See the page that documents this demo on the http://www.FreeRTOS.org +website for more information. ***********************************************/ + +/* The priority for the task that unblocked by the MAC interrupt to process +received packets. */ +#define configMAC_INPUT_TASK_PRIORITY (configMAX_PRIORITIES - 1) + +/* The priority of the task that runs the lwIP stack. */ +#define configLWIP_TASK_PRIORITY (configMAX_PRIORITIES - 2) + +/* The priority of the task that uses lwIP sockets to provide a simple command +line interface. */ +#define configCLI_TASK_PRIORITY (tskIDLE_PRIORITY) + +/* MAC address configuration. */ +#define configMAC_ADDR0 0x00 +#define configMAC_ADDR1 0x13 +#define configMAC_ADDR2 0x14 +#define configMAC_ADDR3 0x15 +#define configMAC_ADDR4 0x15 +#define configMAC_ADDR5 0x16 + +/* IP address configuration. */ +#define configIP_ADDR0 172 +#define configIP_ADDR1 25 +#define configIP_ADDR2 218 +#define configIP_ADDR3 200 + +/* Netmask configuration. */ +#define configNET_MASK0 255 +#define configNET_MASK1 255 +#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/Xilinx.spec b/sdk/freertos_app_cpu0/src/Xilinx.spec index 9c27dcad..8eea3774 100644 --- a/sdk/freertos_app_cpu0/src/Xilinx.spec +++ b/sdk/freertos_app_cpu0/src/Xilinx.spec @@ -1,2 +1,2 @@ -*startfile: -crti%O%s crtbegin%O%s +*startfile: +crti%O%s crtbegin%O%s diff --git a/sdk/freertos_app_cpu0/src/main.c b/sdk/freertos_app_cpu0/src/main.c index 9a77b434..6cae3bae 100644 --- a/sdk/freertos_app_cpu0/src/main.c +++ b/sdk/freertos_app_cpu0/src/main.c @@ -40,24 +40,20 @@ #include "xil_printf.h" #include "xparameters.h" /* Firmware includes */ -#include "sys/icc.h" +//#include "sys/icc.h" #include "sys/intr.h" /* 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 -#define DELAY_10_SECONDS 10000UL #define DELAY_1_SECOND 1000UL -#define TIMER_CHECK_THRESHOLD 9 -/*-----------------------------------------------------------*/ - -/* The Tx and Rx tasks as described at the top of this file. */ -static void prvTxTask(void *pvParameters); -static void prvRxTask(void *pvParameters); -static void prvBlinkyTask(void *pvParameters); -static void vTimerCallback(TimerHandle_t pxTimer); +#define INTC_HANDLER XScuGic_InterruptHandler /*-----------------------------------------------------------*/ /* This project has configSUPPORT_STATIC_ALLOCATION set to 1 (for Inter-Core Communication) so @@ -91,50 +87,12 @@ 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; -static QueueHandle_t xQueue = NULL; -static TimerHandle_t xTimer = NULL; - -char HWstring[32] = "CPU0 - Hello World"; -long RxtaskCntr = 0; - -uint8_t message_status = 0; -// 0 - sending messages -// 1 - complete, success -// 2 - complete, failure - int main(void) { // Both CPUs: Disable cache on OCM // S=b1 TEX=b100 AP=b11, Domain=b1111, C=b0, B=b0 Xil_SetTlbAttributes(0xFFFF0000, 0x14de2); -#if 1 - // CPU0 ONLY: - // This code is required to start CPU1 from CPU0 during boot. - // - // This only applies when booting from flash via the FSBL. - // During development with JTAG loading, these low-level - // calls in this #if block are not needed! However, we'll - // keep them here since it doesn't affect performance... - - // Write starting base address for CPU1 PC. - // It will look for this address upon waking up - static const uintptr_t CPU1_START_ADDR = 0xFFFFFFF0; - static const uint32_t CPU1_BASE_ADDR = 0x20080000; - Xil_Out32(CPU1_START_ADDR, CPU1_BASE_ADDR); - - // Waits until write has finished - // DMB = Data Memory Barrier - dmb(); - - // Wake up CPU1 by sending the SEV command - // SEV = Set Event, which causes CPU1 to wake up and jump to CPU1_BASE_ADDR - __asm__("sev"); -#endif - Xil_ExceptionInit(); intr_init(); icc_init(); @@ -144,59 +102,25 @@ 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); - - xil_printf("CPU0 - Hello from FreeRTOS example main()!\r\n"); - - /* Create the three tasks */ - xTaskCreate(prvTxTask, /* The function that implements the task. */ - (const char *) "CPU0_Tx", /* Text name for the task, provided to assist debugging only. */ - configMINIMAL_STACK_SIZE, /* The stack allocated to the task. */ - NULL, /* The task parameter is not used, so set to NULL. */ - tskIDLE_PRIORITY, /* The task runs at the idle priority. */ - &xTxTaskHandle); - - xTaskCreate(prvRxTask, /* The function that implements the task. */ - (const char *) "CPU0_Rx", /* Text name for the task, provided to assist debugging only. */ - configMINIMAL_STACK_SIZE, - NULL, - tskIDLE_PRIORITY + 1, - &xRxTaskHandle); - - // Create additional blinky task - CPU0 only - xTaskCreate(prvBlinkyTask, - (const char *) "CPU0_Blinky", - configMINIMAL_STACK_SIZE, - NULL, - tskIDLE_PRIORITY, - &xBlinkyTaskHandle); - - /* Create the queue used by the tasks. The Rx task has a higher priority - than the Tx task, so will preempt the Tx task and remove values from the - queue as soon as the Tx task writes to the queue - therefore the queue can - never have more than one item in it. */ - xQueue = xQueueCreate(1, sizeof(HWstring)); - - /* Check the queue was created. */ - configASSERT(xQueue); - - /* Create a timer with a timer expiry of 10 seconds. The timer would expire - after 10 seconds and the timer call back would get called. In the timer call back - checks are done to ensure that the tasks have been running properly till then. - The tasks are deleted in the timer call back and a message is printed to convey that - the example has run successfully. - The timer expiry is set to 10 seconds and the timer set to not auto reload. */ - xTimer = xTimerCreate((const char *) "CPU0_Timer", x10seconds, pdFALSE, (void *) TIMER_ID, vTimerCallback); - - /* Check the timer was created. */ - configASSERT(xTimer); - - /* start the timer with a block time of 0 ticks. This means as soon - as the schedule starts the timer will start running and will expire after - 10 seconds */ - xTimerStart(xTimer, 0); + /* command sets */ + cmd_counter_register(); + + /* 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)); ///////////////////////// // END USER CODE HERE // @@ -211,150 +135,7 @@ int main(void) to be created. See the memory management section on the FreeRTOS web site for more details. */ for (;;) { - } -} - -/*-----------------------------------------------------------*/ -static void prvTxTask(void *pvParameters) -{ - const TickType_t x1second = pdMS_TO_TICKS(DELAY_1_SECOND); - - for (;;) { - if (message_status > 0) { - // Cannot delete tasks created using heap_1 implementation, so instead we suspend immediately if done - vTaskSuspend(NULL); - } else { - /* Delay for 1 second. */ - vTaskDelay(x1second); - - /* Send the next value on the queue. The queue should always be - empty at this point so a block time of 0 is used. */ - // xQueueSend(xQueue, /* The queue being written to. */ - // HWstring, /* The address of the data being sent. */ - // 0UL); /* The block time. */ - - xil_printf("DEBUG: CPU 0 about to attempt send\r\n"); - - // Send a message to the other core - size_t bytes_sent = xMessageBufferSend(xCPU0to1MessageBuffer, HWstring, sizeof(HWstring), 0UL); - - xil_printf("DEBUG: CPU0 sent %d bytes to ICC buffer\r\n", bytes_sent); - - if (bytes_sent == 0) { - xil_printf("ERROR: CPU 0 failed to write to ICC buffer\r\n"); - } - } - } -} - -/*-----------------------------------------------------------*/ -static void prvRxTask(void *pvParameters) -{ - char Rcvdstring[32] = ""; - - for (;;) { - if (message_status > 0) { - // Cannot delete tasks created using heap_1 implementation, so instead we suspend immediately if done - vTaskSuspend(NULL); - } else { - - // /* Block to wait for data arriving on the queue. */ - // xQueueReceive(xQueue, /* The queue being read. */ - // Rcvdstring, /* Data is read into this address. */ - // portMAX_DELAY); /* Wait without a timeout for data. */ - - xil_printf("DEBUG: CPU 0 about to attempt rcv\r\n"); - - size_t bytes_rcvd = xMessageBufferReceive(xCPU1to0MessageBuffer, Rcvdstring, 32, portMAX_DELAY); - - xil_printf("DEBUG: CPU0 rcvd %d bytes from ICC buffer\r\n", bytes_rcvd); - - if (bytes_rcvd == 0) { - xil_printf("CPU 0 failed to receive from ICC buffer\r\n"); - } else { - /* Print the received data. */ - xil_printf("CPU0 - Rx task received string from CPU1 Tx: %s\r\n", Rcvdstring); - RxtaskCntr++; - } - } - } -} - -/*-----------------------------------------------------------*/ -static void prvBlinkyTask(void *pvParameters) -{ - const TickType_t x250ms = pdMS_TO_TICKS(DELAY_1_SECOND / 4); - uint8_t led_offset = 0; - - for (;;) { - if (message_status == 0) { - // If not complete, cycle yellow every 250ms - vTaskDelay(x250ms); - - led_set_color(0 + led_offset, LED_COLOR_YELLOW); - led_set_color(1 + led_offset, LED_COLOR_BLACK); - led_set_color(2 + led_offset, LED_COLOR_BLACK); - led_set_color(3 + led_offset, LED_COLOR_BLACK); - - led_offset = (led_offset + 1) % 4; - } else if (message_status == 1) { - // If complete, flash all green every 250ms - vTaskDelay(x250ms); - - led_set_color(LED0, LED_COLOR_BLACK); - led_set_color(LED1, LED_COLOR_BLACK); - led_set_color(LED2, LED_COLOR_BLACK); - led_set_color(LED3, LED_COLOR_BLACK); - - vTaskDelay(x250ms); - - led_set_color(LED0, LED_COLOR_GREEN); - led_set_color(LED1, LED_COLOR_GREEN); - led_set_color(LED2, LED_COLOR_GREEN); - led_set_color(LED3, LED_COLOR_GREEN); - } else { - // message_status must be 2, meaning failure - // flash all red every 250ms - vTaskDelay(x250ms); - - led_set_color(LED0, LED_COLOR_BLACK); - led_set_color(LED1, LED_COLOR_BLACK); - led_set_color(LED2, LED_COLOR_BLACK); - led_set_color(LED3, LED_COLOR_BLACK); - - vTaskDelay(x250ms); - - led_set_color(LED0, LED_COLOR_RED); - led_set_color(LED1, LED_COLOR_RED); - led_set_color(LED2, LED_COLOR_RED); - led_set_color(LED3, LED_COLOR_RED); - } - } -} - -/*-----------------------------------------------------------*/ -static void vTimerCallback(TimerHandle_t pxTimer) -{ - long lTimerId; - configASSERT(pxTimer); - - lTimerId = (long) pvTimerGetTimerID(pxTimer); - - if (lTimerId != TIMER_ID) { - xil_printf("CPU0 - FreeRTOS Hello World Example FAILED"); - } - - /* If the RxtaskCntr is updated every time the Rx task is called. The - Rx task is called every time the Tx task sends a message. The Tx task - sends a message every 1 second. - The timer expires after 10 seconds. We expect the RxtaskCntr to at least - have a value of 9 (TIMER_CHECK_THRESHOLD) when the timer expires. */ - if (RxtaskCntr >= TIMER_CHECK_THRESHOLD) { - message_status = 1; - xil_printf("CPU0 - FreeRTOS Hello World Example PASSED\r\n"); - } else { - message_status = 2; - xil_printf("CPU0 - FreeRTOS Hello World Example FAILED\r\n"); + xil_printf("IF YOU'RE READING THIS THEN A TERRIBLE ERROR HAS OCCURRED!\n"); } } @@ -410,3 +191,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/freertos_app_cpu0/src/usr/game/app_game.c b/sdk/freertos_app_cpu0/src/usr/game/app_game.c new file mode 100644 index 00000000..2eec8e98 --- /dev/null +++ b/sdk/freertos_app_cpu0/src/usr/game/app_game.c @@ -0,0 +1,16 @@ +#ifdef APP_GAME + +#include "usr/game/app_game.h" +#include "usr/game/cmd/cmd_game.h" +#include "usr/game/task_game.h" + +void app_game_init(void) +{ + // Register "game" command with system + cmd_game_register(); + + // Initialize game task with system + task_game_init(); +} + +#endif // APP_GAME diff --git a/sdk/freertos_app_cpu0/src/usr/game/app_game.h b/sdk/freertos_app_cpu0/src/usr/game/app_game.h new file mode 100644 index 00000000..1aee03ad --- /dev/null +++ b/sdk/freertos_app_cpu0/src/usr/game/app_game.h @@ -0,0 +1,6 @@ +#ifndef APP_GAME_H +#define APP_GAME_H + +void app_game_init(void); + +#endif // APP_GAME_H diff --git a/sdk/freertos_app_cpu0/src/usr/game/cmd/cmd_game.c b/sdk/freertos_app_cpu0/src/usr/game/cmd/cmd_game.c new file mode 100644 index 00000000..c5d5daed --- /dev/null +++ b/sdk/freertos_app_cpu0/src/usr/game/cmd/cmd_game.c @@ -0,0 +1,106 @@ +#ifdef APP_GAME +#include "cmd_game.h" +#include "usr/game/task_game.h" +#include "sys/commands.h" +#include "sys/debug.h" +#include "sys/defines.h" +#include "sys/util.h" +#include +#include + +static command_entry_t cmd_entry1; +static command_entry_t cmd_entry2; +static command_entry_t cmd_entry3; +static command_entry_t cmd_entry4; +static command_entry_t cmd_entryRestart; + +static command_help_t cmd_help1[] = { + { "1", "Send when LED 1 is on" } +}; + +static command_help_t cmd_help2[] = { + { "2", "Send when LED 2 is on" } +}; + +static command_help_t cmd_help3[] = { + { "3", "Send when LED 3 is on" } +}; + +static command_help_t cmd_help4[] = { + { "4", "Send when LED 4 is on" } +}; + +static command_help_t cmd_helpRestart[] = { + { "r", "Send to restart the game" } +}; + +void cmd_game_register(void) +{ + // Populate the command entry block + commands_cmd_init(&cmd_entry1, "1", "Game 1 command", cmd_help1, ARRAY_SIZE(cmd_help1), cmd_game1); + commands_cmd_init(&cmd_entry2, "2", "Game 2 command", cmd_help2, ARRAY_SIZE(cmd_help2), cmd_game2); + commands_cmd_init(&cmd_entry3, "3", "Game 3 command", cmd_help3, ARRAY_SIZE(cmd_help3), cmd_game3); + commands_cmd_init(&cmd_entry4, "4", "Game 4 command", cmd_help4, ARRAY_SIZE(cmd_help4), cmd_game4); + commands_cmd_init(&cmd_entryRestart, "r", "Restart command", cmd_helpRestart, ARRAY_SIZE(cmd_helpRestart), cmd_gameRestart); + + // Register the command + commands_cmd_register(&cmd_entry1); + commands_cmd_register(&cmd_entry2); + commands_cmd_register(&cmd_entry3); + commands_cmd_register(&cmd_entry4); + commands_cmd_register(&cmd_entryRestart); +} + +int cmd_game1(int argc, char **argv) { + if (getGameLedOn() == 1) { + while (getGameLedOn() == 1) { + setGameLedOn(randomInt(1, 4)); + } + incrementGameScore(); + return CMD_SUCCESS; + } + decrementGameScore(); + return CMD_FAILURE; +} + +int cmd_game2(int argc, char **argv) { + if (getGameLedOn() == 2) { + while (getGameLedOn() == 2) { + setGameLedOn(randomInt(1, 4)); + } + incrementGameScore(); + return CMD_SUCCESS; + } + decrementGameScore(); + return CMD_FAILURE; +} + +int cmd_game3(int argc, char **argv) { + if (getGameLedOn() == 3) { + while (getGameLedOn() == 3) { + setGameLedOn(randomInt(1, 4)); + } + incrementGameScore(); + return CMD_SUCCESS; + } + decrementGameScore(); + return CMD_FAILURE; +} + +int cmd_game4(int argc, char **argv) { + if (getGameLedOn() == 4) { + while (getGameLedOn() == 4) { + setGameLedOn(randomInt(1, 4)); + } + incrementGameScore(); + return CMD_SUCCESS; + } + decrementGameScore(); + return CMD_FAILURE; +} + +int cmd_gameRestart(int argc, char **argv) { + reset_game(); + return CMD_SUCCESS; +} +#endif // APP_GAME diff --git a/sdk/freertos_app_cpu0/src/usr/game/cmd/cmd_game.h b/sdk/freertos_app_cpu0/src/usr/game/cmd/cmd_game.h new file mode 100644 index 00000000..dc7b5466 --- /dev/null +++ b/sdk/freertos_app_cpu0/src/usr/game/cmd/cmd_game.h @@ -0,0 +1,12 @@ +#ifndef CMD_GAME_H +#define CMD_GAME_H + +void cmd_game_register(void); + +int cmd_game1(int argc, char **argv); +int cmd_game2(int argc, char **argv); +int cmd_game3(int argc, char **argv); +int cmd_game4(int argc, char **argv); +int cmd_gameRestart(int argc, char **argv); + +#endif // CMD_GAME_H diff --git a/sdk/freertos_app_cpu0/src/usr/game/task_game.c b/sdk/freertos_app_cpu0/src/usr/game/task_game.c new file mode 100644 index 00000000..2893fa1f --- /dev/null +++ b/sdk/freertos_app_cpu0/src/usr/game/task_game.c @@ -0,0 +1,140 @@ +#ifdef APP_GAME + +/* FreeRTOS includes */ +#include "FreeRTOS.h" +#include "task.h" +/* Xilinx includes. */ +#include "xil_printf.h" +/* other includes */ +#include "usr/game/task_game.h" +#include "drv/led.h" +#include +#include + +/* from: https://www.quora.com/Can-we-get-a-random-number-without-using-rand-in-C-C-and-Python */ +int randCustom() { + static int next = 3251 ; // Anything you like here - but not + // 0000, 0100, 2500, 3792, 7600, + // 0540, 2916, 5030 or 3009. + next = ((next * next) / 100) % 10000; + return next ; +} + +int randomInt(int lowerBound, int upperBound) { // random integer between lower and upper bound (inclusive) + return randCustom() % (upperBound + 1 - lowerBound) + lowerBound; +} + +int gameScore = 0; + +void incrementGameScore() { + gameScore++; +} + +void decrementGameScore() { + gameScore--; +} + +uint8_t game_led_on = 1; + +uint8_t getGameLedOn() { + return game_led_on; +} + +void setGameLedOn(uint8_t setTo) { + if (!game_started()) { + start_game(); + } + led_set_color(game_led_on - 1, LED_COLOR_BLACK); + led_set_color(setTo - 1, LED_COLOR_GREEN); + game_led_on = setTo; +} + +// Hold LED animation state +static uint8_t led_pos = 0; +static uint8_t led_color_idx = 0; +// Scheduler TCB which holds task "context" +static TaskHandle_t tcb; + +int task_game_init(void) +{ + // Turn off all LEDs + for (uint8_t i = 1; i < NUM_LEDS; i++) { + led_set_color(i, LED_COLOR_BLACK); + } + // Turn on first LED to RED + led_set_color(0, LED_COLOR_RED); + + // Command parse task (UART) + xTaskCreate(task_game, (const char *) "game", configMINIMAL_STACK_SIZE, + NULL, tskIDLE_PRIORITY, &tcb); + + return 0; +} + +int task_game_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; + + return 0; +} + +int callbackIter = -2; +int secondsLeft = 30; + +void start_game() { + callbackIter = 0; + secondsLeft = 30; +} + +void reset_game() { + // Turn off all LEDs + for (uint8_t i = 1; i < NUM_LEDS; i++) { + led_set_color(i, LED_COLOR_BLACK); + } + // Turn on first LED to RED + led_set_color(0, LED_COLOR_RED); + callbackIter = -2; + gameScore = 0; + game_led_on = 1; +} + +int game_started() { + if (callbackIter == -2) { + return 0; + } + return 1; +} + +void task_game(void *arg) +{ + const TickType_t delayTicks = pdMS_TO_TICKS(1000.0 / TASK_GAME_UPDATES_PER_SEC); + for (;;) { + vTaskDelay(delayTicks); +// xil_printf("hello\n"); + if (callbackIter >= 0) { + // printf("Callback called %d\n", callbackIter); + callbackIter++; + if (callbackIter % 5 == 0) { + xil_printf("%d seconds left\n", secondsLeft); + secondsLeft--; + } + if (callbackIter > 150) { + game_led_on = 0; + for (uint8_t i = 0; i < NUM_LEDS; i++) { + led_set_color(i, LED_COLOR_BLACK); + } + callbackIter = -1; + xil_printf("Time's up! Score: %d\n", gameScore); + } + } + } +} + +#endif // APP_GAME diff --git a/sdk/freertos_app_cpu0/src/usr/game/task_game.h b/sdk/freertos_app_cpu0/src/usr/game/task_game.h new file mode 100644 index 00000000..943cf400 --- /dev/null +++ b/sdk/freertos_app_cpu0/src/usr/game/task_game.h @@ -0,0 +1,48 @@ +#ifndef TASK_GAME_H +#define TASK_GAME_H + +/* FreeRTOS includes */ +#include "FreeRTOS.h" +#include "task.h" + +// Frequency that this task is called (in Hz) +// +// Must be less than or equal to scheduler updates per second +// This value is defined in sys/scheduler.h and defaults to 10kHz. +// Note that it can be overridden via usr/user_config.h +#define TASK_GAME_UPDATES_PER_SEC (5) + +// Microseconds interval between when task is called +// +// This is what scheduler actually uses to run task, +// but is generated via define above +#define TASK_GAME_INTERVAL_USEC (USEC_IN_SEC / TASK_GAME_UPDATES_PER_SEC) + +void incrementGameScore(); +void decrementGameScore(); + +uint8_t getGameLedOn(); +void setGameLedOn(uint8_t setTo); +int randomInt(int lowerBound, int upperBound); + +// Called in app init function to set up task (or via command) +int task_game_init(void); +int task_game_deinit(void); + +// start the game timer +void start_game(); +void reset_game(); + +// returns 1 if the game is already started and 0 otherwise +int game_started(); + +// Callback function which scheduler calls periodically +void task_game(void *arg); + +// Print the statistics gathered by the scheduler +void task_game_stats_print(void); + +// Reset the statistics gathered by the scheduler +void task_game_stats_reset(void); + +#endif // TASK_GAME_H diff --git a/sdk/freertos_app_cpu0/src/usr/user_apps.c b/sdk/freertos_app_cpu0/src/usr/user_apps.c new file mode 100644 index 00000000..2bea0f19 --- /dev/null +++ b/sdk/freertos_app_cpu0/src/usr/user_apps.c @@ -0,0 +1,68 @@ +#include "usr/user_apps.h" + +// Adding applications: +// +// To add a new application, create a block +// like the other example(s) below which +// conditionally includes the app's header file. +// +// Also, conditionally call the app's init function. + +#ifdef APP_PCBTEST +#include "usr/pcbtest/app_pcbtest.h" +#endif + +#ifdef APP_BLINK +#include "usr/blink/app_blink.h" +#endif + +#ifdef APP_GAME +#include "usr/game/app_game.h" +#endif + +#ifdef APP_MATH +#include "usr/math/app_math.h" +#endif + +#ifdef APP_BETA_LABS +#include "usr/beta_labs/app_beta_labs.h" +#endif + +#ifdef APP_DEMO +#include "usr/demo/app_demo.h" +#endif + +#ifdef APP_DAC +#include "usr/dac/app_dac.h" +#endif + +void user_apps_init(void) +{ +#ifdef APP_PCBTEST + app_pcbtest_init(); +#endif + +#ifdef APP_BLINK + app_blink_init(); +#endif + +#ifdef APP_GAME + app_game_init(); +#endif + +#ifdef APP_MATH + app_math_init(); +#endif + +#ifdef APP_BETA_LABS + app_beta_labs_init(); +#endif + +#ifdef APP_DEMO + app_demo_init(); +#endif + +#ifdef APP_DAC + app_dac_init(); +#endif +} diff --git a/sdk/freertos_app_cpu0/src/usr/user_apps.h b/sdk/freertos_app_cpu0/src/usr/user_apps.h new file mode 100644 index 00000000..1564485c --- /dev/null +++ b/sdk/freertos_app_cpu0/src/usr/user_apps.h @@ -0,0 +1,6 @@ +#ifndef USER_APPS_H +#define USER_APPS_H + +void user_apps_init(void); + +#endif // USER_APPS_H diff --git a/sdk/freertos_app_cpu0/src/usr/user_config.h b/sdk/freertos_app_cpu0/src/usr/user_config.h new file mode 100644 index 00000000..65066adf --- /dev/null +++ b/sdk/freertos_app_cpu0/src/usr/user_config.h @@ -0,0 +1,6 @@ +#ifndef USER_CONFIG_H +#define USER_CONFIG_H + + + +#endif // USER_CONFIG_H 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/freertos_app_cpu1/src/FreeRTOSConfig.h b/sdk/freertos_app_cpu1/src/FreeRTOSConfig.h index b92d6969..94d03f1f 100644 --- a/sdk/freertos_app_cpu1/src/FreeRTOSConfig.h +++ b/sdk/freertos_app_cpu1/src/FreeRTOSConfig.h @@ -1,247 +1,247 @@ -/* README!!! - * - * This configuration is copied from the FreeRTOS v10.1.1 - * based example project for the Zynq 7000 platform (for - * compatibility). However, you can add to it. - * - * Another example configuration file is available at - * "sdk/FreeRTOS-Kernel/examples/sample_configuration/FreeRTOSConfig.h" - * Because that example is in the submodule, it may update - * from time-to-time when the submodule is updated. - */ - -/* - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * 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: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * 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. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - -#ifndef FREERTOS_CONFIG_H -#define FREERTOS_CONFIG_H - -#include "xparameters.h" - -/*----------------------------------------------------------- - * Application specific definitions. - * - * These definitions should be adjusted for your particular hardware and - * application requirements. - * - * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE - * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. - * - * See http://www.freertos.org/a00110.html - *----------------------------------------------------------*/ - -/* - * The FreeRTOS Cortex-A port implements a full interrupt nesting model. - * - * Interrupts that are assigned a priority at or below - * configMAX_API_CALL_INTERRUPT_PRIORITY (which counter-intuitively in the ARM - * generic interrupt controller [GIC] means a priority that has a numerical - * value above configMAX_API_CALL_INTERRUPT_PRIORITY) can call FreeRTOS safe API - * functions and will nest. - * - * Interrupts that are assigned a priority above - * configMAX_API_CALL_INTERRUPT_PRIORITY (which in the GIC means a numerical - * value below configMAX_API_CALL_INTERRUPT_PRIORITY) cannot call any FreeRTOS - * API functions, will nest, and will not be masked by FreeRTOS critical - * sections (although it is necessary for interrupts to be globally disabled - * extremely briefly as the interrupt mask is updated in the GIC). - * - * FreeRTOS functions that can be called from an interrupt are those that end in - * "FromISR". FreeRTOS maintains a separate interrupt safe API to enable - * interrupt entry to be shorter, faster, simpler and smaller. - * - * The Zynq implements 256 unique interrupt priorities. For the purpose of - * setting configMAX_API_CALL_INTERRUPT_PRIORITY 255 represents the lowest - * priority. - */ -#define configMAX_API_CALL_INTERRUPT_PRIORITY 18 - -#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 configPERIPHERAL_CLOCK_HZ (33333000UL) -#define configUSE_PREEMPTION 1 -#define configUSE_IDLE_HOOK 0 // TODO: For low-power, set 1 and implement vApplicationIdleHook() -#define configUSE_TICK_HOOK 0 // TODO: Set as 1 if we want to run function every tick -#define configMAX_PRIORITIES (7) -#define configTOTAL_HEAP_SIZE (125 * 1024) -#define configMAX_TASK_NAME_LEN (10) -#define configUSE_TRACE_FACILITY 1 -#define configUSE_16_BIT_TICKS 0 -#define configIDLE_SHOULD_YIELD 1 -#define configUSE_MUTEXES 1 -#define configQUEUE_REGISTRY_SIZE 8 -#define configCHECK_FOR_STACK_OVERFLOW 0 -#define configUSE_RECURSIVE_MUTEXES 1 -#define configUSE_MALLOC_FAILED_HOOK 0 -#define configUSE_APPLICATION_TASK_TAG 0 -#define configUSE_COUNTING_SEMAPHORES 1 -#define configUSE_QUEUE_SETS 1 -#define configSUPPORT_DYNAMIC_ALLOCATION 1 -#define configSUPPORT_STATIC_ALLOCATION 1 - -/* AMDC ADDITION: Need to specify this callback config so we can create message buffers with callbacks - * This is done for Inter-Core Communication (src/sys/icc.c) */ -#define configUSE_SB_COMPLETED_CALLBACK 1 - -/* Include the query-heap CLI command to query the free heap space. */ -#define configINCLUDE_QUERY_HEAP_COMMAND 1 - -/* Co-routine definitions. */ -#define configUSE_CO_ROUTINES 0 -#define configMAX_CO_ROUTINE_PRIORITIES (2) - -/* Software timer definitions. */ -#define configUSE_TIMERS 1 -#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) -#define configTIMER_QUEUE_LENGTH 5 -#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2) - -/* If configUSE_TASK_FPU_SUPPORT is set to 1 (or undefined) then each task will -be created without an FPU context, and a task must call vTaskUsesFPU() before -making use of any FPU registers. If configUSE_TASK_FPU_SUPPORT is set to 2 then -tasks are created with an FPU context by default, and calling vTaskUsesFPU() has -no effect. */ -#define configUSE_TASK_FPU_SUPPORT 2 -#define configMINIMAL_STACK_SIZE ((unsigned short) 250) // Large since all tasks have FPU context - -/* Set the following definitions to 1 to include the API function, or zero -to exclude the API function. */ -#define INCLUDE_vTaskPrioritySet 1 -#define INCLUDE_uxTaskPriorityGet 1 -#define INCLUDE_vTaskDelete 1 -#define INCLUDE_vTaskCleanUpResources 1 -#define INCLUDE_vTaskSuspend 1 -#define INCLUDE_vTaskDelayUntil 1 -#define INCLUDE_vTaskDelay 1 -#define INCLUDE_xTimerPendFunctionCall 1 -#define INCLUDE_eTaskGetState 1 -#define INCLUDE_xTaskAbortDelay 1 -#define INCLUDE_xTaskGetTaskHandle 1 -#define INCLUDE_xTaskGetHandle 1 -#define INCLUDE_xSemaphoreGetMutexHolder 1 - -/* This demo makes use of one or more example stats formatting functions. These -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 - -/* The private watchdog is used to generate run time stats. */ -/* -#include "xscuwdt.h" -extern XScuWdt xWatchDogInstance; -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 ) -*/ - -/* 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 -and one on TCP/IP). This is done to prevent an output buffer being defined by -each implementation - which would waste RAM. In this case, there is only one -command interpreter running. */ -#define configCOMMAND_INT_MAX_OUTPUT_SIZE 2096 - -/* Normal assert() semantics without relying on the provision of an assert.h -header file. */ -void vAssertCalled(const char *pcFile, unsigned long ulLine); - -// Original Implementation -//#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ ); - -#define configASSERT(x) \ - if ((x) == 0) \ - while (1) \ - ; - -/* If configTASK_RETURN_ADDRESS is not defined then a task that attempts to -return from its implementing function will end up in a "task exit error" -function - which contains a call to configASSERT(). However this can give GCC -some problems when it tries to unwind the stack, as the exit error function has -nothing to return to. To avoid this define configTASK_RETURN_ADDRESS to 0. */ -#define configTASK_RETURN_ADDRESS NULL - -/****** Hardware specific settings. *******************************************/ - -/* - * The application must provide a function that configures a peripheral to - * create the FreeRTOS tick interrupt, then define configSETUP_TICK_INTERRUPT() - * in FreeRTOSConfig.h to call the function. This file contains a function - * that is suitable for use on the Zynq MPU. FreeRTOS_Tick_Handler() must - * be installed as the peripheral's interrupt handler. - */ -void vConfigureTickInterrupt(void); -#define configSETUP_TICK_INTERRUPT() vConfigureTickInterrupt() - -void vClearTickInterrupt(void); -#define configCLEAR_TICK_INTERRUPT() vClearTickInterrupt() - -/* The following constant describe the hardware, and are correct for the -Zynq MPU. */ -#define configINTERRUPT_CONTROLLER_BASE_ADDRESS (XPAR_PS7_SCUGIC_0_DIST_BASEADDR) -#define configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET (-0xf00) -#define configUNIQUE_INTERRUPT_PRIORITIES 32 - -/****** Network configuration settings - only used when the lwIP example is -built. See the page that documents this demo on the http://www.FreeRTOS.org -website for more information. ***********************************************/ - -/* The priority for the task that unblocked by the MAC interrupt to process -received packets. */ -#define configMAC_INPUT_TASK_PRIORITY (configMAX_PRIORITIES - 1) - -/* The priority of the task that runs the lwIP stack. */ -#define configLWIP_TASK_PRIORITY (configMAX_PRIORITIES - 2) - -/* The priority of the task that uses lwIP sockets to provide a simple command -line interface. */ -#define configCLI_TASK_PRIORITY (tskIDLE_PRIORITY) - -/* MAC address configuration. */ -#define configMAC_ADDR0 0x00 -#define configMAC_ADDR1 0x13 -#define configMAC_ADDR2 0x14 -#define configMAC_ADDR3 0x15 -#define configMAC_ADDR4 0x15 -#define configMAC_ADDR5 0x16 - -/* IP address configuration. */ -#define configIP_ADDR0 172 -#define configIP_ADDR1 25 -#define configIP_ADDR2 218 -#define configIP_ADDR3 200 - -/* Netmask configuration. */ -#define configNET_MASK0 255 -#define configNET_MASK1 255 -#define configNET_MASK2 255 -#define configNET_MASK3 0 - -#endif /* FREERTOS_CONFIG_H */ +/* README!!! + * + * This configuration is copied from the FreeRTOS v10.1.1 + * based example project for the Zynq 7000 platform (for + * compatibility). However, you can add to it. + * + * Another example configuration file is available at + * "sdk/FreeRTOS-Kernel/examples/sample_configuration/FreeRTOSConfig.h" + * Because that example is in the submodule, it may update + * from time-to-time when the submodule is updated. + */ + +/* + * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#include "xparameters.h" + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html + *----------------------------------------------------------*/ + +/* + * The FreeRTOS Cortex-A port implements a full interrupt nesting model. + * + * Interrupts that are assigned a priority at or below + * configMAX_API_CALL_INTERRUPT_PRIORITY (which counter-intuitively in the ARM + * generic interrupt controller [GIC] means a priority that has a numerical + * value above configMAX_API_CALL_INTERRUPT_PRIORITY) can call FreeRTOS safe API + * functions and will nest. + * + * Interrupts that are assigned a priority above + * configMAX_API_CALL_INTERRUPT_PRIORITY (which in the GIC means a numerical + * value below configMAX_API_CALL_INTERRUPT_PRIORITY) cannot call any FreeRTOS + * API functions, will nest, and will not be masked by FreeRTOS critical + * sections (although it is necessary for interrupts to be globally disabled + * extremely briefly as the interrupt mask is updated in the GIC). + * + * FreeRTOS functions that can be called from an interrupt are those that end in + * "FromISR". FreeRTOS maintains a separate interrupt safe API to enable + * interrupt entry to be shorter, faster, simpler and smaller. + * + * The Zynq implements 256 unique interrupt priorities. For the purpose of + * setting configMAX_API_CALL_INTERRUPT_PRIORITY 255 represents the lowest + * priority. + */ +#define configMAX_API_CALL_INTERRUPT_PRIORITY 18 + +#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 configPERIPHERAL_CLOCK_HZ (33333000UL) +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 0 // TODO: For low-power, set 1 and implement vApplicationIdleHook() +#define configUSE_TICK_HOOK 0 // TODO: Set as 1 if we want to run function every tick +#define configMAX_PRIORITIES (7) +#define configTOTAL_HEAP_SIZE (125 * 1024) +#define configMAX_TASK_NAME_LEN (10) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 8 +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_MALLOC_FAILED_HOOK 0 +#define configUSE_APPLICATION_TASK_TAG 0 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_QUEUE_SETS 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 +#define configSUPPORT_STATIC_ALLOCATION 1 + +/* AMDC ADDITION: Need to specify this callback config so we can create message buffers with callbacks + * This is done for Inter-Core Communication (src/sys/icc.c) */ +#define configUSE_SB_COMPLETED_CALLBACK 1 + +/* Include the query-heap CLI command to query the free heap space. */ +#define configINCLUDE_QUERY_HEAP_COMMAND 1 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES (2) + +/* Software timer definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) +#define configTIMER_QUEUE_LENGTH 5 +#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2) + +/* If configUSE_TASK_FPU_SUPPORT is set to 1 (or undefined) then each task will +be created without an FPU context, and a task must call vTaskUsesFPU() before +making use of any FPU registers. If configUSE_TASK_FPU_SUPPORT is set to 2 then +tasks are created with an FPU context by default, and calling vTaskUsesFPU() has +no effect. */ +#define configUSE_TASK_FPU_SUPPORT 2 +#define configMINIMAL_STACK_SIZE ((unsigned short) 250) // Large since all tasks have FPU context + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 1 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xTaskAbortDelay 1 +#define INCLUDE_xTaskGetTaskHandle 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 + +/* This demo makes use of one or more example stats formatting functions. These +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 + +/* The private watchdog is used to generate run time stats. */ +/* +#include "xscuwdt.h" +extern XScuWdt xWatchDogInstance; +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 ) +*/ + +/* 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 +and one on TCP/IP). This is done to prevent an output buffer being defined by +each implementation - which would waste RAM. In this case, there is only one +command interpreter running. */ +#define configCOMMAND_INT_MAX_OUTPUT_SIZE 2096 + +/* Normal assert() semantics without relying on the provision of an assert.h +header file. */ +void vAssertCalled(const char *pcFile, unsigned long ulLine); + +// Original Implementation +//#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ ); + +#define configASSERT(x) \ + if ((x) == 0) \ + while (1) \ + ; + +/* If configTASK_RETURN_ADDRESS is not defined then a task that attempts to +return from its implementing function will end up in a "task exit error" +function - which contains a call to configASSERT(). However this can give GCC +some problems when it tries to unwind the stack, as the exit error function has +nothing to return to. To avoid this define configTASK_RETURN_ADDRESS to 0. */ +#define configTASK_RETURN_ADDRESS NULL + +/****** Hardware specific settings. *******************************************/ + +/* + * The application must provide a function that configures a peripheral to + * create the FreeRTOS tick interrupt, then define configSETUP_TICK_INTERRUPT() + * in FreeRTOSConfig.h to call the function. This file contains a function + * that is suitable for use on the Zynq MPU. FreeRTOS_Tick_Handler() must + * be installed as the peripheral's interrupt handler. + */ +void vConfigureTickInterrupt(void); +#define configSETUP_TICK_INTERRUPT() vConfigureTickInterrupt() + +void vClearTickInterrupt(void); +#define configCLEAR_TICK_INTERRUPT() vClearTickInterrupt() + +/* The following constant describe the hardware, and are correct for the +Zynq MPU. */ +#define configINTERRUPT_CONTROLLER_BASE_ADDRESS (XPAR_PS7_SCUGIC_0_DIST_BASEADDR) +#define configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET (-0xf00) +#define configUNIQUE_INTERRUPT_PRIORITIES 32 + +/****** Network configuration settings - only used when the lwIP example is +built. See the page that documents this demo on the http://www.FreeRTOS.org +website for more information. ***********************************************/ + +/* The priority for the task that unblocked by the MAC interrupt to process +received packets. */ +#define configMAC_INPUT_TASK_PRIORITY (configMAX_PRIORITIES - 1) + +/* The priority of the task that runs the lwIP stack. */ +#define configLWIP_TASK_PRIORITY (configMAX_PRIORITIES - 2) + +/* The priority of the task that uses lwIP sockets to provide a simple command +line interface. */ +#define configCLI_TASK_PRIORITY (tskIDLE_PRIORITY) + +/* MAC address configuration. */ +#define configMAC_ADDR0 0x00 +#define configMAC_ADDR1 0x13 +#define configMAC_ADDR2 0x14 +#define configMAC_ADDR3 0x15 +#define configMAC_ADDR4 0x15 +#define configMAC_ADDR5 0x16 + +/* IP address configuration. */ +#define configIP_ADDR0 172 +#define configIP_ADDR1 25 +#define configIP_ADDR2 218 +#define configIP_ADDR3 200 + +/* Netmask configuration. */ +#define configNET_MASK0 255 +#define configNET_MASK1 255 +#define configNET_MASK2 255 +#define configNET_MASK3 0 + +#endif /* FREERTOS_CONFIG_H */ diff --git a/sdk/freertos_app_cpu1/src/Xilinx.spec b/sdk/freertos_app_cpu1/src/Xilinx.spec index 9c27dcad..8eea3774 100644 --- a/sdk/freertos_app_cpu1/src/Xilinx.spec +++ b/sdk/freertos_app_cpu1/src/Xilinx.spec @@ -1,2 +1,2 @@ -*startfile: -crti%O%s crtbegin%O%s +*startfile: +crti%O%s crtbegin%O%s diff --git a/sdk/shared/FreeRTOS_tick_config.c b/sdk/shared/FreeRTOS_tick_config.c index 8ed8452d..b231f163 100644 --- a/sdk/shared/FreeRTOS_tick_config.c +++ b/sdk/shared/FreeRTOS_tick_config.c @@ -1,138 +1,138 @@ -/* - * FreeRTOS Kernel V10.1.1 - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * 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: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * 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. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - -/* FreeRTOS includes. */ -#include "FreeRTOS.h" -#include "task.h" - -/* Xilinx includes. */ -#include "xscugic.h" -#include "xscutimer.h" - -#define XSCUTIMER_CLOCK_HZ (XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ / 2UL) - -static XScuTimer xTimer; -XScuGic xInterruptController; /* Interrupt controller instance */ - -/* - * The application must provide a function that configures a peripheral to - * create the FreeRTOS tick interrupt, then define configSETUP_TICK_INTERRUPT() - * in FreeRTOSConfig.h to call the function. This file contains a function - * that is suitable for use on the Zynq SoC. - */ -void vConfigureTickInterrupt(void) -{ - BaseType_t xStatus; - extern void FreeRTOS_Tick_Handler(void); - XScuTimer_Config *pxTimerConfig; - XScuGic_Config *pxGICConfig; - const uint8_t ucRisingEdge = 3; - - /* This function is called with the IRQ interrupt disabled, and the IRQ - interrupt should be left disabled. It is enabled automatically when the - scheduler is started. */ - - /* Ensure XScuGic_CfgInitialize() has been called. In this demo it has - already been called from prvSetupHardware() in main(). */ - pxGICConfig = XScuGic_LookupConfig(XPAR_SCUGIC_SINGLE_DEVICE_ID); - xStatus = XScuGic_CfgInitialize(&xInterruptController, pxGICConfig, pxGICConfig->CpuBaseAddress); - configASSERT(xStatus == XST_SUCCESS); - (void) xStatus; /* Remove compiler warning if configASSERT() is not defined. */ - - /* The priority must be the lowest possible. */ - XScuGic_SetPriorityTriggerType(&xInterruptController, - XPAR_SCUTIMER_INTR, - portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT, - ucRisingEdge); - - /* Install the FreeRTOS tick handler. */ - xStatus = XScuGic_Connect( - &xInterruptController, XPAR_SCUTIMER_INTR, (Xil_ExceptionHandler) FreeRTOS_Tick_Handler, (void *) &xTimer); - configASSERT(xStatus == XST_SUCCESS); - (void) xStatus; /* Remove compiler warning if configASSERT() is not defined. */ - - /* Initialise the timer. */ - pxTimerConfig = XScuTimer_LookupConfig(XPAR_SCUTIMER_DEVICE_ID); - xStatus = XScuTimer_CfgInitialize(&xTimer, pxTimerConfig, pxTimerConfig->BaseAddr); - configASSERT(xStatus == XST_SUCCESS); - (void) xStatus; /* Remove compiler warning if configASSERT() is not defined. */ - - /* Enable Auto reload mode. */ - XScuTimer_EnableAutoReload(&xTimer); - - /* Ensure there is no prescale. */ - XScuTimer_SetPrescaler(&xTimer, 0); - - /* Load the timer counter register. */ - XScuTimer_LoadTimer(&xTimer, XSCUTIMER_CLOCK_HZ / configTICK_RATE_HZ); - - /* Start the timer counter and then wait for it to timeout a number of - times. */ - XScuTimer_Start(&xTimer); - - /* Enable the interrupt for the xTimer in the interrupt controller. */ - XScuGic_Enable(&xInterruptController, XPAR_SCUTIMER_INTR); - - /* Enable the interrupt in the xTimer itself. */ - vClearTickInterrupt(); - XScuTimer_EnableInterrupt(&xTimer); -} -/*-----------------------------------------------------------*/ - -void vClearTickInterrupt(void) -{ - XScuTimer_ClearInterruptStatus(&xTimer); -} -/*-----------------------------------------------------------*/ - -/* This is the callback function which is called by the FreeRTOS Cortex-A port -layer in response to an interrupt. If the function is called -vApplicationFPUSafeIRQHandler() then it is called after the floating point -registers have been saved. If the function is called vApplicationIRQHandler() -then it will be called without first having saved the FPU registers. See -http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html for -more information */ -void vApplicationFPUSafeIRQHandler(uint32_t ulICCIAR) -{ - extern const XScuGic_Config XScuGic_ConfigTable[]; - static const XScuGic_VectorTableEntry *pxVectorTable - = XScuGic_ConfigTable[XPAR_SCUGIC_SINGLE_DEVICE_ID].HandlerTable; - uint32_t ulInterruptID; - const XScuGic_VectorTableEntry *pxVectorEntry; - - /* Re-enable interrupts. */ - __asm("cpsie i"); - - /* The ID of the interrupt is obtained by bitwise anding the ICCIAR value - with 0x3FF. */ - ulInterruptID = ulICCIAR & 0x3FFUL; - if (ulInterruptID < XSCUGIC_MAX_NUM_INTR_INPUTS) { - /* Call the function installed in the array of installed handler functions. */ - pxVectorEntry = &(pxVectorTable[ulInterruptID]); - pxVectorEntry->Handler(pxVectorEntry->CallBackRef); - } -} +/* + * FreeRTOS Kernel V10.1.1 + * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Xilinx includes. */ +#include "xscugic.h" +#include "xscutimer.h" + +#define XSCUTIMER_CLOCK_HZ (XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ / 2UL) + +static XScuTimer xTimer; +XScuGic xInterruptController; /* Interrupt controller instance */ + +/* + * The application must provide a function that configures a peripheral to + * create the FreeRTOS tick interrupt, then define configSETUP_TICK_INTERRUPT() + * in FreeRTOSConfig.h to call the function. This file contains a function + * that is suitable for use on the Zynq SoC. + */ +void vConfigureTickInterrupt(void) +{ + BaseType_t xStatus; + extern void FreeRTOS_Tick_Handler(void); + XScuTimer_Config *pxTimerConfig; + XScuGic_Config *pxGICConfig; + const uint8_t ucRisingEdge = 3; + + /* This function is called with the IRQ interrupt disabled, and the IRQ + interrupt should be left disabled. It is enabled automatically when the + scheduler is started. */ + + /* Ensure XScuGic_CfgInitialize() has been called. In this demo it has + already been called from prvSetupHardware() in main(). */ + pxGICConfig = XScuGic_LookupConfig(XPAR_SCUGIC_SINGLE_DEVICE_ID); + xStatus = XScuGic_CfgInitialize(&xInterruptController, pxGICConfig, pxGICConfig->CpuBaseAddress); + configASSERT(xStatus == XST_SUCCESS); + (void) xStatus; /* Remove compiler warning if configASSERT() is not defined. */ + + /* The priority must be the lowest possible. */ + XScuGic_SetPriorityTriggerType(&xInterruptController, + XPAR_SCUTIMER_INTR, + portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT, + ucRisingEdge); + + /* Install the FreeRTOS tick handler. */ + xStatus = XScuGic_Connect( + &xInterruptController, XPAR_SCUTIMER_INTR, (Xil_ExceptionHandler) FreeRTOS_Tick_Handler, (void *) &xTimer); + configASSERT(xStatus == XST_SUCCESS); + (void) xStatus; /* Remove compiler warning if configASSERT() is not defined. */ + + /* Initialise the timer. */ + pxTimerConfig = XScuTimer_LookupConfig(XPAR_SCUTIMER_DEVICE_ID); + xStatus = XScuTimer_CfgInitialize(&xTimer, pxTimerConfig, pxTimerConfig->BaseAddr); + configASSERT(xStatus == XST_SUCCESS); + (void) xStatus; /* Remove compiler warning if configASSERT() is not defined. */ + + /* Enable Auto reload mode. */ + XScuTimer_EnableAutoReload(&xTimer); + + /* Ensure there is no prescale. */ + XScuTimer_SetPrescaler(&xTimer, 0); + + /* Load the timer counter register. */ + XScuTimer_LoadTimer(&xTimer, XSCUTIMER_CLOCK_HZ / configTICK_RATE_HZ); + + /* Start the timer counter and then wait for it to timeout a number of + times. */ + XScuTimer_Start(&xTimer); + + /* Enable the interrupt for the xTimer in the interrupt controller. */ + XScuGic_Enable(&xInterruptController, XPAR_SCUTIMER_INTR); + + /* Enable the interrupt in the xTimer itself. */ + vClearTickInterrupt(); + XScuTimer_EnableInterrupt(&xTimer); +} +/*-----------------------------------------------------------*/ + +void vClearTickInterrupt(void) +{ + XScuTimer_ClearInterruptStatus(&xTimer); +} +/*-----------------------------------------------------------*/ + +/* This is the callback function which is called by the FreeRTOS Cortex-A port +layer in response to an interrupt. If the function is called +vApplicationFPUSafeIRQHandler() then it is called after the floating point +registers have been saved. If the function is called vApplicationIRQHandler() +then it will be called without first having saved the FPU registers. See +http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html for +more information */ +void vApplicationFPUSafeIRQHandler(uint32_t ulICCIAR) +{ + extern const XScuGic_Config XScuGic_ConfigTable[]; + static const XScuGic_VectorTableEntry *pxVectorTable + = XScuGic_ConfigTable[XPAR_SCUGIC_SINGLE_DEVICE_ID].HandlerTable; + uint32_t ulInterruptID; + const XScuGic_VectorTableEntry *pxVectorEntry; + + /* Re-enable interrupts. */ + __asm("cpsie i"); + + /* The ID of the interrupt is obtained by bitwise anding the ICCIAR value + with 0x3FF. */ + ulInterruptID = ulICCIAR & 0x3FFUL; + if (ulInterruptID < XSCUGIC_MAX_NUM_INTR_INPUTS) { + /* Call the function installed in the array of installed handler functions. */ + pxVectorEntry = &(pxVectorTable[ulInterruptID]); + pxVectorEntry->Handler(pxVectorEntry->CallBackRef); + } +} diff --git a/sdk/shared/README.md b/sdk/shared/README.md index acf8ca46..49cda056 100644 --- a/sdk/shared/README.md +++ b/sdk/shared/README.md @@ -1,30 +1,30 @@ -# Shared Code Folder - -This folder (`AMDC-Firmware/sdk/shared`) contains source code shared by both CPU applications in the v2, FreeRTOS-based firmware. - -Shared code includes system-level source code for inter-core communication, interrupts, etc, as well as the [FreeRTOS-Kernel](https://github.com/FreeRTOS/FreeRTOS-Kernel) source code, which is available in `AMDC-Firmware/sdk/FreeRTOS-Kernel` as a [Git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules). - -### Differentiating code between CPUs - -If you need to include or run slightly different code on CPU 0 and CPU 1 in a shared source file, it can be done using the `#if` directive like so: - -```c -#include xparameters.h // Must be included to gain access to the XPAR_CPU_ID definition -#include foo.h -#include bar.h - -// Code to be included on both CPUs - -#if XPAR_CPU_ID == 0 - -// Code for CPU 0 only - -#elif XPAR_CPU_ID == 1 - -// Code for CPU 1 only - -#endif - -// More code to be included on both CPUs - -``` +# Shared Code Folder + +This folder (`AMDC-Firmware/sdk/shared`) contains source code shared by both CPU applications in the v2, FreeRTOS-based firmware. + +Shared code includes system-level source code for inter-core communication, interrupts, etc, as well as the [FreeRTOS-Kernel](https://github.com/FreeRTOS/FreeRTOS-Kernel) source code, which is available in `AMDC-Firmware/sdk/FreeRTOS-Kernel` as a [Git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules). + +### Differentiating code between CPUs + +If you need to include or run slightly different code on CPU 0 and CPU 1 in a shared source file, it can be done using the `#if` directive like so: + +```c +#include xparameters.h // Must be included to gain access to the XPAR_CPU_ID definition +#include foo.h +#include bar.h + +// Code to be included on both CPUs + +#if XPAR_CPU_ID == 0 + +// Code for CPU 0 only + +#elif XPAR_CPU_ID == 1 + +// Code for CPU 1 only + +#endif + +// More code to be included on both CPUs + +``` diff --git a/sdk/shared/drv/uart.c b/sdk/shared/drv/uart.c new file mode 100644 index 00000000..58784b5b --- /dev/null +++ b/sdk/shared/drv/uart.c @@ -0,0 +1,115 @@ +#include "uart.h" +#include "sys/defines.h" +#include "xparameters.h" +#include "xuartps.h" +#include + +#define UART_DEVICE_ID XPAR_XUARTPS_0_DEVICE_ID + +#define TEST_BUFFER_SIZE (26) + +// Instance of the UART Device +XUartPs UartPs; + +// The following buffers are used in this example to send +// and receive data with the UART. +static u8 SendBuffer[TEST_BUFFER_SIZE]; // Buffer for Transmitting Data +static u8 RecvBuffer[TEST_BUFFER_SIZE]; // Buffer for Receiving Data + +// The following counters are used to determine when the entire +// buffer has been sent and received. +volatile int TotalReceivedCount; +volatile int TotalSentCount; +int TotalErrorCount; + +int uart_init(void) +{ + XUartPs *UartInstPtr = &UartPs; + u16 DeviceId = UART_DEVICE_ID; + + u32 LoopCount = 0; + unsigned int SentCount; + unsigned int ReceivedCount; + + int Status; + XUartPs_Config *Config; + int Index; + + /* + * Initialize the UART driver so that it's ready to use + * Look up the configuration in the config table, then initialize it. + */ + Config = XUartPs_LookupConfig(DeviceId); + if (NULL == Config) { + return FAILURE; + } + + Status = XUartPs_CfgInitialize(UartInstPtr, Config, Config->BaseAddress); + if (Status != XST_SUCCESS) { + return FAILURE; + } + + /* Check hardware build */ + Status = XUartPs_SelfTest(UartInstPtr); + if (Status != XST_SUCCESS) { + return FAILURE; + } + + /* Use local loopback mode. */ + XUartPs_SetOperMode(UartInstPtr, XUARTPS_OPER_MODE_LOCAL_LOOP); + + /* + * Initialize the send buffer bytes with a pattern and zero out + * the receive buffer. + */ + for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) { + SendBuffer[Index] = (Index % 26) + 'A'; + RecvBuffer[Index] = 0; + } + + /* Block sending the buffer. */ + SentCount = XUartPs_Send(UartInstPtr, SendBuffer, TEST_BUFFER_SIZE); + if (SentCount != TEST_BUFFER_SIZE) { + return FAILURE; + } + + /* + * Wait while the UART is sending the data so that we are guaranteed + * to get the data the 1st time we call receive, otherwise this function + * may enter receive before the data has arrived + */ + while (XUartPs_IsSending(UartInstPtr)) { + LoopCount++; + } + + /* Block receiving the buffer. */ + ReceivedCount = 0; + while (ReceivedCount < TEST_BUFFER_SIZE) { + ReceivedCount += XUartPs_Recv(UartInstPtr, &RecvBuffer[ReceivedCount], (TEST_BUFFER_SIZE - ReceivedCount)); + } + + /* + * Check the receive buffer against the send buffer and verify the + * data was correctly received + */ + for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) { + if (SendBuffer[Index] != RecvBuffer[Index]) { + return FAILURE; + } + } + + /* Restore to normal mode. */ + XUartPs_SetOperMode(UartInstPtr, XUARTPS_OPER_MODE_NORMAL); + + return SUCCESS; +} + +int uart_send(char *msg, int len) +{ + return XUartPs_Send(&UartPs, (uint8_t *) msg, len); +} + +int uart_recv(char *msg, int len) +{ + return XUartPs_Recv(&UartPs, (uint8_t *) msg, len); +} diff --git a/sdk/shared/drv/uart.h b/sdk/shared/drv/uart.h new file mode 100644 index 00000000..d63a6332 --- /dev/null +++ b/sdk/shared/drv/uart.h @@ -0,0 +1,14 @@ +#ifndef UART_H +#define UART_H + +#include + +#define UART_RX_FIFO_LENGTH (64) +#define UART_TX_FIFO_LENGTH (64) + +int uart_init(void); + +int uart_send(char *msg, int len); +int uart_recv(char *msg, int len); + +#endif // UART_H diff --git a/sdk/shared/platform_config.h b/sdk/shared/platform_config.h index 3e9b7f18..eda2e2eb 100644 --- a/sdk/shared/platform_config.h +++ b/sdk/shared/platform_config.h @@ -1,6 +1,6 @@ -#ifndef __PLATFORM_CONFIG_H_ -#define __PLATFORM_CONFIG_H_ - -#define STDOUT_IS_PS7_UART -#define UART_DEVICE_ID 0 -#endif +#ifndef __PLATFORM_CONFIG_H_ +#define __PLATFORM_CONFIG_H_ + +#define STDOUT_IS_PS7_UART +#define UART_DEVICE_ID 0 +#endif diff --git a/sdk/shared/sys/cmd/cmd_counter.c b/sdk/shared/sys/cmd/cmd_counter.c new file mode 100644 index 00000000..82ac0d34 --- /dev/null +++ b/sdk/shared/sys/cmd/cmd_counter.c @@ -0,0 +1,54 @@ +#include "sys/cmd/cmd_counter.h" +#include "sys/commands.h" +#include "sys/defines.h" +#include "sys/util.h" +#include +#include +#include + +static command_entry_t cmd_entry; + +static command_help_t cmd_help[] = { + { "inc", "Increment CNT reg" }, + { "dec", "Decrement CNT reg" }, + { "clr", "Clear CNT reg" }, + { "get", "Get CNT reg" }, +}; + +void cmd_counter_register(void) +{ + // Populate the command entry block + commands_cmd_init( + &cmd_entry, "counter", "Counter reg related commands", cmd_help, ARRAY_SIZE(cmd_help), cmd_counter); + + // Register the command + commands_cmd_register(&cmd_entry); +} + +static int CNT = 0; + +// Handles the 'counter' command and all sub-commands +int cmd_counter(int argc, char **argv) +{ + if (argc == 2 && STREQ("inc", argv[1])) { + CNT++; + return CMD_SUCCESS; + } + + if (argc == 2 && STREQ("dec", argv[1])) { + CNT--; + return CMD_SUCCESS; + } + + if (argc == 2 && STREQ("clr", argv[1])) { + CNT = 0; + return CMD_SUCCESS; + } + + if (argc == 2 && STREQ("get", argv[1])) { + cmd_resp_printf("CNT = %d\r\n", CNT); + return CMD_SUCCESS; + } + + return CMD_INVALID_ARGUMENTS; +} diff --git a/sdk/shared/sys/cmd/cmd_counter.h b/sdk/shared/sys/cmd/cmd_counter.h new file mode 100644 index 00000000..a9fa6f16 --- /dev/null +++ b/sdk/shared/sys/cmd/cmd_counter.h @@ -0,0 +1,8 @@ +#ifndef CMD_COUNTER_H +#define CMD_COUNTER_H + +void cmd_counter_register(void); + +int cmd_counter(int argc, char **argv); + +#endif // CMD_COUNTER_H diff --git a/sdk/shared/sys/cmd/cmd_help.c b/sdk/shared/sys/cmd/cmd_help.c new file mode 100644 index 00000000..03793982 --- /dev/null +++ b/sdk/shared/sys/cmd/cmd_help.c @@ -0,0 +1,29 @@ +#include "cmd_help.h" +#include "sys/commands.h" +#include +#include + +static command_entry_t cmd_entry; + +void cmd_help_register(void) +{ + // Populate the command entry block + commands_cmd_init(&cmd_entry, "help", "Display this help message", NULL, 0, cmd_help); + + // Register the command + commands_cmd_register(&cmd_entry); +} + +// +// Handles the 'help' command +// +int cmd_help(int argc, char **argv) +{ + if (argc > 1) { + return CMD_INVALID_ARGUMENTS; + } + + commands_display_help(); + + return CMD_SUCCESS_QUIET; +} diff --git a/sdk/shared/sys/cmd/cmd_help.h b/sdk/shared/sys/cmd/cmd_help.h new file mode 100644 index 00000000..130a1a93 --- /dev/null +++ b/sdk/shared/sys/cmd/cmd_help.h @@ -0,0 +1,8 @@ +#ifndef CMD_HELP_H +#define CMD_HELP_H + +void cmd_help_register(void); + +int cmd_help(int argc, char **argv); + +#endif // CMD_HELP_H diff --git a/sdk/shared/sys/commands.c b/sdk/shared/sys/commands.c new file mode 100644 index 00000000..6ec9b02f --- /dev/null +++ b/sdk/shared/sys/commands.c @@ -0,0 +1,662 @@ +/* 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 +#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, tskIDLE_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/shared/sys/commands.h b/sdk/shared/sys/commands.h new file mode 100644 index 00000000..65bd4852 --- /dev/null +++ b/sdk/shared/sys/commands.h @@ -0,0 +1,61 @@ +#ifndef COMMANDS_H +#define COMMANDS_H + +#define COMMANDS_UPDATES_PER_SEC (10000) +#define COMMANDS_INTERVAL_TICKS (pdMS_TO_TICKS(1000.0 / COMMANDS_UPDATES_PER_SEC)) + +// Supported command handler return codes +// +// NOTE: all commands must return a valid response to the host. +// Only use the resp: "SUCCESS_QUIET" if you will output a valid +// response later in your handler. +// +// For example, "help" and "log dump" work this way. +// +#define CMD_SUCCESS (0) +#define CMD_FAILURE (1) +#define CMD_SUCCESS_QUIET (2) +#define CMD_INVALID_ARGUMENTS (3) +#define CMD_INPUT_TOO_LONG (4) +#define CMD_UNKNOWN_CMD (5) + +// Forward declarations +typedef struct command_entry_t command_entry_t; +typedef struct command_help_t command_help_t; + +typedef struct command_entry_t { + const char *cmd; + const char *desc; + command_help_t *help; + int num_help_cmds; + int (*cmd_function)(int, char **); + + // Pointer to next cmd; set this to NULL in user code. + // When cmd is registered, this will form a linked list. + command_entry_t *next; +} command_entry_t; + +typedef struct command_help_t { + const char *subcmd; + const char *desc; +} command_help_t; + +// Use these functions to output data for a cmd response: +void cmd_resp_write(char *msg, int len); +void cmd_resp_print(char *msg); +void cmd_resp_printf(const char *format, ...); + +void commands_init(void); + +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 **)); +void commands_cmd_register(command_entry_t *cmd_entry); + +void commands_start_msg(void); +void commands_display_help(void); + +#endif // COMMANDS_H diff --git a/sdk/shared/sys/debug.c b/sdk/shared/sys/debug.c new file mode 100644 index 00000000..3054f8ff --- /dev/null +++ b/sdk/shared/sys/debug.c @@ -0,0 +1,24 @@ +#include "sys/debug.h" +#include "sys/serial.h" +#include +#include +#include + +#define BUFFER_LENGTH (1024) +static char buffer[BUFFER_LENGTH] = { 0 }; + +void debug_print(char *msg) +{ + serial_write(msg, strlen(msg)); +} + +void debug_printf(const char *format, ...) +{ + va_list vargs; + va_start(vargs, format); + + vsnprintf(buffer, BUFFER_LENGTH, format, vargs); + debug_print(buffer); + + va_end(vargs); +} diff --git a/sdk/shared/sys/debug.h b/sdk/shared/sys/debug.h new file mode 100644 index 00000000..85d4b235 --- /dev/null +++ b/sdk/shared/sys/debug.h @@ -0,0 +1,7 @@ +#ifndef DEBUG_H +#define DEBUG_H + +void debug_print(char *msg); +void debug_printf(const char *msg, ...); + +#endif // DEBUG_H diff --git a/sdk/shared/sys/defines.h b/sdk/shared/sys/defines.h new file mode 100644 index 00000000..36228b3e --- /dev/null +++ b/sdk/shared/sys/defines.h @@ -0,0 +1,28 @@ +#ifndef DEFINES_H +#define DEFINES_H + +#include + +#define UNUSED(x) (void) (x) + +#define HANG \ + printf("HANG!!!\n"); \ + while (1) + +#define SUCCESS (0) +#define FAILURE (1) + +#define PI (3.141592653589793238463) // pi +#define PI23 (2.094395102393195492308) // 2*pi/3 +#define PI2 (6.283185307179586476925) // 2*pi + +#define SQRT23 (0.816496580927726032732) // sqrt(2/3) +#define SQRT2 (1.414213562373095048802) // sqrt(2) +#define SQRT3 (1.732050807568877293528) // sqrt(3) + +#define DEG_TO_RAD(deg) (deg * PI / 180.0) +#define RAD_TO_DEG(rad) (rad * 180.0 / PI) +#define RPM_TO_RAD_PER_SEC(rpm) (rpm * PI2 / 60.0) +#define RAD_PER_SEC_TO_RPM(rps) (rps * 60.0 / PI2) + +#endif // DEFINES_H diff --git a/sdk/shared/sys/icc.c b/sdk/shared/sys/icc.c index 2673a593..b6b662d8 100644 --- a/sdk/shared/sys/icc.c +++ b/sdk/shared/sys/icc.c @@ -1,91 +1,91 @@ -#include "icc.h" - -/////////////////////////////////////////////////////// -// THIS IS A SHARED FILE, SO IT IS ALWAYS -// IN SYNC IN BOTH CPU0 AND CPU1 -// -// If you need to differentiate something between -// CPUs, use "#if XPAR_CPU_ID == ?" -/////////////////////////////////////////////////////// - -void icc_init(uint32_t cpu_num) -{ -#if XPAR_CPU_ID == 0 - // ONLY CPU 0 INITIALIZES THE MESSAGE BUFFERS - - /* Create two message buffers for inter-core communication that use the callback - * functions below as send and receive completed callback functions. */ - xCPU0to1MessageBuffer = xMessageBufferCreateStaticWithCallback(ICC_BUFFER_SIZE - 1, - ICC_CPU0to1_BufferSpaceAddr, - ICC_CPU0to1_BufferStructAddr, - vCPU0to1SendCallback, - vCPU0to1ReceiveCallback); - - xCPU1to0MessageBuffer = xMessageBufferCreateStaticWithCallback(ICC_BUFFER_SIZE - 1, - ICC_CPU1to0_BufferSpaceAddr, - ICC_CPU1to0_BufferStructAddr, - vCPU1to0SendCallback, - vCPU1to0ReceiveCallback); -#endif -} - -/* From FreeRTOS: - * Insert code into callback which is invoked when a message is written to the message buffer. - * This is useful when a message buffer is used to pass messages between - * cores on a multicore processor. In that scenario, this callback - * can be implemented to generate an interrupt in the other CPU core, - * and the interrupt's service routine can then use the - * xMessageBufferSendCompletedFromISR() API function to check, and if - * necessary unblock, a task that was waiting for message. */ - -/* !! IMPORTANT !! - * These callback functions must ALL exist in BOTH CPUs for the above Message Buffer creations - * to work. HOWEVER, the callbacks only have to DO SOMETHING in the relevant CPU - * For example, the behavior of the 0 to 1 Send Callback must be implemented in CPU 0, since - * CPU 0 needs to send an interrupt to CPU 1 when it sends to the buffer. But CPU 1 will never - * send to the 0 to 1 buffer, so in CPU 1 this callback doesn't need to DO ANYTHING except exist. - * - Patrick */ - -void vCPU0to1SendCallback(MessageBufferHandle_t xMessageBuffer, - BaseType_t xIsInsideISR, - BaseType_t *const pxHigherPriorityTaskWoken) -{ -#if XPAR_CPU_ID == 0 - xil_printf("DEBUG: CPU 0 to 1 Send Callback reached\r\n"); - // In CPU 0, this callback should send an interrupt to CPU 1's Rx task - XScuGic_SoftwareIntr(&InterruptController, INTC_0TO1_SEND_INTERRUPT_ID, CPU1_ID); -#endif -} - -void vCPU1to0ReceiveCallback(MessageBufferHandle_t xMessageBuffer, - BaseType_t xIsInsideISR, - BaseType_t *const pxHigherPriorityTaskWoken) -{ -#if XPAR_CPU_ID == 0 - xil_printf("DEBUG: CPU 1 to 0 Receive Callback reached\r\n"); - // In CPU 0, this callback should send an interrupt to CPU 1's Tx task - XScuGic_SoftwareIntr(&InterruptController, INTC_1TO0_RCVE_INTERRUPT_ID, CPU1_ID); -#endif -} - -void vCPU1to0SendCallback(MessageBufferHandle_t xMessageBuffer, - BaseType_t xIsInsideISR, - BaseType_t *const pxHigherPriorityTaskWoken) -{ -#if XPAR_CPU_ID == 1 - xil_printf("DEBUG: CPU 1 to 0 Send Callback reached\r\n"); - // In CPU 1, this callback should send an interrupt to CPU 0's Rx task - XScuGic_SoftwareIntr(&InterruptController, INTC_1TO0_SEND_INTERRUPT_ID, CPU0_ID); -#endif -} - -void vCPU0to1ReceiveCallback(MessageBufferHandle_t xMessageBuffer, - BaseType_t xIsInsideISR, - BaseType_t *const pxHigherPriorityTaskWoken) -{ -#if XPAR_CPU_ID == 1 - xil_printf("DEBUG: CPU 0 to 1 Receive Callback reached\r\n"); - // In CPU 1, this callback should send an interrupt to CPU 0's Tx task - XScuGic_SoftwareIntr(&InterruptController, INTC_0TO1_RCVE_INTERRUPT_ID, CPU0_ID); -#endif -} +#include "icc.h" + +/////////////////////////////////////////////////////// +// THIS IS A SHARED FILE, SO IT IS ALWAYS +// IN SYNC IN BOTH CPU0 AND CPU1 +// +// If you need to differentiate something between +// CPUs, use "#if XPAR_CPU_ID == ?" +/////////////////////////////////////////////////////// + +void icc_init(uint32_t cpu_num) +{ +#if XPAR_CPU_ID == 0 + // ONLY CPU 0 INITIALIZES THE MESSAGE BUFFERS + + /* Create two message buffers for inter-core communication that use the callback + * functions below as send and receive completed callback functions. */ + xCPU0to1MessageBuffer = xMessageBufferCreateStaticWithCallback(ICC_BUFFER_SIZE - 1, + ICC_CPU0to1_BufferSpaceAddr, + ICC_CPU0to1_BufferStructAddr, + vCPU0to1SendCallback, + vCPU0to1ReceiveCallback); + + xCPU1to0MessageBuffer = xMessageBufferCreateStaticWithCallback(ICC_BUFFER_SIZE - 1, + ICC_CPU1to0_BufferSpaceAddr, + ICC_CPU1to0_BufferStructAddr, + vCPU1to0SendCallback, + vCPU1to0ReceiveCallback); +#endif +} + +/* From FreeRTOS: + * Insert code into callback which is invoked when a message is written to the message buffer. + * This is useful when a message buffer is used to pass messages between + * cores on a multicore processor. In that scenario, this callback + * can be implemented to generate an interrupt in the other CPU core, + * and the interrupt's service routine can then use the + * xMessageBufferSendCompletedFromISR() API function to check, and if + * necessary unblock, a task that was waiting for message. */ + +/* !! IMPORTANT !! + * These callback functions must ALL exist in BOTH CPUs for the above Message Buffer creations + * to work. HOWEVER, the callbacks only have to DO SOMETHING in the relevant CPU + * For example, the behavior of the 0 to 1 Send Callback must be implemented in CPU 0, since + * CPU 0 needs to send an interrupt to CPU 1 when it sends to the buffer. But CPU 1 will never + * send to the 0 to 1 buffer, so in CPU 1 this callback doesn't need to DO ANYTHING except exist. + * - Patrick */ + +void vCPU0to1SendCallback(MessageBufferHandle_t xMessageBuffer, + BaseType_t xIsInsideISR, + BaseType_t *const pxHigherPriorityTaskWoken) +{ +#if XPAR_CPU_ID == 0 + xil_printf("DEBUG: CPU 0 to 1 Send Callback reached\r\n"); + // In CPU 0, this callback should send an interrupt to CPU 1's Rx task + XScuGic_SoftwareIntr(&InterruptController, INTC_0TO1_SEND_INTERRUPT_ID, CPU1_ID); +#endif +} + +void vCPU1to0ReceiveCallback(MessageBufferHandle_t xMessageBuffer, + BaseType_t xIsInsideISR, + BaseType_t *const pxHigherPriorityTaskWoken) +{ +#if XPAR_CPU_ID == 0 + xil_printf("DEBUG: CPU 1 to 0 Receive Callback reached\r\n"); + // In CPU 0, this callback should send an interrupt to CPU 1's Tx task + XScuGic_SoftwareIntr(&InterruptController, INTC_1TO0_RCVE_INTERRUPT_ID, CPU1_ID); +#endif +} + +void vCPU1to0SendCallback(MessageBufferHandle_t xMessageBuffer, + BaseType_t xIsInsideISR, + BaseType_t *const pxHigherPriorityTaskWoken) +{ +#if XPAR_CPU_ID == 1 + xil_printf("DEBUG: CPU 1 to 0 Send Callback reached\r\n"); + // In CPU 1, this callback should send an interrupt to CPU 0's Rx task + XScuGic_SoftwareIntr(&InterruptController, INTC_1TO0_SEND_INTERRUPT_ID, CPU0_ID); +#endif +} + +void vCPU0to1ReceiveCallback(MessageBufferHandle_t xMessageBuffer, + BaseType_t xIsInsideISR, + BaseType_t *const pxHigherPriorityTaskWoken) +{ +#if XPAR_CPU_ID == 1 + xil_printf("DEBUG: CPU 0 to 1 Receive Callback reached\r\n"); + // In CPU 1, this callback should send an interrupt to CPU 0's Tx task + XScuGic_SoftwareIntr(&InterruptController, INTC_0TO1_RCVE_INTERRUPT_ID, CPU0_ID); +#endif +} diff --git a/sdk/shared/sys/icc.h b/sdk/shared/sys/icc.h index c8d82879..72273101 100644 --- a/sdk/shared/sys/icc.h +++ b/sdk/shared/sys/icc.h @@ -1,89 +1,89 @@ -#ifndef ICC_H -#define ICC_H - -#include "FreeRTOS.h" -#include "intr.h" -#include "message_buffer.h" -#include "xil_printf.h" -#include - -/////////////////////////////////////////////////////// -// THIS IS A SHARED FILE, SO IT IS ALWAYS -// IN SYNC IN BOTH CPU0 AND CPU1 -// -// If you need to differentiate something between -// CPUs, use "#if XPAR_CPU_ID == ?" -/////////////////////////////////////////////////////// - -// ======================== -// Inter-Core Communication -// ======================== -// -// This module implements communication between the two cores, CPU0 and CPU1. -// CPU0 acts as the master and initializes all shared memory spaces. -// -// In the OCM, we implement two FreeRTOS Message Buffers: one from CPU0 to CPU1, -// and one from CPU1 to CPU0. Each FIFO and associated data are used to build a -// simple producer-consumer system. -// -// This implementation is known to be thread (dual-core) safe. -// -// For more details and pseudo code, see these resources: -// https://www.freertos.org/RTOS-message-buffer-API.html -// https://www.freertos.org/2020/02/simple-multicore-core-to-core-communication-using-freertos-message-buffers.html - -// Per Zynq-7000 TRM Ch. 4: System Addresses (page 106), the initial mapping -// of OCM is split between low addresses and high addresses in 64 KB chunks. -// -// We will pick to use the highest 64 KB chunk as our base address: -#define OCM_BASE_ADDR (0xFFFF0000) -#define ICC_BUFFER_STRUCT_SIZE (sizeof(StaticMessageBuffer_t)) -#define ICC_BUFFER_SIZE (4 * 1024) -#define ICC_HANDLE_SIZE (sizeof(MessageBufferHandle_t)) - - -/* Define the pointers to the two structs (that store the metadata) and two message spaces (that hold the messages) in shared memory. - * The ICC_BUFFER_SIZE Should be one more than the value passed in the xBufferSizeBytes parameter. - * The two structs will be located back-to-back right at the base addr of the shared OCM, followed thereafter by the actual message buffers. */ -#define ICC_CPU0to1_BufferStructAddr ((uint8_t *) (OCM_BASE_ADDR + (0 * ICC_BUFFER_STRUCT_SIZE))) -#define ICC_CPU1to0_BufferStructAddr ((uint8_t *) (OCM_BASE_ADDR + (1 * ICC_BUFFER_STRUCT_SIZE))) - -#define ICC_CPU0to1_BufferSpaceAddr ((uint8_t *) (OCM_BASE_ADDR + (2 * ICC_BUFFER_STRUCT_SIZE) + (0 * ICC_BUFFER_SIZE))) -#define ICC_CPU1to0_BufferSpaceAddr ((uint8_t *) (OCM_BASE_ADDR + (2 * ICC_BUFFER_STRUCT_SIZE) + (1 * ICC_BUFFER_SIZE))) - - -/* These memory spaces are used to transfer the Message Buffer Handles from CPU0 (who does the initialization work, and gets the handles - * from the xMessageBufferCreateStaticWithCallback function) to CPU1 (who doesn't initialize anything and gets the handles from CPU0, via - * these drop-zones) */ -#define ICC_CPU0to1_HandleDropzoneAddr (OCM_BASE_ADDR + (2 * ICC_BUFFER_STRUCT_SIZE) + (2 * ICC_BUFFER_SIZE) + (0 * ICC_HANDLE_SIZE))) -#define ICC_CPU1to0_HandleDropzoneAddr (OCM_BASE_ADDR + (2 * ICC_BUFFER_STRUCT_SIZE) + (2 * ICC_BUFFER_SIZE) + (1 * ICC_HANDLE_SIZE))) - -#define ICC_getCPU0to1Handle (*((MessageBufferHandle_t *) ICC_CPU0to1_HandleDropzoneAddr)) -#define ICC_setCPU0to1Handle(handle) (*((MessageBufferHandle_t *) ICC_CPU0to1_HandleDropzoneAddr) = handle) -#define ICC_getCPU1to0Handle (*((MessageBufferHandle_t *) ICC_CPU1to0_HandleDropzoneAddr)) -#define ICC_setCPU1to0Handle(handle) (*((MessageBufferHandle_t *) ICC_CPU1to0_HandleDropzoneAddr) = handle) - - - -/* These are the handles for the Message Buffers that need to be used by other tasks - * In reality, the handle is just the pointer to the message buffer struct (its memory address) - * These should end up being the addresses computed above */ -MessageBufferHandle_t xCPU0to1MessageBuffer; -MessageBufferHandle_t xCPU1to0MessageBuffer; - - -void icc_init(); -void vCPU0to1SendCallback(MessageBufferHandle_t xMessageBuffer, - BaseType_t xIsInsideISR, - BaseType_t *const pxHigherPriorityTaskWoken); -void vCPU0to1ReceiveCallback(MessageBufferHandle_t xMessageBuffer, - BaseType_t xIsInsideISR, - BaseType_t *const pxHigherPriorityTaskWoken); -void vCPU1to0SendCallback(MessageBufferHandle_t xMessageBuffer, - BaseType_t xIsInsideISR, - BaseType_t *const pxHigherPriorityTaskWoken); -void vCPU1to0ReceiveCallback(MessageBufferHandle_t xMessageBuffer, - BaseType_t xIsInsideISR, - BaseType_t *const pxHigherPriorityTaskWoken); - -#endif /* ICC_H */ +#ifndef ICC_H +#define ICC_H + +#include "FreeRTOS.h" +#include "intr.h" +#include "message_buffer.h" +#include "xil_printf.h" +#include + +/////////////////////////////////////////////////////// +// THIS IS A SHARED FILE, SO IT IS ALWAYS +// IN SYNC IN BOTH CPU0 AND CPU1 +// +// If you need to differentiate something between +// CPUs, use "#if XPAR_CPU_ID == ?" +/////////////////////////////////////////////////////// + +// ======================== +// Inter-Core Communication +// ======================== +// +// This module implements communication between the two cores, CPU0 and CPU1. +// CPU0 acts as the master and initializes all shared memory spaces. +// +// In the OCM, we implement two FreeRTOS Message Buffers: one from CPU0 to CPU1, +// and one from CPU1 to CPU0. Each FIFO and associated data are used to build a +// simple producer-consumer system. +// +// This implementation is known to be thread (dual-core) safe. +// +// For more details and pseudo code, see these resources: +// https://www.freertos.org/RTOS-message-buffer-API.html +// https://www.freertos.org/2020/02/simple-multicore-core-to-core-communication-using-freertos-message-buffers.html + +// Per Zynq-7000 TRM Ch. 4: System Addresses (page 106), the initial mapping +// of OCM is split between low addresses and high addresses in 64 KB chunks. +// +// We will pick to use the highest 64 KB chunk as our base address: +#define OCM_BASE_ADDR (0xFFFF0000) +#define ICC_BUFFER_STRUCT_SIZE (sizeof(StaticMessageBuffer_t)) +#define ICC_BUFFER_SIZE (4 * 1024) +#define ICC_HANDLE_SIZE (sizeof(MessageBufferHandle_t)) + + +/* Define the pointers to the two structs (that store the metadata) and two message spaces (that hold the messages) in shared memory. + * The ICC_BUFFER_SIZE Should be one more than the value passed in the xBufferSizeBytes parameter. + * The two structs will be located back-to-back right at the base addr of the shared OCM, followed thereafter by the actual message buffers. */ +#define ICC_CPU0to1_BufferStructAddr ((uint8_t *) (OCM_BASE_ADDR + (0 * ICC_BUFFER_STRUCT_SIZE))) +#define ICC_CPU1to0_BufferStructAddr ((uint8_t *) (OCM_BASE_ADDR + (1 * ICC_BUFFER_STRUCT_SIZE))) + +#define ICC_CPU0to1_BufferSpaceAddr ((uint8_t *) (OCM_BASE_ADDR + (2 * ICC_BUFFER_STRUCT_SIZE) + (0 * ICC_BUFFER_SIZE))) +#define ICC_CPU1to0_BufferSpaceAddr ((uint8_t *) (OCM_BASE_ADDR + (2 * ICC_BUFFER_STRUCT_SIZE) + (1 * ICC_BUFFER_SIZE))) + + +/* These memory spaces are used to transfer the Message Buffer Handles from CPU0 (who does the initialization work, and gets the handles + * from the xMessageBufferCreateStaticWithCallback function) to CPU1 (who doesn't initialize anything and gets the handles from CPU0, via + * these drop-zones) */ +#define ICC_CPU0to1_HandleDropzoneAddr (OCM_BASE_ADDR + (2 * ICC_BUFFER_STRUCT_SIZE) + (2 * ICC_BUFFER_SIZE) + (0 * ICC_HANDLE_SIZE))) +#define ICC_CPU1to0_HandleDropzoneAddr (OCM_BASE_ADDR + (2 * ICC_BUFFER_STRUCT_SIZE) + (2 * ICC_BUFFER_SIZE) + (1 * ICC_HANDLE_SIZE))) + +#define ICC_getCPU0to1Handle (*((MessageBufferHandle_t *) ICC_CPU0to1_HandleDropzoneAddr)) +#define ICC_setCPU0to1Handle(handle) (*((MessageBufferHandle_t *) ICC_CPU0to1_HandleDropzoneAddr) = handle) +#define ICC_getCPU1to0Handle (*((MessageBufferHandle_t *) ICC_CPU1to0_HandleDropzoneAddr)) +#define ICC_setCPU1to0Handle(handle) (*((MessageBufferHandle_t *) ICC_CPU1to0_HandleDropzoneAddr) = handle) + + + +/* These are the handles for the Message Buffers that need to be used by other tasks + * In reality, the handle is just the pointer to the message buffer struct (its memory address) + * These should end up being the addresses computed above */ +MessageBufferHandle_t xCPU0to1MessageBuffer; +MessageBufferHandle_t xCPU1to0MessageBuffer; + + +void icc_init(); +void vCPU0to1SendCallback(MessageBufferHandle_t xMessageBuffer, + BaseType_t xIsInsideISR, + BaseType_t *const pxHigherPriorityTaskWoken); +void vCPU0to1ReceiveCallback(MessageBufferHandle_t xMessageBuffer, + BaseType_t xIsInsideISR, + BaseType_t *const pxHigherPriorityTaskWoken); +void vCPU1to0SendCallback(MessageBufferHandle_t xMessageBuffer, + BaseType_t xIsInsideISR, + BaseType_t *const pxHigherPriorityTaskWoken); +void vCPU1to0ReceiveCallback(MessageBufferHandle_t xMessageBuffer, + BaseType_t xIsInsideISR, + BaseType_t *const pxHigherPriorityTaskWoken); + +#endif /* ICC_H */ diff --git a/sdk/shared/sys/intr.c b/sdk/shared/sys/intr.c index 253dcbbc..990b647d 100644 --- a/sdk/shared/sys/intr.c +++ b/sdk/shared/sys/intr.c @@ -1,114 +1,114 @@ -#include "intr.h" - -/////////////////////////////////////////////////////// -// THIS IS A SHARED FILE, SO IT IS ALWAYS -// IN SYNC IN BOTH CPU0 AND CPU1 -// -// If you need to differentiate something between -// CPUs, use "#if XPAR_CPU_ID == ?" -/////////////////////////////////////////////////////// - -/* The functions in this file are responsible for setting up the - * Xilinx Generic Interrupt Controller (GIC). - * - * Interrupts are needed for Inter-Core Communication, specifically - * the ability to trigger an interrupt in the receiving CPU after a - * message is placed into an empty ICC Message Buffer, - * OR - * the ability to trigger an interrupt in the sending CPU after a - * message is removed from a full ICC Message Buffer - * - * See sys/icc.c for more info. - */ - -int intr_init() -{ - int Status = XST_FAILURE; - - XScuGic_Config *IntcConfig; - - IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID); - XScuGic_CfgInitialize(&InterruptController, IntcConfig, IntcConfig->CpuBaseAddress); - - /* - * Perform a self-test to ensure that the hardware was built - * correctly - */ - Status = XScuGic_SelfTest(&InterruptController); - if (Status != XST_SUCCESS) { - return XST_FAILURE; - } - - // Initialize the interrupt controller - Xil_ExceptionRegisterHandler( - XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler) XScuGic_InterruptHandler, &InterruptController); - Xil_ExceptionEnable(); - -#if XPAR_CPU_ID == 0 - // Connect the given interrupt with its handler - XScuGic_Connect(&InterruptController, INTC_1TO0_SEND_INTERRUPT_ID, (Xil_ExceptionHandler) CPU0WakeRxHandler, NULL); - XScuGic_Connect(&InterruptController, INTC_0TO1_RCVE_INTERRUPT_ID, (Xil_ExceptionHandler) CPU0WakeTxHandler, NULL); - -#elif XPAR_CPU_ID == 1 - // Connect the given interrupt with its handler - XScuGic_Connect(&InterruptController, INTC_0TO1_SEND_INTERRUPT_ID, (Xil_ExceptionHandler) CPU1WakeRxHandler, NULL); - XScuGic_Connect(&InterruptController, INTC_1TO0_RCVE_INTERRUPT_ID, (Xil_ExceptionHandler) CPU1WakeTxHandler, NULL); -#endif - - /* - // Enable the interrupt for the second CPU core - XScuGic_SetPriorityTriggerType(&InterruptController, INTC_INTERRUPT_ID, 0xA0, 3); // Set priority and trigger type - XScuGic_Enable(&InterruptController, INTC_INTERRUPT_ID); - - // Enable the interrupt for CPU1 - Xil_Out32(XPAR_PS7_SCUGIC_DIST_BASEADDR + XSCUGIC_CPU_PRIOR_OFFSET + (CPU1_ID * 4), 0xFF); - Xil_Out32(XPAR_PS7_SCUGIC_DIST_BASEADDR + XSCUGIC_CPU_TARGET_OFFSET + (CPU1_ID * 4), 0x1); - - // Enable interrupts globally - Xil_ExceptionEnableMask(XIL_EXCEPTION_NON_CRITICAL); - - print("Interrupt system setup complete.\r\n"); - */ - - return XST_SUCCESS; -} - -/* We only need to define the handlers in the appropriate core - */ -#if XPAR_CPU_ID == 0 -void CPU0WakeTxHandler() -{ - xil_printf("CPU 0 - WakeTxHandler reached\r\n"); - - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xMessageBufferReceiveCompletedFromISR(xCPU0to1MessageBuffer, &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -} - -void CPU0WakeRxHandler() -{ - xil_printf("CPU 0 - WakeRxHandler reached\r\n"); - - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xMessageBufferSendCompletedFromISR(xCPU1to0MessageBuffer, &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -} -#elif XPAR_CPU_ID == 1 -void CPU1WakeTxHandler() -{ - xil_printf("CPU 1 - WakeTxHandler reached\r\n"); - - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xMessageBufferReceiveCompletedFromISR(xCPU1to0MessageBuffer, &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -} - -void CPU1WakeRxHandler() -{ - xil_printf("CPU 1 - WakeRxHandler reached\r\n"); - - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xMessageBufferSendCompletedFromISR(xCPU0to1MessageBuffer, &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -} -#endif +#include "intr.h" + +/////////////////////////////////////////////////////// +// THIS IS A SHARED FILE, SO IT IS ALWAYS +// IN SYNC IN BOTH CPU0 AND CPU1 +// +// If you need to differentiate something between +// CPUs, use "#if XPAR_CPU_ID == ?" +/////////////////////////////////////////////////////// + +/* The functions in this file are responsible for setting up the + * Xilinx Generic Interrupt Controller (GIC). + * + * Interrupts are needed for Inter-Core Communication, specifically + * the ability to trigger an interrupt in the receiving CPU after a + * message is placed into an empty ICC Message Buffer, + * OR + * the ability to trigger an interrupt in the sending CPU after a + * message is removed from a full ICC Message Buffer + * + * See sys/icc.c for more info. + */ + +int intr_init() +{ + int Status = XST_FAILURE; + + XScuGic_Config *IntcConfig; + + IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID); + XScuGic_CfgInitialize(&InterruptController, IntcConfig, IntcConfig->CpuBaseAddress); + + /* + * Perform a self-test to ensure that the hardware was built + * correctly + */ + Status = XScuGic_SelfTest(&InterruptController); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + // Initialize the interrupt controller + Xil_ExceptionRegisterHandler( + XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler) XScuGic_InterruptHandler, &InterruptController); + Xil_ExceptionEnable(); + +#if XPAR_CPU_ID == 0 + // Connect the given interrupt with its handler + XScuGic_Connect(&InterruptController, INTC_1TO0_SEND_INTERRUPT_ID, (Xil_ExceptionHandler) CPU0WakeRxHandler, NULL); + XScuGic_Connect(&InterruptController, INTC_0TO1_RCVE_INTERRUPT_ID, (Xil_ExceptionHandler) CPU0WakeTxHandler, NULL); + +#elif XPAR_CPU_ID == 1 + // Connect the given interrupt with its handler + XScuGic_Connect(&InterruptController, INTC_0TO1_SEND_INTERRUPT_ID, (Xil_ExceptionHandler) CPU1WakeRxHandler, NULL); + XScuGic_Connect(&InterruptController, INTC_1TO0_RCVE_INTERRUPT_ID, (Xil_ExceptionHandler) CPU1WakeTxHandler, NULL); +#endif + + /* + // Enable the interrupt for the second CPU core + XScuGic_SetPriorityTriggerType(&InterruptController, INTC_INTERRUPT_ID, 0xA0, 3); // Set priority and trigger type + XScuGic_Enable(&InterruptController, INTC_INTERRUPT_ID); + + // Enable the interrupt for CPU1 + Xil_Out32(XPAR_PS7_SCUGIC_DIST_BASEADDR + XSCUGIC_CPU_PRIOR_OFFSET + (CPU1_ID * 4), 0xFF); + Xil_Out32(XPAR_PS7_SCUGIC_DIST_BASEADDR + XSCUGIC_CPU_TARGET_OFFSET + (CPU1_ID * 4), 0x1); + + // Enable interrupts globally + Xil_ExceptionEnableMask(XIL_EXCEPTION_NON_CRITICAL); + + print("Interrupt system setup complete.\r\n"); + */ + + return XST_SUCCESS; +} + +/* We only need to define the handlers in the appropriate core + */ +#if XPAR_CPU_ID == 0 +void CPU0WakeTxHandler() +{ + xil_printf("CPU 0 - WakeTxHandler reached\r\n"); + + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xMessageBufferReceiveCompletedFromISR(xCPU0to1MessageBuffer, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +} + +void CPU0WakeRxHandler() +{ + xil_printf("CPU 0 - WakeRxHandler reached\r\n"); + + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xMessageBufferSendCompletedFromISR(xCPU1to0MessageBuffer, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +} +#elif XPAR_CPU_ID == 1 +void CPU1WakeTxHandler() +{ + xil_printf("CPU 1 - WakeTxHandler reached\r\n"); + + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xMessageBufferReceiveCompletedFromISR(xCPU1to0MessageBuffer, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +} + +void CPU1WakeRxHandler() +{ + xil_printf("CPU 1 - WakeRxHandler reached\r\n"); + + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xMessageBufferSendCompletedFromISR(xCPU0to1MessageBuffer, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +} +#endif diff --git a/sdk/shared/sys/intr.h b/sdk/shared/sys/intr.h index 137771a4..7b29abe0 100644 --- a/sdk/shared/sys/intr.h +++ b/sdk/shared/sys/intr.h @@ -1,51 +1,51 @@ -#ifndef INTR_H -#define INTR_H - -#include "FreeRTOS.h" -#include "icc.h" -#include "xil_exception.h" -#include "xil_printf.h" -#include "xparameters.h" -#include "xscugic.h" - -#include -#include -#include - -// test - -/////////////////////////////////////////////////////// -// THIS IS A SHARED FILE, SO IT IS ALWAYS -// IN SYNC IN BOTH CPU0 AND CPU1 -// -// If you need to differentiate something between -// CPUs, use "#if XPAR_CPU_ID == ?" -/////////////////////////////////////////////////////// - -#define CPU0_ID (XSCUGIC_SPI_CPU0_MASK << 0) -#define CPU1_ID (XSCUGIC_SPI_CPU0_MASK << 1) - -#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID - -#define INTC_0TO1_SEND_INTERRUPT_ID 0U -#define INTC_1TO0_RCVE_INTERRUPT_ID 1U -#define INTC_1TO0_SEND_INTERRUPT_ID 2U -#define INTC_0TO1_RCVE_INTERRUPT_ID 3U - -// Interrupt Controller Instance -// Defined here to be accessable in sys/icc.c -static XScuGic InterruptController; - -int intr_init(); - -/* We only need to define the handlers in the appropriate core - */ -#if XPAR_CPU_ID == 0 -void CPU0WakeTxHandler(); -void CPU0WakeRxHandler(); -#elif XPAR_CPU_ID == 1 -void CPU1WakeTxHandler(); -void CPU1WakeRxHandler(); -#endif - -#endif /* INTR_H */ +#ifndef INTR_H +#define INTR_H + +#include "FreeRTOS.h" +#include "icc.h" +#include "xil_exception.h" +#include "xil_printf.h" +#include "xparameters.h" +#include "xscugic.h" + +#include +#include +#include + +// test + +/////////////////////////////////////////////////////// +// THIS IS A SHARED FILE, SO IT IS ALWAYS +// IN SYNC IN BOTH CPU0 AND CPU1 +// +// If you need to differentiate something between +// CPUs, use "#if XPAR_CPU_ID == ?" +/////////////////////////////////////////////////////// + +#define CPU0_ID (XSCUGIC_SPI_CPU0_MASK << 0) +#define CPU1_ID (XSCUGIC_SPI_CPU0_MASK << 1) + +#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID + +#define INTC_0TO1_SEND_INTERRUPT_ID 0U +#define INTC_1TO0_RCVE_INTERRUPT_ID 1U +#define INTC_1TO0_SEND_INTERRUPT_ID 2U +#define INTC_0TO1_RCVE_INTERRUPT_ID 3U + +// Interrupt Controller Instance +// Defined here to be accessable in sys/icc.c +XScuGic InterruptController; + +int intr_init(); + +/* We only need to define the handlers in the appropriate core + */ +#if XPAR_CPU_ID == 0 +void CPU0WakeTxHandler(); +void CPU0WakeRxHandler(); +#elif XPAR_CPU_ID == 1 +void CPU1WakeTxHandler(); +void CPU1WakeRxHandler(); +#endif + +#endif /* INTR_H */ diff --git a/sdk/shared/sys/serial.c b/sdk/shared/sys/serial.c new file mode 100644 index 00000000..96dc21f5 --- /dev/null +++ b/sdk/shared/sys/serial.c @@ -0,0 +1,85 @@ +/* FreeRTOS includes */ +#include "FreeRTOS.h" +#include "task.h" +/* Other includes */ +#include "sys/serial.h" +#include "drv/uart.h" +#include "sys/util.h" +#include + +#define OUTPUT_BUFFER_LENGTH (32 * 1024) + +static char output_buffer[OUTPUT_BUFFER_LENGTH] = { 0 }; +static int output_idx = 0; + +// Used to mark position in `output_buffer` of char which needs to output +// +// -1 means not currently outputting anything +// >= 0 means trying to print at that idx +static int print_idx = -1; + +// Amount of chars we need to print at the moment +static int print_amount = 0; + + +/* task handle */ +static TaskHandle_t xSerialTaskHandle; +void serial_init(void) +{ + // Create serial task + xTaskCreate(serial_main, (const char *) "uartSerial", configMINIMAL_STACK_SIZE, + NULL, tskIDLE_PRIORITY, &xSerialTaskHandle); +} + +void serial_main(void *arg) +{ + 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) +{ + output_buffer[output_idx] = c; + + output_idx++; + if (output_idx >= OUTPUT_BUFFER_LENGTH) { + output_idx = 0; + } +} + +void serial_write(char *msg, int len) +{ + // Mark index to start outputting at in the callback + if (print_idx == -1) { + print_idx = output_idx; + } + + print_amount += len; + + // Copy contents into circular output buffer + for (int i = 0; i < len; i++) { + _append_to_output_buffer(msg[i]); + } +} diff --git a/sdk/shared/sys/serial.h b/sdk/shared/sys/serial.h new file mode 100644 index 00000000..a0d56aa0 --- /dev/null +++ b/sdk/shared/sys/serial.h @@ -0,0 +1,12 @@ +#ifndef SERIAL_H +#define SERIAL_H + +#define SERIAL_UPDATES_PER_SEC (10000) +#define SERIAL_INTERVAL_TICKS (pdMS_TO_TICKS(1000.0 / SERIAL_UPDATES_PER_SEC)) + +void serial_init(void); +void serial_main(void *arg); + +void serial_write(char *msg, int len); + +#endif // SERIAL_H diff --git a/sdk/shared/sys/util.h b/sdk/shared/sys/util.h new file mode 100644 index 00000000..32bee572 --- /dev/null +++ b/sdk/shared/sys/util.h @@ -0,0 +1,22 @@ +#ifndef UTIL_H +#define UTIL_H + +#include +#include + +#define MIN(x, y) (((x) > (y)) ? (y) : (x)) +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + +#define BITSET(word, nbit) ((word) |= (1 << (nbit))) +#define BITCLEAR(word, nbit) ((word) &= ~(1 << (nbit))) +#define BITFLIP(word, nbit) ((word) ^= (1 << (nbit))) +#define BITCHECK(word, nbit) ((word) & (1 << (nbit))) + +static inline bool STREQ(char *in1, char *in2) +{ + return (strcmp(in1, in2) == 0) ? true : false; +} + +#endif // UTIL_H From 197dc3f290c427275126b0a65a7ee21b4cafa771 Mon Sep 17 00:00:00 2001 From: Ryan Srichai Date: Sat, 20 Jul 2024 13:38:49 -0500 Subject: [PATCH 02/17] checking if git is smart enough to figure this out --- sdk/app_cpu1/common/sys/commands.c | 579 ----------------------------- sdk/app_cpu1/common/sys/commands.h | 63 ---- sdk/app_cpu1/common/sys/debug.c | 24 -- sdk/app_cpu1/common/sys/debug.h | 7 - sdk/app_cpu1/common/sys/defines.h | 28 -- sdk/app_cpu1/common/sys/serial.c | 78 ---- sdk/app_cpu1/common/sys/serial.h | 14 - sdk/app_cpu1/common/sys/util.c | 1 - sdk/app_cpu1/common/sys/util.h | 22 -- 9 files changed, 816 deletions(-) delete mode 100644 sdk/app_cpu1/common/sys/commands.c delete mode 100644 sdk/app_cpu1/common/sys/commands.h delete mode 100644 sdk/app_cpu1/common/sys/debug.c delete mode 100644 sdk/app_cpu1/common/sys/debug.h delete mode 100644 sdk/app_cpu1/common/sys/defines.h delete mode 100644 sdk/app_cpu1/common/sys/serial.c delete mode 100644 sdk/app_cpu1/common/sys/serial.h delete mode 100644 sdk/app_cpu1/common/sys/util.c delete mode 100644 sdk/app_cpu1/common/sys/util.h 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/commands.h b/sdk/app_cpu1/common/sys/commands.h deleted file mode 100644 index 239a22c9..00000000 --- a/sdk/app_cpu1/common/sys/commands.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef COMMANDS_H -#define COMMANDS_H - -#include "sys/scheduler.h" - -#define COMMANDS_UPDATES_PER_SEC (10000) -#define COMMANDS_INTERVAL_USEC (USEC_IN_SEC / COMMANDS_UPDATES_PER_SEC) - -// Supported command handler return codes -// -// NOTE: all commands must return a valid response to the host. -// Only use the resp: "SUCCESS_QUIET" if you will output a valid -// response later in your handler. -// -// For example, "help" and "log dump" work this way. -// -#define CMD_SUCCESS (0) -#define CMD_FAILURE (1) -#define CMD_SUCCESS_QUIET (2) -#define CMD_INVALID_ARGUMENTS (3) -#define CMD_INPUT_TOO_LONG (4) -#define CMD_UNKNOWN_CMD (5) - -// Forward declarations -typedef struct command_entry_t command_entry_t; -typedef struct command_help_t command_help_t; - -typedef struct command_entry_t { - const char *cmd; - const char *desc; - command_help_t *help; - int num_help_cmds; - int (*cmd_function)(int, char **); - - // Pointer to next cmd; set this to NULL in user code. - // When cmd is registered, this will form a linked list. - command_entry_t *next; -} command_entry_t; - -typedef struct command_help_t { - const char *subcmd; - const char *desc; -} command_help_t; - -// Use these functions to output data for a cmd response: -void cmd_resp_write(char *msg, int len); -void cmd_resp_print(char *msg); -void cmd_resp_printf(const char *format, ...); - -void commands_init(void); - -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 **)); -void commands_cmd_register(command_entry_t *cmd_entry); - -void commands_start_msg(void); -void commands_display_help(void); - -#endif // COMMANDS_H diff --git a/sdk/app_cpu1/common/sys/debug.c b/sdk/app_cpu1/common/sys/debug.c deleted file mode 100644 index 3054f8ff..00000000 --- a/sdk/app_cpu1/common/sys/debug.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "sys/debug.h" -#include "sys/serial.h" -#include -#include -#include - -#define BUFFER_LENGTH (1024) -static char buffer[BUFFER_LENGTH] = { 0 }; - -void debug_print(char *msg) -{ - serial_write(msg, strlen(msg)); -} - -void debug_printf(const char *format, ...) -{ - va_list vargs; - va_start(vargs, format); - - vsnprintf(buffer, BUFFER_LENGTH, format, vargs); - debug_print(buffer); - - va_end(vargs); -} diff --git a/sdk/app_cpu1/common/sys/debug.h b/sdk/app_cpu1/common/sys/debug.h deleted file mode 100644 index 85d4b235..00000000 --- a/sdk/app_cpu1/common/sys/debug.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef DEBUG_H -#define DEBUG_H - -void debug_print(char *msg); -void debug_printf(const char *msg, ...); - -#endif // DEBUG_H diff --git a/sdk/app_cpu1/common/sys/defines.h b/sdk/app_cpu1/common/sys/defines.h deleted file mode 100644 index 36228b3e..00000000 --- a/sdk/app_cpu1/common/sys/defines.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef DEFINES_H -#define DEFINES_H - -#include - -#define UNUSED(x) (void) (x) - -#define HANG \ - printf("HANG!!!\n"); \ - while (1) - -#define SUCCESS (0) -#define FAILURE (1) - -#define PI (3.141592653589793238463) // pi -#define PI23 (2.094395102393195492308) // 2*pi/3 -#define PI2 (6.283185307179586476925) // 2*pi - -#define SQRT23 (0.816496580927726032732) // sqrt(2/3) -#define SQRT2 (1.414213562373095048802) // sqrt(2) -#define SQRT3 (1.732050807568877293528) // sqrt(3) - -#define DEG_TO_RAD(deg) (deg * PI / 180.0) -#define RAD_TO_DEG(rad) (rad * 180.0 / PI) -#define RPM_TO_RAD_PER_SEC(rpm) (rpm * PI2 / 60.0) -#define RAD_PER_SEC_TO_RPM(rps) (rps * 60.0 / PI2) - -#endif // DEFINES_H diff --git a/sdk/app_cpu1/common/sys/serial.c b/sdk/app_cpu1/common/sys/serial.c deleted file mode 100644 index cd9d07c9..00000000 --- a/sdk/app_cpu1/common/sys/serial.c +++ /dev/null @@ -1,78 +0,0 @@ -#include "sys/serial.h" -#include "drv/uart.h" -#include "sys/scheduler.h" -#include "sys/util.h" -#include - -#define OUTPUT_BUFFER_LENGTH (32 * 1024) - -static char output_buffer[OUTPUT_BUFFER_LENGTH] = { 0 }; -static int output_idx = 0; - -// Used to mark position in `output_buffer` of char which needs to output -// -// -1 means not currently outputting anything -// >= 0 means trying to print at that idx -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; - -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); -} - -void serial_callback(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; - } - } -} - -static void _append_to_output_buffer(char c) -{ - output_buffer[output_idx] = c; - - output_idx++; - if (output_idx >= OUTPUT_BUFFER_LENGTH) { - output_idx = 0; - } -} - -void serial_write(char *msg, int len) -{ - // Mark index to start outputting at in the callback - if (print_idx == -1) { - print_idx = output_idx; - } - - print_amount += len; - - // Copy contents into circular output buffer - for (int i = 0; i < len; i++) { - _append_to_output_buffer(msg[i]); - } -} diff --git a/sdk/app_cpu1/common/sys/serial.h b/sdk/app_cpu1/common/sys/serial.h deleted file mode 100644 index bcf9e646..00000000 --- a/sdk/app_cpu1/common/sys/serial.h +++ /dev/null @@ -1,14 +0,0 @@ -#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) - -void serial_init(void); -void serial_callback(void *arg); - -void serial_write(char *msg, int len); - -#endif // SERIAL_H 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/common/sys/util.h b/sdk/app_cpu1/common/sys/util.h deleted file mode 100644 index 32bee572..00000000 --- a/sdk/app_cpu1/common/sys/util.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef UTIL_H -#define UTIL_H - -#include -#include - -#define MIN(x, y) (((x) > (y)) ? (y) : (x)) -#define MAX(x, y) (((x) > (y)) ? (x) : (y)) - -#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) - -#define BITSET(word, nbit) ((word) |= (1 << (nbit))) -#define BITCLEAR(word, nbit) ((word) &= ~(1 << (nbit))) -#define BITFLIP(word, nbit) ((word) ^= (1 << (nbit))) -#define BITCHECK(word, nbit) ((word) & (1 << (nbit))) - -static inline bool STREQ(char *in1, char *in2) -{ - return (strcmp(in1, in2) == 0) ? true : false; -} - -#endif // UTIL_H From 750a0d4256eb2397ca19c30d958501d513b23d52 Mon Sep 17 00:00:00 2001 From: Ryan Srichai Date: Sat, 20 Jul 2024 13:41:04 -0500 Subject: [PATCH 03/17] some files removed from appcpu1 so they show up as renames in the shared folder --- sdk/app_cpu1/common/drv/uart.c | 115 ---------------------- sdk/app_cpu1/common/drv/uart.h | 14 --- sdk/app_cpu1/common/sys/cmd/cmd_counter.c | 54 ---------- sdk/app_cpu1/common/sys/cmd/cmd_counter.h | 8 -- sdk/app_cpu1/common/sys/cmd/cmd_help.c | 29 ------ sdk/app_cpu1/common/sys/cmd/cmd_help.h | 8 -- sdk/app_cpu1/user/usr/user_apps.c | 52 ---------- sdk/app_cpu1/user/usr/user_apps.h | 6 -- sdk/app_cpu1/user/usr/user_config.h | 53 ---------- 9 files changed, 339 deletions(-) delete mode 100644 sdk/app_cpu1/common/drv/uart.c delete mode 100644 sdk/app_cpu1/common/drv/uart.h delete mode 100644 sdk/app_cpu1/common/sys/cmd/cmd_counter.c delete mode 100644 sdk/app_cpu1/common/sys/cmd/cmd_counter.h delete mode 100644 sdk/app_cpu1/common/sys/cmd/cmd_help.c delete mode 100644 sdk/app_cpu1/common/sys/cmd/cmd_help.h delete mode 100644 sdk/app_cpu1/user/usr/user_apps.c delete mode 100644 sdk/app_cpu1/user/usr/user_apps.h delete mode 100644 sdk/app_cpu1/user/usr/user_config.h diff --git a/sdk/app_cpu1/common/drv/uart.c b/sdk/app_cpu1/common/drv/uart.c deleted file mode 100644 index 933f936b..00000000 --- a/sdk/app_cpu1/common/drv/uart.c +++ /dev/null @@ -1,115 +0,0 @@ -#include "drv/uart.h" -#include "sys/defines.h" -#include "xparameters.h" -#include "xuartps.h" -#include - -#define UART_DEVICE_ID XPAR_XUARTPS_0_DEVICE_ID - -#define TEST_BUFFER_SIZE (26) - -// Instance of the UART Device -XUartPs UartPs; - -// The following buffers are used in this example to send -// and receive data with the UART. -static u8 SendBuffer[TEST_BUFFER_SIZE]; // Buffer for Transmitting Data -static u8 RecvBuffer[TEST_BUFFER_SIZE]; // Buffer for Receiving Data - -// The following counters are used to determine when the entire -// buffer has been sent and received. -volatile int TotalReceivedCount; -volatile int TotalSentCount; -int TotalErrorCount; - -int uart_init(void) -{ - XUartPs *UartInstPtr = &UartPs; - u16 DeviceId = UART_DEVICE_ID; - - u32 LoopCount = 0; - unsigned int SentCount; - unsigned int ReceivedCount; - - int Status; - XUartPs_Config *Config; - int Index; - - /* - * Initialize the UART driver so that it's ready to use - * Look up the configuration in the config table, then initialize it. - */ - Config = XUartPs_LookupConfig(DeviceId); - if (NULL == Config) { - return FAILURE; - } - - Status = XUartPs_CfgInitialize(UartInstPtr, Config, Config->BaseAddress); - if (Status != XST_SUCCESS) { - return FAILURE; - } - - /* Check hardware build */ - Status = XUartPs_SelfTest(UartInstPtr); - if (Status != XST_SUCCESS) { - return FAILURE; - } - - /* Use local loopback mode. */ - XUartPs_SetOperMode(UartInstPtr, XUARTPS_OPER_MODE_LOCAL_LOOP); - - /* - * Initialize the send buffer bytes with a pattern and zero out - * the receive buffer. - */ - for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) { - SendBuffer[Index] = (Index % 26) + 'A'; - RecvBuffer[Index] = 0; - } - - /* Block sending the buffer. */ - SentCount = XUartPs_Send(UartInstPtr, SendBuffer, TEST_BUFFER_SIZE); - if (SentCount != TEST_BUFFER_SIZE) { - return FAILURE; - } - - /* - * Wait while the UART is sending the data so that we are guaranteed - * to get the data the 1st time we call receive, otherwise this function - * may enter receive before the data has arrived - */ - while (XUartPs_IsSending(UartInstPtr)) { - LoopCount++; - } - - /* Block receiving the buffer. */ - ReceivedCount = 0; - while (ReceivedCount < TEST_BUFFER_SIZE) { - ReceivedCount += XUartPs_Recv(UartInstPtr, &RecvBuffer[ReceivedCount], (TEST_BUFFER_SIZE - ReceivedCount)); - } - - /* - * Check the receive buffer against the send buffer and verify the - * data was correctly received - */ - for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) { - if (SendBuffer[Index] != RecvBuffer[Index]) { - return FAILURE; - } - } - - /* Restore to normal mode. */ - XUartPs_SetOperMode(UartInstPtr, XUARTPS_OPER_MODE_NORMAL); - - return SUCCESS; -} - -int uart_send(char *msg, int len) -{ - return XUartPs_Send(&UartPs, (uint8_t *) msg, len); -} - -int uart_recv(char *msg, int len) -{ - return XUartPs_Recv(&UartPs, (uint8_t *) msg, len); -} diff --git a/sdk/app_cpu1/common/drv/uart.h b/sdk/app_cpu1/common/drv/uart.h deleted file mode 100644 index d63a6332..00000000 --- a/sdk/app_cpu1/common/drv/uart.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef UART_H -#define UART_H - -#include - -#define UART_RX_FIFO_LENGTH (64) -#define UART_TX_FIFO_LENGTH (64) - -int uart_init(void); - -int uart_send(char *msg, int len); -int uart_recv(char *msg, int len); - -#endif // UART_H diff --git a/sdk/app_cpu1/common/sys/cmd/cmd_counter.c b/sdk/app_cpu1/common/sys/cmd/cmd_counter.c deleted file mode 100644 index 82ac0d34..00000000 --- a/sdk/app_cpu1/common/sys/cmd/cmd_counter.c +++ /dev/null @@ -1,54 +0,0 @@ -#include "sys/cmd/cmd_counter.h" -#include "sys/commands.h" -#include "sys/defines.h" -#include "sys/util.h" -#include -#include -#include - -static command_entry_t cmd_entry; - -static command_help_t cmd_help[] = { - { "inc", "Increment CNT reg" }, - { "dec", "Decrement CNT reg" }, - { "clr", "Clear CNT reg" }, - { "get", "Get CNT reg" }, -}; - -void cmd_counter_register(void) -{ - // Populate the command entry block - commands_cmd_init( - &cmd_entry, "counter", "Counter reg related commands", cmd_help, ARRAY_SIZE(cmd_help), cmd_counter); - - // Register the command - commands_cmd_register(&cmd_entry); -} - -static int CNT = 0; - -// Handles the 'counter' command and all sub-commands -int cmd_counter(int argc, char **argv) -{ - if (argc == 2 && STREQ("inc", argv[1])) { - CNT++; - return CMD_SUCCESS; - } - - if (argc == 2 && STREQ("dec", argv[1])) { - CNT--; - return CMD_SUCCESS; - } - - if (argc == 2 && STREQ("clr", argv[1])) { - CNT = 0; - return CMD_SUCCESS; - } - - if (argc == 2 && STREQ("get", argv[1])) { - cmd_resp_printf("CNT = %d\r\n", CNT); - return CMD_SUCCESS; - } - - return CMD_INVALID_ARGUMENTS; -} diff --git a/sdk/app_cpu1/common/sys/cmd/cmd_counter.h b/sdk/app_cpu1/common/sys/cmd/cmd_counter.h deleted file mode 100644 index a9fa6f16..00000000 --- a/sdk/app_cpu1/common/sys/cmd/cmd_counter.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef CMD_COUNTER_H -#define CMD_COUNTER_H - -void cmd_counter_register(void); - -int cmd_counter(int argc, char **argv); - -#endif // CMD_COUNTER_H diff --git a/sdk/app_cpu1/common/sys/cmd/cmd_help.c b/sdk/app_cpu1/common/sys/cmd/cmd_help.c deleted file mode 100644 index 03793982..00000000 --- a/sdk/app_cpu1/common/sys/cmd/cmd_help.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "cmd_help.h" -#include "sys/commands.h" -#include -#include - -static command_entry_t cmd_entry; - -void cmd_help_register(void) -{ - // Populate the command entry block - commands_cmd_init(&cmd_entry, "help", "Display this help message", NULL, 0, cmd_help); - - // Register the command - commands_cmd_register(&cmd_entry); -} - -// -// Handles the 'help' command -// -int cmd_help(int argc, char **argv) -{ - if (argc > 1) { - return CMD_INVALID_ARGUMENTS; - } - - commands_display_help(); - - return CMD_SUCCESS_QUIET; -} diff --git a/sdk/app_cpu1/common/sys/cmd/cmd_help.h b/sdk/app_cpu1/common/sys/cmd/cmd_help.h deleted file mode 100644 index 130a1a93..00000000 --- a/sdk/app_cpu1/common/sys/cmd/cmd_help.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef CMD_HELP_H -#define CMD_HELP_H - -void cmd_help_register(void); - -int cmd_help(int argc, char **argv); - -#endif // CMD_HELP_H diff --git a/sdk/app_cpu1/user/usr/user_apps.c b/sdk/app_cpu1/user/usr/user_apps.c deleted file mode 100644 index d87a85f4..00000000 --- a/sdk/app_cpu1/user/usr/user_apps.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "usr/user_apps.h" - -// Adding applications: -// -// To add a new application, create a block -// like the other example(s) below which -// conditionally includes the app's header file. -// -// Also, conditionally call the app's init function. - -#ifdef APP_PCBTEST -#include "usr/pcbtest/app_pcbtest.h" -#endif - -#ifdef APP_BLINK -#include "usr/blink/app_blink.h" -#endif - -#ifdef APP_BETA_LABS -#include "usr/beta_labs/app_beta_labs.h" -#endif - -#ifdef APP_DEMO -#include "usr/demo/app_demo.h" -#endif - -#ifdef APP_DAC -#include "usr/dac/app_dac.h" -#endif - -void user_apps_init(void) -{ -#ifdef APP_PCBTEST - app_pcbtest_init(); -#endif - -#ifdef APP_BLINK - app_blink_init(); -#endif - -#ifdef APP_BETA_LABS - app_beta_labs_init(); -#endif - -#ifdef APP_DEMO - app_demo_init(); -#endif - -#ifdef APP_DAC - app_dac_init(); -#endif -} diff --git a/sdk/app_cpu1/user/usr/user_apps.h b/sdk/app_cpu1/user/usr/user_apps.h deleted file mode 100644 index 1564485c..00000000 --- a/sdk/app_cpu1/user/usr/user_apps.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef USER_APPS_H -#define USER_APPS_H - -void user_apps_init(void); - -#endif // USER_APPS_H diff --git a/sdk/app_cpu1/user/usr/user_config.h b/sdk/app_cpu1/user/usr/user_config.h deleted file mode 100644 index 53b3c8b8..00000000 --- a/sdk/app_cpu1/user/usr/user_config.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef USER_CONFIG_H -#define USER_CONFIG_H - -#include "drv/hardware_targets.h" - -// This file is used to override system defines and conditionally enable -// various system-level firmware features. - -// 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 -#define USER_CONFIG_ENABLE_TASK_STATISTICS_BY_DEFAULT (0) - -// Enable the watchdog timer -// set to 1 for enabled, 0 for disabled -#define USER_CONFIG_ENABLE_WATCHDOG (0) - -// Enable logging functionality -// set to 1 for enabled, 0 for disabled -#define USER_CONFIG_ENABLE_LOGGING (0) - -// Override default number of available logging variables -// when defined, this takes precedence over system default of 32 -//#define USER_CONFIG_LOGGING_MAX_NUM_VARIABLES (150) - -// Override default logging sample depth per variable -// when defined, this takes precedence over system default of 100k -//#define USER_CONFIG_LOGGING_SAMPLE_DEPTH_PER_VARIABLE (50000) - -// Enable injection functionality -// set to 1 for enabled, 0 for disabled -#define USER_CONFIG_ENABLE_INJECTION (0) - -// Enable SensorCard platform motherboard support -// set to 1 for enabled, 0 for disabled -#define USER_CONFIG_ENABLE_MOTHERBOARD_SUPPORT (0) - -// Enable SensorCard platform motherboard auto request new ADC sample data -// set to 1 for enabled, 0 for disabled -#define USER_CONFIG_ENABLE_MOTHERBOARD_AUTO_TX (0) - -#endif // USER_CONFIG_H From 04787c193c2d6a8ea3eab4ace5259c22fa1361c6 Mon Sep 17 00:00:00 2001 From: Ryan Srichai Date: Fri, 2 Aug 2024 12:05:01 -0500 Subject: [PATCH 04/17] removed game app --- sdk/app_cpu1/user/usr/blink/task_blink.c | 78 ---------- sdk/app_cpu1/user/usr/blink/task_vsi.c | 55 ------- sdk/app_cpu1/user/usr/blink/task_vsi.h | 13 -- .../src}/usr/blink/README.md | 0 .../src}/usr/blink/app_blink.c | 0 .../src}/usr/blink/app_blink.h | 0 .../src}/usr/blink/cmd/cmd_blink.c | 0 .../src}/usr/blink/cmd/cmd_blink.h | 0 .../src/usr/blink/task_blink.c | 92 ++++++++++++ .../src}/usr/blink/task_blink.h | 8 +- .../src/usr/blink/task_vsi.c | 55 +++++++ .../src/usr/blink/task_vsi.h | 15 ++ sdk/freertos_app_cpu0/src/usr/game/app_game.c | 16 -- sdk/freertos_app_cpu0/src/usr/game/app_game.h | 6 - .../src/usr/game/cmd/cmd_game.c | 106 ------------- .../src/usr/game/cmd/cmd_game.h | 12 -- .../src/usr/game/task_game.c | 140 ------------------ .../src/usr/game/task_game.h | 48 ------ sdk/freertos_app_cpu0/src/usr/user_apps.c | 16 -- sdk/freertos_app_cpu0/src/usr/user_config.h | 39 +++++ 20 files changed, 206 insertions(+), 493 deletions(-) delete mode 100644 sdk/app_cpu1/user/usr/blink/task_blink.c delete mode 100644 sdk/app_cpu1/user/usr/blink/task_vsi.c delete mode 100644 sdk/app_cpu1/user/usr/blink/task_vsi.h rename sdk/{app_cpu1/user => freertos_app_cpu0/src}/usr/blink/README.md (100%) rename sdk/{app_cpu1/user => freertos_app_cpu0/src}/usr/blink/app_blink.c (100%) rename sdk/{app_cpu1/user => freertos_app_cpu0/src}/usr/blink/app_blink.h (100%) rename sdk/{app_cpu1/user => freertos_app_cpu0/src}/usr/blink/cmd/cmd_blink.c (100%) rename sdk/{app_cpu1/user => freertos_app_cpu0/src}/usr/blink/cmd/cmd_blink.h (100%) create mode 100644 sdk/freertos_app_cpu0/src/usr/blink/task_blink.c rename sdk/{app_cpu1/user => freertos_app_cpu0/src}/usr/blink/task_blink.h (82%) create mode 100644 sdk/freertos_app_cpu0/src/usr/blink/task_vsi.c create mode 100644 sdk/freertos_app_cpu0/src/usr/blink/task_vsi.h delete mode 100644 sdk/freertos_app_cpu0/src/usr/game/app_game.c delete mode 100644 sdk/freertos_app_cpu0/src/usr/game/app_game.h delete mode 100644 sdk/freertos_app_cpu0/src/usr/game/cmd/cmd_game.c delete mode 100644 sdk/freertos_app_cpu0/src/usr/game/cmd/cmd_game.h delete mode 100644 sdk/freertos_app_cpu0/src/usr/game/task_game.c delete mode 100644 sdk/freertos_app_cpu0/src/usr/game/task_game.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/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..2a84c892 --- /dev/null +++ b/sdk/freertos_app_cpu0/src/usr/blink/task_blink.c @@ -0,0 +1,92 @@ +#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 + +// 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, tskIDLE_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..e6e7bbe7 --- /dev/null +++ b/sdk/freertos_app_cpu0/src/usr/blink/task_vsi.c @@ -0,0 +1,55 @@ +#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 +#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, tskIDLE_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..eeaf396f --- /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/freertos_app_cpu0/src/usr/game/app_game.c b/sdk/freertos_app_cpu0/src/usr/game/app_game.c deleted file mode 100644 index 2eec8e98..00000000 --- a/sdk/freertos_app_cpu0/src/usr/game/app_game.c +++ /dev/null @@ -1,16 +0,0 @@ -#ifdef APP_GAME - -#include "usr/game/app_game.h" -#include "usr/game/cmd/cmd_game.h" -#include "usr/game/task_game.h" - -void app_game_init(void) -{ - // Register "game" command with system - cmd_game_register(); - - // Initialize game task with system - task_game_init(); -} - -#endif // APP_GAME diff --git a/sdk/freertos_app_cpu0/src/usr/game/app_game.h b/sdk/freertos_app_cpu0/src/usr/game/app_game.h deleted file mode 100644 index 1aee03ad..00000000 --- a/sdk/freertos_app_cpu0/src/usr/game/app_game.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef APP_GAME_H -#define APP_GAME_H - -void app_game_init(void); - -#endif // APP_GAME_H diff --git a/sdk/freertos_app_cpu0/src/usr/game/cmd/cmd_game.c b/sdk/freertos_app_cpu0/src/usr/game/cmd/cmd_game.c deleted file mode 100644 index c5d5daed..00000000 --- a/sdk/freertos_app_cpu0/src/usr/game/cmd/cmd_game.c +++ /dev/null @@ -1,106 +0,0 @@ -#ifdef APP_GAME -#include "cmd_game.h" -#include "usr/game/task_game.h" -#include "sys/commands.h" -#include "sys/debug.h" -#include "sys/defines.h" -#include "sys/util.h" -#include -#include - -static command_entry_t cmd_entry1; -static command_entry_t cmd_entry2; -static command_entry_t cmd_entry3; -static command_entry_t cmd_entry4; -static command_entry_t cmd_entryRestart; - -static command_help_t cmd_help1[] = { - { "1", "Send when LED 1 is on" } -}; - -static command_help_t cmd_help2[] = { - { "2", "Send when LED 2 is on" } -}; - -static command_help_t cmd_help3[] = { - { "3", "Send when LED 3 is on" } -}; - -static command_help_t cmd_help4[] = { - { "4", "Send when LED 4 is on" } -}; - -static command_help_t cmd_helpRestart[] = { - { "r", "Send to restart the game" } -}; - -void cmd_game_register(void) -{ - // Populate the command entry block - commands_cmd_init(&cmd_entry1, "1", "Game 1 command", cmd_help1, ARRAY_SIZE(cmd_help1), cmd_game1); - commands_cmd_init(&cmd_entry2, "2", "Game 2 command", cmd_help2, ARRAY_SIZE(cmd_help2), cmd_game2); - commands_cmd_init(&cmd_entry3, "3", "Game 3 command", cmd_help3, ARRAY_SIZE(cmd_help3), cmd_game3); - commands_cmd_init(&cmd_entry4, "4", "Game 4 command", cmd_help4, ARRAY_SIZE(cmd_help4), cmd_game4); - commands_cmd_init(&cmd_entryRestart, "r", "Restart command", cmd_helpRestart, ARRAY_SIZE(cmd_helpRestart), cmd_gameRestart); - - // Register the command - commands_cmd_register(&cmd_entry1); - commands_cmd_register(&cmd_entry2); - commands_cmd_register(&cmd_entry3); - commands_cmd_register(&cmd_entry4); - commands_cmd_register(&cmd_entryRestart); -} - -int cmd_game1(int argc, char **argv) { - if (getGameLedOn() == 1) { - while (getGameLedOn() == 1) { - setGameLedOn(randomInt(1, 4)); - } - incrementGameScore(); - return CMD_SUCCESS; - } - decrementGameScore(); - return CMD_FAILURE; -} - -int cmd_game2(int argc, char **argv) { - if (getGameLedOn() == 2) { - while (getGameLedOn() == 2) { - setGameLedOn(randomInt(1, 4)); - } - incrementGameScore(); - return CMD_SUCCESS; - } - decrementGameScore(); - return CMD_FAILURE; -} - -int cmd_game3(int argc, char **argv) { - if (getGameLedOn() == 3) { - while (getGameLedOn() == 3) { - setGameLedOn(randomInt(1, 4)); - } - incrementGameScore(); - return CMD_SUCCESS; - } - decrementGameScore(); - return CMD_FAILURE; -} - -int cmd_game4(int argc, char **argv) { - if (getGameLedOn() == 4) { - while (getGameLedOn() == 4) { - setGameLedOn(randomInt(1, 4)); - } - incrementGameScore(); - return CMD_SUCCESS; - } - decrementGameScore(); - return CMD_FAILURE; -} - -int cmd_gameRestart(int argc, char **argv) { - reset_game(); - return CMD_SUCCESS; -} -#endif // APP_GAME diff --git a/sdk/freertos_app_cpu0/src/usr/game/cmd/cmd_game.h b/sdk/freertos_app_cpu0/src/usr/game/cmd/cmd_game.h deleted file mode 100644 index dc7b5466..00000000 --- a/sdk/freertos_app_cpu0/src/usr/game/cmd/cmd_game.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef CMD_GAME_H -#define CMD_GAME_H - -void cmd_game_register(void); - -int cmd_game1(int argc, char **argv); -int cmd_game2(int argc, char **argv); -int cmd_game3(int argc, char **argv); -int cmd_game4(int argc, char **argv); -int cmd_gameRestart(int argc, char **argv); - -#endif // CMD_GAME_H diff --git a/sdk/freertos_app_cpu0/src/usr/game/task_game.c b/sdk/freertos_app_cpu0/src/usr/game/task_game.c deleted file mode 100644 index 2893fa1f..00000000 --- a/sdk/freertos_app_cpu0/src/usr/game/task_game.c +++ /dev/null @@ -1,140 +0,0 @@ -#ifdef APP_GAME - -/* FreeRTOS includes */ -#include "FreeRTOS.h" -#include "task.h" -/* Xilinx includes. */ -#include "xil_printf.h" -/* other includes */ -#include "usr/game/task_game.h" -#include "drv/led.h" -#include -#include - -/* from: https://www.quora.com/Can-we-get-a-random-number-without-using-rand-in-C-C-and-Python */ -int randCustom() { - static int next = 3251 ; // Anything you like here - but not - // 0000, 0100, 2500, 3792, 7600, - // 0540, 2916, 5030 or 3009. - next = ((next * next) / 100) % 10000; - return next ; -} - -int randomInt(int lowerBound, int upperBound) { // random integer between lower and upper bound (inclusive) - return randCustom() % (upperBound + 1 - lowerBound) + lowerBound; -} - -int gameScore = 0; - -void incrementGameScore() { - gameScore++; -} - -void decrementGameScore() { - gameScore--; -} - -uint8_t game_led_on = 1; - -uint8_t getGameLedOn() { - return game_led_on; -} - -void setGameLedOn(uint8_t setTo) { - if (!game_started()) { - start_game(); - } - led_set_color(game_led_on - 1, LED_COLOR_BLACK); - led_set_color(setTo - 1, LED_COLOR_GREEN); - game_led_on = setTo; -} - -// Hold LED animation state -static uint8_t led_pos = 0; -static uint8_t led_color_idx = 0; -// Scheduler TCB which holds task "context" -static TaskHandle_t tcb; - -int task_game_init(void) -{ - // Turn off all LEDs - for (uint8_t i = 1; i < NUM_LEDS; i++) { - led_set_color(i, LED_COLOR_BLACK); - } - // Turn on first LED to RED - led_set_color(0, LED_COLOR_RED); - - // Command parse task (UART) - xTaskCreate(task_game, (const char *) "game", configMINIMAL_STACK_SIZE, - NULL, tskIDLE_PRIORITY, &tcb); - - return 0; -} - -int task_game_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; - - return 0; -} - -int callbackIter = -2; -int secondsLeft = 30; - -void start_game() { - callbackIter = 0; - secondsLeft = 30; -} - -void reset_game() { - // Turn off all LEDs - for (uint8_t i = 1; i < NUM_LEDS; i++) { - led_set_color(i, LED_COLOR_BLACK); - } - // Turn on first LED to RED - led_set_color(0, LED_COLOR_RED); - callbackIter = -2; - gameScore = 0; - game_led_on = 1; -} - -int game_started() { - if (callbackIter == -2) { - return 0; - } - return 1; -} - -void task_game(void *arg) -{ - const TickType_t delayTicks = pdMS_TO_TICKS(1000.0 / TASK_GAME_UPDATES_PER_SEC); - for (;;) { - vTaskDelay(delayTicks); -// xil_printf("hello\n"); - if (callbackIter >= 0) { - // printf("Callback called %d\n", callbackIter); - callbackIter++; - if (callbackIter % 5 == 0) { - xil_printf("%d seconds left\n", secondsLeft); - secondsLeft--; - } - if (callbackIter > 150) { - game_led_on = 0; - for (uint8_t i = 0; i < NUM_LEDS; i++) { - led_set_color(i, LED_COLOR_BLACK); - } - callbackIter = -1; - xil_printf("Time's up! Score: %d\n", gameScore); - } - } - } -} - -#endif // APP_GAME diff --git a/sdk/freertos_app_cpu0/src/usr/game/task_game.h b/sdk/freertos_app_cpu0/src/usr/game/task_game.h deleted file mode 100644 index 943cf400..00000000 --- a/sdk/freertos_app_cpu0/src/usr/game/task_game.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef TASK_GAME_H -#define TASK_GAME_H - -/* FreeRTOS includes */ -#include "FreeRTOS.h" -#include "task.h" - -// Frequency that this task is called (in Hz) -// -// Must be less than or equal to scheduler updates per second -// This value is defined in sys/scheduler.h and defaults to 10kHz. -// Note that it can be overridden via usr/user_config.h -#define TASK_GAME_UPDATES_PER_SEC (5) - -// Microseconds interval between when task is called -// -// This is what scheduler actually uses to run task, -// but is generated via define above -#define TASK_GAME_INTERVAL_USEC (USEC_IN_SEC / TASK_GAME_UPDATES_PER_SEC) - -void incrementGameScore(); -void decrementGameScore(); - -uint8_t getGameLedOn(); -void setGameLedOn(uint8_t setTo); -int randomInt(int lowerBound, int upperBound); - -// Called in app init function to set up task (or via command) -int task_game_init(void); -int task_game_deinit(void); - -// start the game timer -void start_game(); -void reset_game(); - -// returns 1 if the game is already started and 0 otherwise -int game_started(); - -// Callback function which scheduler calls periodically -void task_game(void *arg); - -// Print the statistics gathered by the scheduler -void task_game_stats_print(void); - -// Reset the statistics gathered by the scheduler -void task_game_stats_reset(void); - -#endif // TASK_GAME_H diff --git a/sdk/freertos_app_cpu0/src/usr/user_apps.c b/sdk/freertos_app_cpu0/src/usr/user_apps.c index 2bea0f19..d87a85f4 100644 --- a/sdk/freertos_app_cpu0/src/usr/user_apps.c +++ b/sdk/freertos_app_cpu0/src/usr/user_apps.c @@ -16,14 +16,6 @@ #include "usr/blink/app_blink.h" #endif -#ifdef APP_GAME -#include "usr/game/app_game.h" -#endif - -#ifdef APP_MATH -#include "usr/math/app_math.h" -#endif - #ifdef APP_BETA_LABS #include "usr/beta_labs/app_beta_labs.h" #endif @@ -46,14 +38,6 @@ void user_apps_init(void) app_blink_init(); #endif -#ifdef APP_GAME - app_game_init(); -#endif - -#ifdef APP_MATH - app_math_init(); -#endif - #ifdef APP_BETA_LABS app_beta_labs_init(); #endif diff --git a/sdk/freertos_app_cpu0/src/usr/user_config.h b/sdk/freertos_app_cpu0/src/usr/user_config.h index 65066adf..6f448c47 100644 --- a/sdk/freertos_app_cpu0/src/usr/user_config.h +++ b/sdk/freertos_app_cpu0/src/usr/user_config.h @@ -1,6 +1,45 @@ #ifndef USER_CONFIG_H #define USER_CONFIG_H +#include "drv/hardware_targets.h" +// This file is used to override system defines and conditionally enable +// various system-level firmware features. + +// Specify hardware revision (i.e. REV E, REV F, etc) +#define USER_CONFIG_HARDWARE_TARGET (AMDC_REV_F) + +// 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 +#define USER_CONFIG_ENABLE_TASK_STATISTICS_BY_DEFAULT (0) + +// Enable the watchdog timer +// set to 1 for enabled, 0 for disabled +#define USER_CONFIG_ENABLE_WATCHDOG (0) + +// Enable logging functionality +// set to 1 for enabled, 0 for disabled +#define USER_CONFIG_ENABLE_LOGGING (0) + +// Override default number of available logging variables +// when defined, this takes precedence over system default of 32 +//#define USER_CONFIG_LOGGING_MAX_NUM_VARIABLES (150) + +// Override default logging sample depth per variable +// when defined, this takes precedence over system default of 100k +//#define USER_CONFIG_LOGGING_SAMPLE_DEPTH_PER_VARIABLE (50000) + +// Enable injection functionality +// set to 1 for enabled, 0 for disabled +#define USER_CONFIG_ENABLE_INJECTION (0) + +// Enable SensorCard platform motherboard support +// set to 1 for enabled, 0 for disabled +#define USER_CONFIG_ENABLE_MOTHERBOARD_SUPPORT (0) + +// Enable SensorCard platform motherboard auto request new ADC sample data +// set to 1 for enabled, 0 for disabled +#define USER_CONFIG_ENABLE_MOTHERBOARD_AUTO_TX (0) #endif // USER_CONFIG_H From ac4b7d31a4ff43788ad4cd88458bb53b5bc10613 Mon Sep 17 00:00:00 2001 From: Ryan Srichai Date: Fri, 2 Aug 2024 12:13:00 -0500 Subject: [PATCH 05/17] readded queue and blinky tasks to main.c --- sdk/freertos_app_cpu0/src/main.c | 248 ++++++++++++++++++++++++++++++- 1 file changed, 247 insertions(+), 1 deletion(-) diff --git a/sdk/freertos_app_cpu0/src/main.c b/sdk/freertos_app_cpu0/src/main.c index 6cae3bae..ff2984d1 100644 --- a/sdk/freertos_app_cpu0/src/main.c +++ b/sdk/freertos_app_cpu0/src/main.c @@ -52,6 +52,18 @@ #include "usr/user_apps.h" /* End User Includes */ +#define TIMER_ID 1 +#define DELAY_10_SECONDS 10000UL +#define DELAY_1_SECOND 1000UL +#define TIMER_CHECK_THRESHOLD 9 +/*-----------------------------------------------------------*/ + +/* The Tx and Rx tasks as described at the top of this file. */ +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 /*-----------------------------------------------------------*/ @@ -87,12 +99,52 @@ 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; +static QueueHandle_t xQueue = NULL; +static TimerHandle_t xTimer = NULL; + +char HWstring[32] = "CPU0 - Hello World"; +long RxtaskCntr = 0; + +uint8_t message_status = 0; +// 0 - sending messages +// 1 - complete, success +// 2 - complete, failure + int main(void) { // Both CPUs: Disable cache on OCM // S=b1 TEX=b100 AP=b11, Domain=b1111, C=b0, B=b0 Xil_SetTlbAttributes(0xFFFF0000, 0x14de2); +#if 1 + // CPU0 ONLY: + // This code is required to start CPU1 from CPU0 during boot. + // + // This only applies when booting from flash via the FSBL. + // During development with JTAG loading, these low-level + // calls in this #if block are not needed! However, we'll + // keep them here since it doesn't affect performance... + + // Write starting base address for CPU1 PC. + // It will look for this address upon waking up + static const uintptr_t CPU1_START_ADDR = 0xFFFFFFF0; + static const uint32_t CPU1_BASE_ADDR = 0x20080000; + Xil_Out32(CPU1_START_ADDR, CPU1_BASE_ADDR); + + // Waits until write has finished + // DMB = Data Memory Barrier + dmb(); + + // Wake up CPU1 by sending the SEV command + // SEV = Set Event, which causes CPU1 to wake up and jump to CPU1_BASE_ADDR + __asm__("sev"); +#endif + + Xil_ExceptionInit(); intr_init(); icc_init(); @@ -122,6 +174,56 @@ int main(void) // 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. */ + (const char *) "CPU0_Tx", /* Text name for the task, provided to assist debugging only. */ + configMINIMAL_STACK_SIZE, /* The stack allocated to the task. */ + NULL, /* The task parameter is not used, so set to NULL. */ + tskIDLE_PRIORITY, /* The task runs at the idle priority. */ + &xTxTaskHandle); + + xTaskCreate(prvRxTask, /* The function that implements the task. */ + (const char *) "CPU0_Rx", /* Text name for the task, provided to assist debugging only. */ + configMINIMAL_STACK_SIZE, + NULL, + tskIDLE_PRIORITY + 1, + &xRxTaskHandle); + + // Create additional blinky task - CPU0 only + xTaskCreate(prvBlinkyTask, + (const char *) "CPU0_Blinky", + configMINIMAL_STACK_SIZE, + NULL, + tskIDLE_PRIORITY, + &xBlinkyTaskHandle); + + /* Create the queue used by the tasks. The Rx task has a higher priority + than the Tx task, so will preempt the Tx task and remove values from the + queue as soon as the Tx task writes to the queue - therefore the queue can + never have more than one item in it. */ + xQueue = xQueueCreate(1, sizeof(HWstring)); + + /* Check the queue was created. */ + configASSERT(xQueue); + + /* Create a timer with a timer expiry of 10 seconds. The timer would expire + after 10 seconds and the timer call back would get called. In the timer call back + checks are done to ensure that the tasks have been running properly till then. + The tasks are deleted in the timer call back and a message is printed to convey that + the example has run successfully. + The timer expiry is set to 10 seconds and the timer set to not auto reload. */ + xTimer = xTimerCreate((const char *) "CPU0_Timer", x10seconds, pdFALSE, (void *) TIMER_ID, vTimerCallback); + + /* Check the timer was created. */ + configASSERT(xTimer); + + /* start the timer with a block time of 0 ticks. This means as soon + as the schedule starts the timer will start running and will expire after + 10 seconds */ + xTimerStart(xTimer, 0); + ///////////////////////// // END USER CODE HERE // /////////////////////// @@ -135,7 +237,151 @@ 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 A TERRIBLE ERROR HAS OCCURRED!\n"); + xil_printf("IF YOU'RE READING THIS THEN HEAP MEMORY HAS RUN OUT!\n"); + } +} + +/*-----------------------------------------------------------*/ +static void prvTxTask(void *pvParameters) +{ + const TickType_t x1second = pdMS_TO_TICKS(DELAY_1_SECOND); + + for (;;) { + if (message_status > 0) { + // Cannot delete tasks created using heap_1 implementation, so instead we suspend immediately if done + vTaskSuspend(NULL); + } else { + /* Delay for 1 second. */ + vTaskDelay(x1second); + + /* Send the next value on the queue. The queue should always be + empty at this point so a block time of 0 is used. */ + // xQueueSend(xQueue, /* The queue being written to. */ + // HWstring, /* The address of the data being sent. */ + // 0UL); /* The block time. */ + + xil_printf("DEBUG: CPU 0 about to attempt send\r\n"); + + // Send a message to the other core + size_t bytes_sent = xMessageBufferSend(xCPU0to1MessageBuffer, HWstring, sizeof(HWstring), 0UL); + + xil_printf("DEBUG: CPU0 sent %d bytes to ICC buffer\r\n", bytes_sent); + + if (bytes_sent == 0) { + xil_printf("ERROR: CPU 0 failed to write to ICC buffer\r\n"); + } + } + } +} + +/*-----------------------------------------------------------*/ +static void prvRxTask(void *pvParameters) +{ + char Rcvdstring[32] = ""; + + for (;;) { + if (message_status > 0) { + // Cannot delete tasks created using heap_1 implementation, so instead we suspend immediately if done + vTaskSuspend(NULL); + } else { + + // /* Block to wait for data arriving on the queue. */ + // xQueueReceive(xQueue, /* The queue being read. */ + // Rcvdstring, /* Data is read into this address. */ + // portMAX_DELAY); /* Wait without a timeout for data. */ + + xil_printf("DEBUG: CPU 0 about to attempt rcv\r\n"); + + size_t bytes_rcvd = xMessageBufferReceive(xCPU1to0MessageBuffer, Rcvdstring, 32, portMAX_DELAY); + + xil_printf("DEBUG: CPU0 rcvd %d bytes from ICC buffer\r\n", bytes_rcvd); + + if (bytes_rcvd == 0) { + xil_printf("CPU 0 failed to receive from ICC buffer\r\n"); + } else { + /* Print the received data. */ + xil_printf("CPU0 - Rx task received string from CPU1 Tx: %s\r\n", Rcvdstring); + RxtaskCntr++; + } + } + } +} + +/*-----------------------------------------------------------*/ +static void prvBlinkyTask(void *pvParameters) +{ + const TickType_t x250ms = pdMS_TO_TICKS(DELAY_1_SECOND / 4); + uint8_t led_offset = 0; + + for (;;) { + if (message_status == 0) { + // If not complete, cycle yellow every 250ms + vTaskDelay(x250ms); + + led_set_color(0 + led_offset, LED_COLOR_YELLOW); + led_set_color(1 + led_offset, LED_COLOR_BLACK); + led_set_color(2 + led_offset, LED_COLOR_BLACK); + led_set_color(3 + led_offset, LED_COLOR_BLACK); + + led_offset = (led_offset + 1) % 4; + } else if (message_status == 1) { + // If complete, flash all green every 250ms + vTaskDelay(x250ms); + + led_set_color(LED0, LED_COLOR_BLACK); + led_set_color(LED1, LED_COLOR_BLACK); + led_set_color(LED2, LED_COLOR_BLACK); + led_set_color(LED3, LED_COLOR_BLACK); + + vTaskDelay(x250ms); + + led_set_color(LED0, LED_COLOR_GREEN); + led_set_color(LED1, LED_COLOR_GREEN); + led_set_color(LED2, LED_COLOR_GREEN); + led_set_color(LED3, LED_COLOR_GREEN); + } else { + // message_status must be 2, meaning failure + // flash all red every 250ms + vTaskDelay(x250ms); + + led_set_color(LED0, LED_COLOR_BLACK); + led_set_color(LED1, LED_COLOR_BLACK); + led_set_color(LED2, LED_COLOR_BLACK); + led_set_color(LED3, LED_COLOR_BLACK); + + vTaskDelay(x250ms); + + led_set_color(LED0, LED_COLOR_RED); + led_set_color(LED1, LED_COLOR_RED); + led_set_color(LED2, LED_COLOR_RED); + led_set_color(LED3, LED_COLOR_RED); + } + } +} + +/*-----------------------------------------------------------*/ +static void vTimerCallback(TimerHandle_t pxTimer) +{ + long lTimerId; + configASSERT(pxTimer); + + lTimerId = (long) pvTimerGetTimerID(pxTimer); + + if (lTimerId != TIMER_ID) { + xil_printf("CPU0 - FreeRTOS Hello World Example FAILED"); + } + + /* If the RxtaskCntr is updated every time the Rx task is called. The + Rx task is called every time the Tx task sends a message. The Tx task + sends a message every 1 second. + The timer expires after 10 seconds. We expect the RxtaskCntr to at least + have a value of 9 (TIMER_CHECK_THRESHOLD) when the timer expires. */ + if (RxtaskCntr >= TIMER_CHECK_THRESHOLD) { + message_status = 1; + xil_printf("CPU0 - FreeRTOS Hello World Example PASSED\r\n"); + } else { + message_status = 2; + xil_printf("CPU0 - FreeRTOS Hello World Example FAILED\r\n"); } } From fba5b6264d9d7f90977dc637bfe5a7a45def3b28 Mon Sep 17 00:00:00 2001 From: Ryan Srichai Date: Fri, 2 Aug 2024 12:17:00 -0500 Subject: [PATCH 06/17] converted LF to CRLF in shared/sys files --- sdk/freertos_app_cpu0/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/freertos_app_cpu0/src/main.c b/sdk/freertos_app_cpu0/src/main.c index ff2984d1..61b22a1c 100644 --- a/sdk/freertos_app_cpu0/src/main.c +++ b/sdk/freertos_app_cpu0/src/main.c @@ -40,7 +40,7 @@ #include "xil_printf.h" #include "xparameters.h" /* Firmware includes */ -//#include "sys/icc.h" +#include "sys/icc.h" #include "sys/intr.h" /* Begin User Includes */ From 759f8c57ec9c1a97dd04ccc7d5de9b01ad73b592 Mon Sep 17 00:00:00 2001 From: Ryan Srichai Date: Fri, 2 Aug 2024 12:18:23 -0500 Subject: [PATCH 07/17] okay that didn't work --- sdk/shared/sys/intr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/shared/sys/intr.h b/sdk/shared/sys/intr.h index 7b29abe0..49107642 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 -XScuGic InterruptController; +static XScuGic InterruptController; int intr_init(); From 8fa23c16f8a5bcb3dcf5fdc2edc25fcf7383950c Mon Sep 17 00:00:00 2001 From: Ryan Srichai Date: Fri, 2 Aug 2024 12:36:35 -0500 Subject: [PATCH 08/17] linux permissions --- sdk/shared/sys/icc.c | 182 ++++++++++++++++----------------- sdk/shared/sys/icc.h | 178 ++++++++++++++++----------------- sdk/shared/sys/intr.c | 228 +++++++++++++++++++++--------------------- sdk/shared/sys/intr.h | 102 +++++++++---------- 4 files changed, 345 insertions(+), 345 deletions(-) diff --git a/sdk/shared/sys/icc.c b/sdk/shared/sys/icc.c index b6b662d8..2673a593 100644 --- a/sdk/shared/sys/icc.c +++ b/sdk/shared/sys/icc.c @@ -1,91 +1,91 @@ -#include "icc.h" - -/////////////////////////////////////////////////////// -// THIS IS A SHARED FILE, SO IT IS ALWAYS -// IN SYNC IN BOTH CPU0 AND CPU1 -// -// If you need to differentiate something between -// CPUs, use "#if XPAR_CPU_ID == ?" -/////////////////////////////////////////////////////// - -void icc_init(uint32_t cpu_num) -{ -#if XPAR_CPU_ID == 0 - // ONLY CPU 0 INITIALIZES THE MESSAGE BUFFERS - - /* Create two message buffers for inter-core communication that use the callback - * functions below as send and receive completed callback functions. */ - xCPU0to1MessageBuffer = xMessageBufferCreateStaticWithCallback(ICC_BUFFER_SIZE - 1, - ICC_CPU0to1_BufferSpaceAddr, - ICC_CPU0to1_BufferStructAddr, - vCPU0to1SendCallback, - vCPU0to1ReceiveCallback); - - xCPU1to0MessageBuffer = xMessageBufferCreateStaticWithCallback(ICC_BUFFER_SIZE - 1, - ICC_CPU1to0_BufferSpaceAddr, - ICC_CPU1to0_BufferStructAddr, - vCPU1to0SendCallback, - vCPU1to0ReceiveCallback); -#endif -} - -/* From FreeRTOS: - * Insert code into callback which is invoked when a message is written to the message buffer. - * This is useful when a message buffer is used to pass messages between - * cores on a multicore processor. In that scenario, this callback - * can be implemented to generate an interrupt in the other CPU core, - * and the interrupt's service routine can then use the - * xMessageBufferSendCompletedFromISR() API function to check, and if - * necessary unblock, a task that was waiting for message. */ - -/* !! IMPORTANT !! - * These callback functions must ALL exist in BOTH CPUs for the above Message Buffer creations - * to work. HOWEVER, the callbacks only have to DO SOMETHING in the relevant CPU - * For example, the behavior of the 0 to 1 Send Callback must be implemented in CPU 0, since - * CPU 0 needs to send an interrupt to CPU 1 when it sends to the buffer. But CPU 1 will never - * send to the 0 to 1 buffer, so in CPU 1 this callback doesn't need to DO ANYTHING except exist. - * - Patrick */ - -void vCPU0to1SendCallback(MessageBufferHandle_t xMessageBuffer, - BaseType_t xIsInsideISR, - BaseType_t *const pxHigherPriorityTaskWoken) -{ -#if XPAR_CPU_ID == 0 - xil_printf("DEBUG: CPU 0 to 1 Send Callback reached\r\n"); - // In CPU 0, this callback should send an interrupt to CPU 1's Rx task - XScuGic_SoftwareIntr(&InterruptController, INTC_0TO1_SEND_INTERRUPT_ID, CPU1_ID); -#endif -} - -void vCPU1to0ReceiveCallback(MessageBufferHandle_t xMessageBuffer, - BaseType_t xIsInsideISR, - BaseType_t *const pxHigherPriorityTaskWoken) -{ -#if XPAR_CPU_ID == 0 - xil_printf("DEBUG: CPU 1 to 0 Receive Callback reached\r\n"); - // In CPU 0, this callback should send an interrupt to CPU 1's Tx task - XScuGic_SoftwareIntr(&InterruptController, INTC_1TO0_RCVE_INTERRUPT_ID, CPU1_ID); -#endif -} - -void vCPU1to0SendCallback(MessageBufferHandle_t xMessageBuffer, - BaseType_t xIsInsideISR, - BaseType_t *const pxHigherPriorityTaskWoken) -{ -#if XPAR_CPU_ID == 1 - xil_printf("DEBUG: CPU 1 to 0 Send Callback reached\r\n"); - // In CPU 1, this callback should send an interrupt to CPU 0's Rx task - XScuGic_SoftwareIntr(&InterruptController, INTC_1TO0_SEND_INTERRUPT_ID, CPU0_ID); -#endif -} - -void vCPU0to1ReceiveCallback(MessageBufferHandle_t xMessageBuffer, - BaseType_t xIsInsideISR, - BaseType_t *const pxHigherPriorityTaskWoken) -{ -#if XPAR_CPU_ID == 1 - xil_printf("DEBUG: CPU 0 to 1 Receive Callback reached\r\n"); - // In CPU 1, this callback should send an interrupt to CPU 0's Tx task - XScuGic_SoftwareIntr(&InterruptController, INTC_0TO1_RCVE_INTERRUPT_ID, CPU0_ID); -#endif -} +#include "icc.h" + +/////////////////////////////////////////////////////// +// THIS IS A SHARED FILE, SO IT IS ALWAYS +// IN SYNC IN BOTH CPU0 AND CPU1 +// +// If you need to differentiate something between +// CPUs, use "#if XPAR_CPU_ID == ?" +/////////////////////////////////////////////////////// + +void icc_init(uint32_t cpu_num) +{ +#if XPAR_CPU_ID == 0 + // ONLY CPU 0 INITIALIZES THE MESSAGE BUFFERS + + /* Create two message buffers for inter-core communication that use the callback + * functions below as send and receive completed callback functions. */ + xCPU0to1MessageBuffer = xMessageBufferCreateStaticWithCallback(ICC_BUFFER_SIZE - 1, + ICC_CPU0to1_BufferSpaceAddr, + ICC_CPU0to1_BufferStructAddr, + vCPU0to1SendCallback, + vCPU0to1ReceiveCallback); + + xCPU1to0MessageBuffer = xMessageBufferCreateStaticWithCallback(ICC_BUFFER_SIZE - 1, + ICC_CPU1to0_BufferSpaceAddr, + ICC_CPU1to0_BufferStructAddr, + vCPU1to0SendCallback, + vCPU1to0ReceiveCallback); +#endif +} + +/* From FreeRTOS: + * Insert code into callback which is invoked when a message is written to the message buffer. + * This is useful when a message buffer is used to pass messages between + * cores on a multicore processor. In that scenario, this callback + * can be implemented to generate an interrupt in the other CPU core, + * and the interrupt's service routine can then use the + * xMessageBufferSendCompletedFromISR() API function to check, and if + * necessary unblock, a task that was waiting for message. */ + +/* !! IMPORTANT !! + * These callback functions must ALL exist in BOTH CPUs for the above Message Buffer creations + * to work. HOWEVER, the callbacks only have to DO SOMETHING in the relevant CPU + * For example, the behavior of the 0 to 1 Send Callback must be implemented in CPU 0, since + * CPU 0 needs to send an interrupt to CPU 1 when it sends to the buffer. But CPU 1 will never + * send to the 0 to 1 buffer, so in CPU 1 this callback doesn't need to DO ANYTHING except exist. + * - Patrick */ + +void vCPU0to1SendCallback(MessageBufferHandle_t xMessageBuffer, + BaseType_t xIsInsideISR, + BaseType_t *const pxHigherPriorityTaskWoken) +{ +#if XPAR_CPU_ID == 0 + xil_printf("DEBUG: CPU 0 to 1 Send Callback reached\r\n"); + // In CPU 0, this callback should send an interrupt to CPU 1's Rx task + XScuGic_SoftwareIntr(&InterruptController, INTC_0TO1_SEND_INTERRUPT_ID, CPU1_ID); +#endif +} + +void vCPU1to0ReceiveCallback(MessageBufferHandle_t xMessageBuffer, + BaseType_t xIsInsideISR, + BaseType_t *const pxHigherPriorityTaskWoken) +{ +#if XPAR_CPU_ID == 0 + xil_printf("DEBUG: CPU 1 to 0 Receive Callback reached\r\n"); + // In CPU 0, this callback should send an interrupt to CPU 1's Tx task + XScuGic_SoftwareIntr(&InterruptController, INTC_1TO0_RCVE_INTERRUPT_ID, CPU1_ID); +#endif +} + +void vCPU1to0SendCallback(MessageBufferHandle_t xMessageBuffer, + BaseType_t xIsInsideISR, + BaseType_t *const pxHigherPriorityTaskWoken) +{ +#if XPAR_CPU_ID == 1 + xil_printf("DEBUG: CPU 1 to 0 Send Callback reached\r\n"); + // In CPU 1, this callback should send an interrupt to CPU 0's Rx task + XScuGic_SoftwareIntr(&InterruptController, INTC_1TO0_SEND_INTERRUPT_ID, CPU0_ID); +#endif +} + +void vCPU0to1ReceiveCallback(MessageBufferHandle_t xMessageBuffer, + BaseType_t xIsInsideISR, + BaseType_t *const pxHigherPriorityTaskWoken) +{ +#if XPAR_CPU_ID == 1 + xil_printf("DEBUG: CPU 0 to 1 Receive Callback reached\r\n"); + // In CPU 1, this callback should send an interrupt to CPU 0's Tx task + XScuGic_SoftwareIntr(&InterruptController, INTC_0TO1_RCVE_INTERRUPT_ID, CPU0_ID); +#endif +} diff --git a/sdk/shared/sys/icc.h b/sdk/shared/sys/icc.h index 72273101..c8d82879 100644 --- a/sdk/shared/sys/icc.h +++ b/sdk/shared/sys/icc.h @@ -1,89 +1,89 @@ -#ifndef ICC_H -#define ICC_H - -#include "FreeRTOS.h" -#include "intr.h" -#include "message_buffer.h" -#include "xil_printf.h" -#include - -/////////////////////////////////////////////////////// -// THIS IS A SHARED FILE, SO IT IS ALWAYS -// IN SYNC IN BOTH CPU0 AND CPU1 -// -// If you need to differentiate something between -// CPUs, use "#if XPAR_CPU_ID == ?" -/////////////////////////////////////////////////////// - -// ======================== -// Inter-Core Communication -// ======================== -// -// This module implements communication between the two cores, CPU0 and CPU1. -// CPU0 acts as the master and initializes all shared memory spaces. -// -// In the OCM, we implement two FreeRTOS Message Buffers: one from CPU0 to CPU1, -// and one from CPU1 to CPU0. Each FIFO and associated data are used to build a -// simple producer-consumer system. -// -// This implementation is known to be thread (dual-core) safe. -// -// For more details and pseudo code, see these resources: -// https://www.freertos.org/RTOS-message-buffer-API.html -// https://www.freertos.org/2020/02/simple-multicore-core-to-core-communication-using-freertos-message-buffers.html - -// Per Zynq-7000 TRM Ch. 4: System Addresses (page 106), the initial mapping -// of OCM is split between low addresses and high addresses in 64 KB chunks. -// -// We will pick to use the highest 64 KB chunk as our base address: -#define OCM_BASE_ADDR (0xFFFF0000) -#define ICC_BUFFER_STRUCT_SIZE (sizeof(StaticMessageBuffer_t)) -#define ICC_BUFFER_SIZE (4 * 1024) -#define ICC_HANDLE_SIZE (sizeof(MessageBufferHandle_t)) - - -/* Define the pointers to the two structs (that store the metadata) and two message spaces (that hold the messages) in shared memory. - * The ICC_BUFFER_SIZE Should be one more than the value passed in the xBufferSizeBytes parameter. - * The two structs will be located back-to-back right at the base addr of the shared OCM, followed thereafter by the actual message buffers. */ -#define ICC_CPU0to1_BufferStructAddr ((uint8_t *) (OCM_BASE_ADDR + (0 * ICC_BUFFER_STRUCT_SIZE))) -#define ICC_CPU1to0_BufferStructAddr ((uint8_t *) (OCM_BASE_ADDR + (1 * ICC_BUFFER_STRUCT_SIZE))) - -#define ICC_CPU0to1_BufferSpaceAddr ((uint8_t *) (OCM_BASE_ADDR + (2 * ICC_BUFFER_STRUCT_SIZE) + (0 * ICC_BUFFER_SIZE))) -#define ICC_CPU1to0_BufferSpaceAddr ((uint8_t *) (OCM_BASE_ADDR + (2 * ICC_BUFFER_STRUCT_SIZE) + (1 * ICC_BUFFER_SIZE))) - - -/* These memory spaces are used to transfer the Message Buffer Handles from CPU0 (who does the initialization work, and gets the handles - * from the xMessageBufferCreateStaticWithCallback function) to CPU1 (who doesn't initialize anything and gets the handles from CPU0, via - * these drop-zones) */ -#define ICC_CPU0to1_HandleDropzoneAddr (OCM_BASE_ADDR + (2 * ICC_BUFFER_STRUCT_SIZE) + (2 * ICC_BUFFER_SIZE) + (0 * ICC_HANDLE_SIZE))) -#define ICC_CPU1to0_HandleDropzoneAddr (OCM_BASE_ADDR + (2 * ICC_BUFFER_STRUCT_SIZE) + (2 * ICC_BUFFER_SIZE) + (1 * ICC_HANDLE_SIZE))) - -#define ICC_getCPU0to1Handle (*((MessageBufferHandle_t *) ICC_CPU0to1_HandleDropzoneAddr)) -#define ICC_setCPU0to1Handle(handle) (*((MessageBufferHandle_t *) ICC_CPU0to1_HandleDropzoneAddr) = handle) -#define ICC_getCPU1to0Handle (*((MessageBufferHandle_t *) ICC_CPU1to0_HandleDropzoneAddr)) -#define ICC_setCPU1to0Handle(handle) (*((MessageBufferHandle_t *) ICC_CPU1to0_HandleDropzoneAddr) = handle) - - - -/* These are the handles for the Message Buffers that need to be used by other tasks - * In reality, the handle is just the pointer to the message buffer struct (its memory address) - * These should end up being the addresses computed above */ -MessageBufferHandle_t xCPU0to1MessageBuffer; -MessageBufferHandle_t xCPU1to0MessageBuffer; - - -void icc_init(); -void vCPU0to1SendCallback(MessageBufferHandle_t xMessageBuffer, - BaseType_t xIsInsideISR, - BaseType_t *const pxHigherPriorityTaskWoken); -void vCPU0to1ReceiveCallback(MessageBufferHandle_t xMessageBuffer, - BaseType_t xIsInsideISR, - BaseType_t *const pxHigherPriorityTaskWoken); -void vCPU1to0SendCallback(MessageBufferHandle_t xMessageBuffer, - BaseType_t xIsInsideISR, - BaseType_t *const pxHigherPriorityTaskWoken); -void vCPU1to0ReceiveCallback(MessageBufferHandle_t xMessageBuffer, - BaseType_t xIsInsideISR, - BaseType_t *const pxHigherPriorityTaskWoken); - -#endif /* ICC_H */ +#ifndef ICC_H +#define ICC_H + +#include "FreeRTOS.h" +#include "intr.h" +#include "message_buffer.h" +#include "xil_printf.h" +#include + +/////////////////////////////////////////////////////// +// THIS IS A SHARED FILE, SO IT IS ALWAYS +// IN SYNC IN BOTH CPU0 AND CPU1 +// +// If you need to differentiate something between +// CPUs, use "#if XPAR_CPU_ID == ?" +/////////////////////////////////////////////////////// + +// ======================== +// Inter-Core Communication +// ======================== +// +// This module implements communication between the two cores, CPU0 and CPU1. +// CPU0 acts as the master and initializes all shared memory spaces. +// +// In the OCM, we implement two FreeRTOS Message Buffers: one from CPU0 to CPU1, +// and one from CPU1 to CPU0. Each FIFO and associated data are used to build a +// simple producer-consumer system. +// +// This implementation is known to be thread (dual-core) safe. +// +// For more details and pseudo code, see these resources: +// https://www.freertos.org/RTOS-message-buffer-API.html +// https://www.freertos.org/2020/02/simple-multicore-core-to-core-communication-using-freertos-message-buffers.html + +// Per Zynq-7000 TRM Ch. 4: System Addresses (page 106), the initial mapping +// of OCM is split between low addresses and high addresses in 64 KB chunks. +// +// We will pick to use the highest 64 KB chunk as our base address: +#define OCM_BASE_ADDR (0xFFFF0000) +#define ICC_BUFFER_STRUCT_SIZE (sizeof(StaticMessageBuffer_t)) +#define ICC_BUFFER_SIZE (4 * 1024) +#define ICC_HANDLE_SIZE (sizeof(MessageBufferHandle_t)) + + +/* Define the pointers to the two structs (that store the metadata) and two message spaces (that hold the messages) in shared memory. + * The ICC_BUFFER_SIZE Should be one more than the value passed in the xBufferSizeBytes parameter. + * The two structs will be located back-to-back right at the base addr of the shared OCM, followed thereafter by the actual message buffers. */ +#define ICC_CPU0to1_BufferStructAddr ((uint8_t *) (OCM_BASE_ADDR + (0 * ICC_BUFFER_STRUCT_SIZE))) +#define ICC_CPU1to0_BufferStructAddr ((uint8_t *) (OCM_BASE_ADDR + (1 * ICC_BUFFER_STRUCT_SIZE))) + +#define ICC_CPU0to1_BufferSpaceAddr ((uint8_t *) (OCM_BASE_ADDR + (2 * ICC_BUFFER_STRUCT_SIZE) + (0 * ICC_BUFFER_SIZE))) +#define ICC_CPU1to0_BufferSpaceAddr ((uint8_t *) (OCM_BASE_ADDR + (2 * ICC_BUFFER_STRUCT_SIZE) + (1 * ICC_BUFFER_SIZE))) + + +/* These memory spaces are used to transfer the Message Buffer Handles from CPU0 (who does the initialization work, and gets the handles + * from the xMessageBufferCreateStaticWithCallback function) to CPU1 (who doesn't initialize anything and gets the handles from CPU0, via + * these drop-zones) */ +#define ICC_CPU0to1_HandleDropzoneAddr (OCM_BASE_ADDR + (2 * ICC_BUFFER_STRUCT_SIZE) + (2 * ICC_BUFFER_SIZE) + (0 * ICC_HANDLE_SIZE))) +#define ICC_CPU1to0_HandleDropzoneAddr (OCM_BASE_ADDR + (2 * ICC_BUFFER_STRUCT_SIZE) + (2 * ICC_BUFFER_SIZE) + (1 * ICC_HANDLE_SIZE))) + +#define ICC_getCPU0to1Handle (*((MessageBufferHandle_t *) ICC_CPU0to1_HandleDropzoneAddr)) +#define ICC_setCPU0to1Handle(handle) (*((MessageBufferHandle_t *) ICC_CPU0to1_HandleDropzoneAddr) = handle) +#define ICC_getCPU1to0Handle (*((MessageBufferHandle_t *) ICC_CPU1to0_HandleDropzoneAddr)) +#define ICC_setCPU1to0Handle(handle) (*((MessageBufferHandle_t *) ICC_CPU1to0_HandleDropzoneAddr) = handle) + + + +/* These are the handles for the Message Buffers that need to be used by other tasks + * In reality, the handle is just the pointer to the message buffer struct (its memory address) + * These should end up being the addresses computed above */ +MessageBufferHandle_t xCPU0to1MessageBuffer; +MessageBufferHandle_t xCPU1to0MessageBuffer; + + +void icc_init(); +void vCPU0to1SendCallback(MessageBufferHandle_t xMessageBuffer, + BaseType_t xIsInsideISR, + BaseType_t *const pxHigherPriorityTaskWoken); +void vCPU0to1ReceiveCallback(MessageBufferHandle_t xMessageBuffer, + BaseType_t xIsInsideISR, + BaseType_t *const pxHigherPriorityTaskWoken); +void vCPU1to0SendCallback(MessageBufferHandle_t xMessageBuffer, + BaseType_t xIsInsideISR, + BaseType_t *const pxHigherPriorityTaskWoken); +void vCPU1to0ReceiveCallback(MessageBufferHandle_t xMessageBuffer, + BaseType_t xIsInsideISR, + BaseType_t *const pxHigherPriorityTaskWoken); + +#endif /* ICC_H */ diff --git a/sdk/shared/sys/intr.c b/sdk/shared/sys/intr.c index 990b647d..253dcbbc 100644 --- a/sdk/shared/sys/intr.c +++ b/sdk/shared/sys/intr.c @@ -1,114 +1,114 @@ -#include "intr.h" - -/////////////////////////////////////////////////////// -// THIS IS A SHARED FILE, SO IT IS ALWAYS -// IN SYNC IN BOTH CPU0 AND CPU1 -// -// If you need to differentiate something between -// CPUs, use "#if XPAR_CPU_ID == ?" -/////////////////////////////////////////////////////// - -/* The functions in this file are responsible for setting up the - * Xilinx Generic Interrupt Controller (GIC). - * - * Interrupts are needed for Inter-Core Communication, specifically - * the ability to trigger an interrupt in the receiving CPU after a - * message is placed into an empty ICC Message Buffer, - * OR - * the ability to trigger an interrupt in the sending CPU after a - * message is removed from a full ICC Message Buffer - * - * See sys/icc.c for more info. - */ - -int intr_init() -{ - int Status = XST_FAILURE; - - XScuGic_Config *IntcConfig; - - IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID); - XScuGic_CfgInitialize(&InterruptController, IntcConfig, IntcConfig->CpuBaseAddress); - - /* - * Perform a self-test to ensure that the hardware was built - * correctly - */ - Status = XScuGic_SelfTest(&InterruptController); - if (Status != XST_SUCCESS) { - return XST_FAILURE; - } - - // Initialize the interrupt controller - Xil_ExceptionRegisterHandler( - XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler) XScuGic_InterruptHandler, &InterruptController); - Xil_ExceptionEnable(); - -#if XPAR_CPU_ID == 0 - // Connect the given interrupt with its handler - XScuGic_Connect(&InterruptController, INTC_1TO0_SEND_INTERRUPT_ID, (Xil_ExceptionHandler) CPU0WakeRxHandler, NULL); - XScuGic_Connect(&InterruptController, INTC_0TO1_RCVE_INTERRUPT_ID, (Xil_ExceptionHandler) CPU0WakeTxHandler, NULL); - -#elif XPAR_CPU_ID == 1 - // Connect the given interrupt with its handler - XScuGic_Connect(&InterruptController, INTC_0TO1_SEND_INTERRUPT_ID, (Xil_ExceptionHandler) CPU1WakeRxHandler, NULL); - XScuGic_Connect(&InterruptController, INTC_1TO0_RCVE_INTERRUPT_ID, (Xil_ExceptionHandler) CPU1WakeTxHandler, NULL); -#endif - - /* - // Enable the interrupt for the second CPU core - XScuGic_SetPriorityTriggerType(&InterruptController, INTC_INTERRUPT_ID, 0xA0, 3); // Set priority and trigger type - XScuGic_Enable(&InterruptController, INTC_INTERRUPT_ID); - - // Enable the interrupt for CPU1 - Xil_Out32(XPAR_PS7_SCUGIC_DIST_BASEADDR + XSCUGIC_CPU_PRIOR_OFFSET + (CPU1_ID * 4), 0xFF); - Xil_Out32(XPAR_PS7_SCUGIC_DIST_BASEADDR + XSCUGIC_CPU_TARGET_OFFSET + (CPU1_ID * 4), 0x1); - - // Enable interrupts globally - Xil_ExceptionEnableMask(XIL_EXCEPTION_NON_CRITICAL); - - print("Interrupt system setup complete.\r\n"); - */ - - return XST_SUCCESS; -} - -/* We only need to define the handlers in the appropriate core - */ -#if XPAR_CPU_ID == 0 -void CPU0WakeTxHandler() -{ - xil_printf("CPU 0 - WakeTxHandler reached\r\n"); - - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xMessageBufferReceiveCompletedFromISR(xCPU0to1MessageBuffer, &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -} - -void CPU0WakeRxHandler() -{ - xil_printf("CPU 0 - WakeRxHandler reached\r\n"); - - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xMessageBufferSendCompletedFromISR(xCPU1to0MessageBuffer, &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -} -#elif XPAR_CPU_ID == 1 -void CPU1WakeTxHandler() -{ - xil_printf("CPU 1 - WakeTxHandler reached\r\n"); - - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xMessageBufferReceiveCompletedFromISR(xCPU1to0MessageBuffer, &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -} - -void CPU1WakeRxHandler() -{ - xil_printf("CPU 1 - WakeRxHandler reached\r\n"); - - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xMessageBufferSendCompletedFromISR(xCPU0to1MessageBuffer, &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -} -#endif +#include "intr.h" + +/////////////////////////////////////////////////////// +// THIS IS A SHARED FILE, SO IT IS ALWAYS +// IN SYNC IN BOTH CPU0 AND CPU1 +// +// If you need to differentiate something between +// CPUs, use "#if XPAR_CPU_ID == ?" +/////////////////////////////////////////////////////// + +/* The functions in this file are responsible for setting up the + * Xilinx Generic Interrupt Controller (GIC). + * + * Interrupts are needed for Inter-Core Communication, specifically + * the ability to trigger an interrupt in the receiving CPU after a + * message is placed into an empty ICC Message Buffer, + * OR + * the ability to trigger an interrupt in the sending CPU after a + * message is removed from a full ICC Message Buffer + * + * See sys/icc.c for more info. + */ + +int intr_init() +{ + int Status = XST_FAILURE; + + XScuGic_Config *IntcConfig; + + IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID); + XScuGic_CfgInitialize(&InterruptController, IntcConfig, IntcConfig->CpuBaseAddress); + + /* + * Perform a self-test to ensure that the hardware was built + * correctly + */ + Status = XScuGic_SelfTest(&InterruptController); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + // Initialize the interrupt controller + Xil_ExceptionRegisterHandler( + XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler) XScuGic_InterruptHandler, &InterruptController); + Xil_ExceptionEnable(); + +#if XPAR_CPU_ID == 0 + // Connect the given interrupt with its handler + XScuGic_Connect(&InterruptController, INTC_1TO0_SEND_INTERRUPT_ID, (Xil_ExceptionHandler) CPU0WakeRxHandler, NULL); + XScuGic_Connect(&InterruptController, INTC_0TO1_RCVE_INTERRUPT_ID, (Xil_ExceptionHandler) CPU0WakeTxHandler, NULL); + +#elif XPAR_CPU_ID == 1 + // Connect the given interrupt with its handler + XScuGic_Connect(&InterruptController, INTC_0TO1_SEND_INTERRUPT_ID, (Xil_ExceptionHandler) CPU1WakeRxHandler, NULL); + XScuGic_Connect(&InterruptController, INTC_1TO0_RCVE_INTERRUPT_ID, (Xil_ExceptionHandler) CPU1WakeTxHandler, NULL); +#endif + + /* + // Enable the interrupt for the second CPU core + XScuGic_SetPriorityTriggerType(&InterruptController, INTC_INTERRUPT_ID, 0xA0, 3); // Set priority and trigger type + XScuGic_Enable(&InterruptController, INTC_INTERRUPT_ID); + + // Enable the interrupt for CPU1 + Xil_Out32(XPAR_PS7_SCUGIC_DIST_BASEADDR + XSCUGIC_CPU_PRIOR_OFFSET + (CPU1_ID * 4), 0xFF); + Xil_Out32(XPAR_PS7_SCUGIC_DIST_BASEADDR + XSCUGIC_CPU_TARGET_OFFSET + (CPU1_ID * 4), 0x1); + + // Enable interrupts globally + Xil_ExceptionEnableMask(XIL_EXCEPTION_NON_CRITICAL); + + print("Interrupt system setup complete.\r\n"); + */ + + return XST_SUCCESS; +} + +/* We only need to define the handlers in the appropriate core + */ +#if XPAR_CPU_ID == 0 +void CPU0WakeTxHandler() +{ + xil_printf("CPU 0 - WakeTxHandler reached\r\n"); + + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xMessageBufferReceiveCompletedFromISR(xCPU0to1MessageBuffer, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +} + +void CPU0WakeRxHandler() +{ + xil_printf("CPU 0 - WakeRxHandler reached\r\n"); + + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xMessageBufferSendCompletedFromISR(xCPU1to0MessageBuffer, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +} +#elif XPAR_CPU_ID == 1 +void CPU1WakeTxHandler() +{ + xil_printf("CPU 1 - WakeTxHandler reached\r\n"); + + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xMessageBufferReceiveCompletedFromISR(xCPU1to0MessageBuffer, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +} + +void CPU1WakeRxHandler() +{ + xil_printf("CPU 1 - WakeRxHandler reached\r\n"); + + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xMessageBufferSendCompletedFromISR(xCPU0to1MessageBuffer, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +} +#endif diff --git a/sdk/shared/sys/intr.h b/sdk/shared/sys/intr.h index 49107642..137771a4 100644 --- a/sdk/shared/sys/intr.h +++ b/sdk/shared/sys/intr.h @@ -1,51 +1,51 @@ -#ifndef INTR_H -#define INTR_H - -#include "FreeRTOS.h" -#include "icc.h" -#include "xil_exception.h" -#include "xil_printf.h" -#include "xparameters.h" -#include "xscugic.h" - -#include -#include -#include - -// test - -/////////////////////////////////////////////////////// -// THIS IS A SHARED FILE, SO IT IS ALWAYS -// IN SYNC IN BOTH CPU0 AND CPU1 -// -// If you need to differentiate something between -// CPUs, use "#if XPAR_CPU_ID == ?" -/////////////////////////////////////////////////////// - -#define CPU0_ID (XSCUGIC_SPI_CPU0_MASK << 0) -#define CPU1_ID (XSCUGIC_SPI_CPU0_MASK << 1) - -#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID - -#define INTC_0TO1_SEND_INTERRUPT_ID 0U -#define INTC_1TO0_RCVE_INTERRUPT_ID 1U -#define INTC_1TO0_SEND_INTERRUPT_ID 2U -#define INTC_0TO1_RCVE_INTERRUPT_ID 3U - -// Interrupt Controller Instance -// Defined here to be accessable in sys/icc.c -static XScuGic InterruptController; - -int intr_init(); - -/* We only need to define the handlers in the appropriate core - */ -#if XPAR_CPU_ID == 0 -void CPU0WakeTxHandler(); -void CPU0WakeRxHandler(); -#elif XPAR_CPU_ID == 1 -void CPU1WakeTxHandler(); -void CPU1WakeRxHandler(); -#endif - -#endif /* INTR_H */ +#ifndef INTR_H +#define INTR_H + +#include "FreeRTOS.h" +#include "icc.h" +#include "xil_exception.h" +#include "xil_printf.h" +#include "xparameters.h" +#include "xscugic.h" + +#include +#include +#include + +// test + +/////////////////////////////////////////////////////// +// THIS IS A SHARED FILE, SO IT IS ALWAYS +// IN SYNC IN BOTH CPU0 AND CPU1 +// +// If you need to differentiate something between +// CPUs, use "#if XPAR_CPU_ID == ?" +/////////////////////////////////////////////////////// + +#define CPU0_ID (XSCUGIC_SPI_CPU0_MASK << 0) +#define CPU1_ID (XSCUGIC_SPI_CPU0_MASK << 1) + +#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID + +#define INTC_0TO1_SEND_INTERRUPT_ID 0U +#define INTC_1TO0_RCVE_INTERRUPT_ID 1U +#define INTC_1TO0_SEND_INTERRUPT_ID 2U +#define INTC_0TO1_RCVE_INTERRUPT_ID 3U + +// Interrupt Controller Instance +// Defined here to be accessable in sys/icc.c +static XScuGic InterruptController; + +int intr_init(); + +/* We only need to define the handlers in the appropriate core + */ +#if XPAR_CPU_ID == 0 +void CPU0WakeTxHandler(); +void CPU0WakeRxHandler(); +#elif XPAR_CPU_ID == 1 +void CPU1WakeTxHandler(); +void CPU1WakeRxHandler(); +#endif + +#endif /* INTR_H */ From 3a1362b70e8284d8c9999bdf0d9fd204bdd6d8aa Mon Sep 17 00:00:00 2001 From: Ryan Srichai Date: Fri, 2 Aug 2024 12:42:50 -0500 Subject: [PATCH 09/17] line endings on cpu0 --- sdk/freertos_app_cpu0/src/FreeRTOSConfig.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sdk/freertos_app_cpu0/src/FreeRTOSConfig.h b/sdk/freertos_app_cpu0/src/FreeRTOSConfig.h index 4f3c1bd5..94d03f1f 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) 10000) +#define configTICK_RATE_HZ ((TickType_t) 1000) #define configPERIPHERAL_CLOCK_HZ (33333000UL) #define configUSE_PREEMPTION 1 #define configUSE_IDLE_HOOK 0 // TODO: For low-power, set 1 and implement vApplicationIdleHook() @@ -244,8 +244,4 @@ 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 */ From d44789dcf6a4114e2f6875c133b7d8855a282976 Mon Sep 17 00:00:00 2001 From: Ryan Srichai Date: Fri, 2 Aug 2024 12:46:00 -0500 Subject: [PATCH 10/17] line endings on cpu1 and shared --- sdk/freertos_app_cpu0/src/FreeRTOSConfig.h | 494 ++++++++++----------- sdk/freertos_app_cpu0/src/Xilinx.spec | 4 +- 2 files changed, 249 insertions(+), 249 deletions(-) diff --git a/sdk/freertos_app_cpu0/src/FreeRTOSConfig.h b/sdk/freertos_app_cpu0/src/FreeRTOSConfig.h index 94d03f1f..b92d6969 100644 --- a/sdk/freertos_app_cpu0/src/FreeRTOSConfig.h +++ b/sdk/freertos_app_cpu0/src/FreeRTOSConfig.h @@ -1,247 +1,247 @@ -/* README!!! - * - * This configuration is copied from the FreeRTOS v10.1.1 - * based example project for the Zynq 7000 platform (for - * compatibility). However, you can add to it. - * - * Another example configuration file is available at - * "sdk/FreeRTOS-Kernel/examples/sample_configuration/FreeRTOSConfig.h" - * Because that example is in the submodule, it may update - * from time-to-time when the submodule is updated. - */ - -/* - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * 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: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * 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. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - -#ifndef FREERTOS_CONFIG_H -#define FREERTOS_CONFIG_H - -#include "xparameters.h" - -/*----------------------------------------------------------- - * Application specific definitions. - * - * These definitions should be adjusted for your particular hardware and - * application requirements. - * - * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE - * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. - * - * See http://www.freertos.org/a00110.html - *----------------------------------------------------------*/ - -/* - * The FreeRTOS Cortex-A port implements a full interrupt nesting model. - * - * Interrupts that are assigned a priority at or below - * configMAX_API_CALL_INTERRUPT_PRIORITY (which counter-intuitively in the ARM - * generic interrupt controller [GIC] means a priority that has a numerical - * value above configMAX_API_CALL_INTERRUPT_PRIORITY) can call FreeRTOS safe API - * functions and will nest. - * - * Interrupts that are assigned a priority above - * configMAX_API_CALL_INTERRUPT_PRIORITY (which in the GIC means a numerical - * value below configMAX_API_CALL_INTERRUPT_PRIORITY) cannot call any FreeRTOS - * API functions, will nest, and will not be masked by FreeRTOS critical - * sections (although it is necessary for interrupts to be globally disabled - * extremely briefly as the interrupt mask is updated in the GIC). - * - * FreeRTOS functions that can be called from an interrupt are those that end in - * "FromISR". FreeRTOS maintains a separate interrupt safe API to enable - * interrupt entry to be shorter, faster, simpler and smaller. - * - * The Zynq implements 256 unique interrupt priorities. For the purpose of - * setting configMAX_API_CALL_INTERRUPT_PRIORITY 255 represents the lowest - * priority. - */ -#define configMAX_API_CALL_INTERRUPT_PRIORITY 18 - -#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 configPERIPHERAL_CLOCK_HZ (33333000UL) -#define configUSE_PREEMPTION 1 -#define configUSE_IDLE_HOOK 0 // TODO: For low-power, set 1 and implement vApplicationIdleHook() -#define configUSE_TICK_HOOK 0 // TODO: Set as 1 if we want to run function every tick -#define configMAX_PRIORITIES (7) -#define configTOTAL_HEAP_SIZE (125 * 1024) -#define configMAX_TASK_NAME_LEN (10) -#define configUSE_TRACE_FACILITY 1 -#define configUSE_16_BIT_TICKS 0 -#define configIDLE_SHOULD_YIELD 1 -#define configUSE_MUTEXES 1 -#define configQUEUE_REGISTRY_SIZE 8 -#define configCHECK_FOR_STACK_OVERFLOW 0 -#define configUSE_RECURSIVE_MUTEXES 1 -#define configUSE_MALLOC_FAILED_HOOK 0 -#define configUSE_APPLICATION_TASK_TAG 0 -#define configUSE_COUNTING_SEMAPHORES 1 -#define configUSE_QUEUE_SETS 1 -#define configSUPPORT_DYNAMIC_ALLOCATION 1 -#define configSUPPORT_STATIC_ALLOCATION 1 - -/* AMDC ADDITION: Need to specify this callback config so we can create message buffers with callbacks - * This is done for Inter-Core Communication (src/sys/icc.c) */ -#define configUSE_SB_COMPLETED_CALLBACK 1 - -/* Include the query-heap CLI command to query the free heap space. */ -#define configINCLUDE_QUERY_HEAP_COMMAND 1 - -/* Co-routine definitions. */ -#define configUSE_CO_ROUTINES 0 -#define configMAX_CO_ROUTINE_PRIORITIES (2) - -/* Software timer definitions. */ -#define configUSE_TIMERS 1 -#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) -#define configTIMER_QUEUE_LENGTH 5 -#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2) - -/* If configUSE_TASK_FPU_SUPPORT is set to 1 (or undefined) then each task will -be created without an FPU context, and a task must call vTaskUsesFPU() before -making use of any FPU registers. If configUSE_TASK_FPU_SUPPORT is set to 2 then -tasks are created with an FPU context by default, and calling vTaskUsesFPU() has -no effect. */ -#define configUSE_TASK_FPU_SUPPORT 2 -#define configMINIMAL_STACK_SIZE ((unsigned short) 250) // Large since all tasks have FPU context - -/* Set the following definitions to 1 to include the API function, or zero -to exclude the API function. */ -#define INCLUDE_vTaskPrioritySet 1 -#define INCLUDE_uxTaskPriorityGet 1 -#define INCLUDE_vTaskDelete 1 -#define INCLUDE_vTaskCleanUpResources 1 -#define INCLUDE_vTaskSuspend 1 -#define INCLUDE_vTaskDelayUntil 1 -#define INCLUDE_vTaskDelay 1 -#define INCLUDE_xTimerPendFunctionCall 1 -#define INCLUDE_eTaskGetState 1 -#define INCLUDE_xTaskAbortDelay 1 -#define INCLUDE_xTaskGetTaskHandle 1 -#define INCLUDE_xTaskGetHandle 1 -#define INCLUDE_xSemaphoreGetMutexHolder 1 - -/* This demo makes use of one or more example stats formatting functions. These -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 - -/* The private watchdog is used to generate run time stats. */ -/* -#include "xscuwdt.h" -extern XScuWdt xWatchDogInstance; -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 ) -*/ - -/* 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 -and one on TCP/IP). This is done to prevent an output buffer being defined by -each implementation - which would waste RAM. In this case, there is only one -command interpreter running. */ -#define configCOMMAND_INT_MAX_OUTPUT_SIZE 2096 - -/* Normal assert() semantics without relying on the provision of an assert.h -header file. */ -void vAssertCalled(const char *pcFile, unsigned long ulLine); - -// Original Implementation -//#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ ); - -#define configASSERT(x) \ - if ((x) == 0) \ - while (1) \ - ; - -/* If configTASK_RETURN_ADDRESS is not defined then a task that attempts to -return from its implementing function will end up in a "task exit error" -function - which contains a call to configASSERT(). However this can give GCC -some problems when it tries to unwind the stack, as the exit error function has -nothing to return to. To avoid this define configTASK_RETURN_ADDRESS to 0. */ -#define configTASK_RETURN_ADDRESS NULL - -/****** Hardware specific settings. *******************************************/ - -/* - * The application must provide a function that configures a peripheral to - * create the FreeRTOS tick interrupt, then define configSETUP_TICK_INTERRUPT() - * in FreeRTOSConfig.h to call the function. This file contains a function - * that is suitable for use on the Zynq MPU. FreeRTOS_Tick_Handler() must - * be installed as the peripheral's interrupt handler. - */ -void vConfigureTickInterrupt(void); -#define configSETUP_TICK_INTERRUPT() vConfigureTickInterrupt() - -void vClearTickInterrupt(void); -#define configCLEAR_TICK_INTERRUPT() vClearTickInterrupt() - -/* The following constant describe the hardware, and are correct for the -Zynq MPU. */ -#define configINTERRUPT_CONTROLLER_BASE_ADDRESS (XPAR_PS7_SCUGIC_0_DIST_BASEADDR) -#define configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET (-0xf00) -#define configUNIQUE_INTERRUPT_PRIORITIES 32 - -/****** Network configuration settings - only used when the lwIP example is -built. See the page that documents this demo on the http://www.FreeRTOS.org -website for more information. ***********************************************/ - -/* The priority for the task that unblocked by the MAC interrupt to process -received packets. */ -#define configMAC_INPUT_TASK_PRIORITY (configMAX_PRIORITIES - 1) - -/* The priority of the task that runs the lwIP stack. */ -#define configLWIP_TASK_PRIORITY (configMAX_PRIORITIES - 2) - -/* The priority of the task that uses lwIP sockets to provide a simple command -line interface. */ -#define configCLI_TASK_PRIORITY (tskIDLE_PRIORITY) - -/* MAC address configuration. */ -#define configMAC_ADDR0 0x00 -#define configMAC_ADDR1 0x13 -#define configMAC_ADDR2 0x14 -#define configMAC_ADDR3 0x15 -#define configMAC_ADDR4 0x15 -#define configMAC_ADDR5 0x16 - -/* IP address configuration. */ -#define configIP_ADDR0 172 -#define configIP_ADDR1 25 -#define configIP_ADDR2 218 -#define configIP_ADDR3 200 - -/* Netmask configuration. */ -#define configNET_MASK0 255 -#define configNET_MASK1 255 -#define configNET_MASK2 255 -#define configNET_MASK3 0 - -#endif /* FREERTOS_CONFIG_H */ +/* README!!! + * + * This configuration is copied from the FreeRTOS v10.1.1 + * based example project for the Zynq 7000 platform (for + * compatibility). However, you can add to it. + * + * Another example configuration file is available at + * "sdk/FreeRTOS-Kernel/examples/sample_configuration/FreeRTOSConfig.h" + * Because that example is in the submodule, it may update + * from time-to-time when the submodule is updated. + */ + +/* + * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#include "xparameters.h" + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html + *----------------------------------------------------------*/ + +/* + * The FreeRTOS Cortex-A port implements a full interrupt nesting model. + * + * Interrupts that are assigned a priority at or below + * configMAX_API_CALL_INTERRUPT_PRIORITY (which counter-intuitively in the ARM + * generic interrupt controller [GIC] means a priority that has a numerical + * value above configMAX_API_CALL_INTERRUPT_PRIORITY) can call FreeRTOS safe API + * functions and will nest. + * + * Interrupts that are assigned a priority above + * configMAX_API_CALL_INTERRUPT_PRIORITY (which in the GIC means a numerical + * value below configMAX_API_CALL_INTERRUPT_PRIORITY) cannot call any FreeRTOS + * API functions, will nest, and will not be masked by FreeRTOS critical + * sections (although it is necessary for interrupts to be globally disabled + * extremely briefly as the interrupt mask is updated in the GIC). + * + * FreeRTOS functions that can be called from an interrupt are those that end in + * "FromISR". FreeRTOS maintains a separate interrupt safe API to enable + * interrupt entry to be shorter, faster, simpler and smaller. + * + * The Zynq implements 256 unique interrupt priorities. For the purpose of + * setting configMAX_API_CALL_INTERRUPT_PRIORITY 255 represents the lowest + * priority. + */ +#define configMAX_API_CALL_INTERRUPT_PRIORITY 18 + +#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 configPERIPHERAL_CLOCK_HZ (33333000UL) +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 0 // TODO: For low-power, set 1 and implement vApplicationIdleHook() +#define configUSE_TICK_HOOK 0 // TODO: Set as 1 if we want to run function every tick +#define configMAX_PRIORITIES (7) +#define configTOTAL_HEAP_SIZE (125 * 1024) +#define configMAX_TASK_NAME_LEN (10) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 8 +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_MALLOC_FAILED_HOOK 0 +#define configUSE_APPLICATION_TASK_TAG 0 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_QUEUE_SETS 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 +#define configSUPPORT_STATIC_ALLOCATION 1 + +/* AMDC ADDITION: Need to specify this callback config so we can create message buffers with callbacks + * This is done for Inter-Core Communication (src/sys/icc.c) */ +#define configUSE_SB_COMPLETED_CALLBACK 1 + +/* Include the query-heap CLI command to query the free heap space. */ +#define configINCLUDE_QUERY_HEAP_COMMAND 1 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES (2) + +/* Software timer definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) +#define configTIMER_QUEUE_LENGTH 5 +#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2) + +/* If configUSE_TASK_FPU_SUPPORT is set to 1 (or undefined) then each task will +be created without an FPU context, and a task must call vTaskUsesFPU() before +making use of any FPU registers. If configUSE_TASK_FPU_SUPPORT is set to 2 then +tasks are created with an FPU context by default, and calling vTaskUsesFPU() has +no effect. */ +#define configUSE_TASK_FPU_SUPPORT 2 +#define configMINIMAL_STACK_SIZE ((unsigned short) 250) // Large since all tasks have FPU context + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 1 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xTaskAbortDelay 1 +#define INCLUDE_xTaskGetTaskHandle 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 + +/* This demo makes use of one or more example stats formatting functions. These +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 + +/* The private watchdog is used to generate run time stats. */ +/* +#include "xscuwdt.h" +extern XScuWdt xWatchDogInstance; +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 ) +*/ + +/* 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 +and one on TCP/IP). This is done to prevent an output buffer being defined by +each implementation - which would waste RAM. In this case, there is only one +command interpreter running. */ +#define configCOMMAND_INT_MAX_OUTPUT_SIZE 2096 + +/* Normal assert() semantics without relying on the provision of an assert.h +header file. */ +void vAssertCalled(const char *pcFile, unsigned long ulLine); + +// Original Implementation +//#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ ); + +#define configASSERT(x) \ + if ((x) == 0) \ + while (1) \ + ; + +/* If configTASK_RETURN_ADDRESS is not defined then a task that attempts to +return from its implementing function will end up in a "task exit error" +function - which contains a call to configASSERT(). However this can give GCC +some problems when it tries to unwind the stack, as the exit error function has +nothing to return to. To avoid this define configTASK_RETURN_ADDRESS to 0. */ +#define configTASK_RETURN_ADDRESS NULL + +/****** Hardware specific settings. *******************************************/ + +/* + * The application must provide a function that configures a peripheral to + * create the FreeRTOS tick interrupt, then define configSETUP_TICK_INTERRUPT() + * in FreeRTOSConfig.h to call the function. This file contains a function + * that is suitable for use on the Zynq MPU. FreeRTOS_Tick_Handler() must + * be installed as the peripheral's interrupt handler. + */ +void vConfigureTickInterrupt(void); +#define configSETUP_TICK_INTERRUPT() vConfigureTickInterrupt() + +void vClearTickInterrupt(void); +#define configCLEAR_TICK_INTERRUPT() vClearTickInterrupt() + +/* The following constant describe the hardware, and are correct for the +Zynq MPU. */ +#define configINTERRUPT_CONTROLLER_BASE_ADDRESS (XPAR_PS7_SCUGIC_0_DIST_BASEADDR) +#define configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET (-0xf00) +#define configUNIQUE_INTERRUPT_PRIORITIES 32 + +/****** Network configuration settings - only used when the lwIP example is +built. See the page that documents this demo on the http://www.FreeRTOS.org +website for more information. ***********************************************/ + +/* The priority for the task that unblocked by the MAC interrupt to process +received packets. */ +#define configMAC_INPUT_TASK_PRIORITY (configMAX_PRIORITIES - 1) + +/* The priority of the task that runs the lwIP stack. */ +#define configLWIP_TASK_PRIORITY (configMAX_PRIORITIES - 2) + +/* The priority of the task that uses lwIP sockets to provide a simple command +line interface. */ +#define configCLI_TASK_PRIORITY (tskIDLE_PRIORITY) + +/* MAC address configuration. */ +#define configMAC_ADDR0 0x00 +#define configMAC_ADDR1 0x13 +#define configMAC_ADDR2 0x14 +#define configMAC_ADDR3 0x15 +#define configMAC_ADDR4 0x15 +#define configMAC_ADDR5 0x16 + +/* IP address configuration. */ +#define configIP_ADDR0 172 +#define configIP_ADDR1 25 +#define configIP_ADDR2 218 +#define configIP_ADDR3 200 + +/* Netmask configuration. */ +#define configNET_MASK0 255 +#define configNET_MASK1 255 +#define configNET_MASK2 255 +#define configNET_MASK3 0 + +#endif /* FREERTOS_CONFIG_H */ diff --git a/sdk/freertos_app_cpu0/src/Xilinx.spec b/sdk/freertos_app_cpu0/src/Xilinx.spec index 8eea3774..9c27dcad 100644 --- a/sdk/freertos_app_cpu0/src/Xilinx.spec +++ b/sdk/freertos_app_cpu0/src/Xilinx.spec @@ -1,2 +1,2 @@ -*startfile: -crti%O%s crtbegin%O%s +*startfile: +crti%O%s crtbegin%O%s From 5829e3e356844012bc8d6c3b01a62cf9a0f6b8c8 Mon Sep 17 00:00:00 2001 From: Ryan Srichai Date: Fri, 2 Aug 2024 12:47:11 -0500 Subject: [PATCH 11/17] permissions on cpu1 --- sdk/freertos_app_cpu1/src/FreeRTOSConfig.h | 494 ++++++++++----------- sdk/freertos_app_cpu1/src/Xilinx.spec | 4 +- 2 files changed, 249 insertions(+), 249 deletions(-) diff --git a/sdk/freertos_app_cpu1/src/FreeRTOSConfig.h b/sdk/freertos_app_cpu1/src/FreeRTOSConfig.h index 94d03f1f..b92d6969 100644 --- a/sdk/freertos_app_cpu1/src/FreeRTOSConfig.h +++ b/sdk/freertos_app_cpu1/src/FreeRTOSConfig.h @@ -1,247 +1,247 @@ -/* README!!! - * - * This configuration is copied from the FreeRTOS v10.1.1 - * based example project for the Zynq 7000 platform (for - * compatibility). However, you can add to it. - * - * Another example configuration file is available at - * "sdk/FreeRTOS-Kernel/examples/sample_configuration/FreeRTOSConfig.h" - * Because that example is in the submodule, it may update - * from time-to-time when the submodule is updated. - */ - -/* - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * 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: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * 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. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - -#ifndef FREERTOS_CONFIG_H -#define FREERTOS_CONFIG_H - -#include "xparameters.h" - -/*----------------------------------------------------------- - * Application specific definitions. - * - * These definitions should be adjusted for your particular hardware and - * application requirements. - * - * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE - * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. - * - * See http://www.freertos.org/a00110.html - *----------------------------------------------------------*/ - -/* - * The FreeRTOS Cortex-A port implements a full interrupt nesting model. - * - * Interrupts that are assigned a priority at or below - * configMAX_API_CALL_INTERRUPT_PRIORITY (which counter-intuitively in the ARM - * generic interrupt controller [GIC] means a priority that has a numerical - * value above configMAX_API_CALL_INTERRUPT_PRIORITY) can call FreeRTOS safe API - * functions and will nest. - * - * Interrupts that are assigned a priority above - * configMAX_API_CALL_INTERRUPT_PRIORITY (which in the GIC means a numerical - * value below configMAX_API_CALL_INTERRUPT_PRIORITY) cannot call any FreeRTOS - * API functions, will nest, and will not be masked by FreeRTOS critical - * sections (although it is necessary for interrupts to be globally disabled - * extremely briefly as the interrupt mask is updated in the GIC). - * - * FreeRTOS functions that can be called from an interrupt are those that end in - * "FromISR". FreeRTOS maintains a separate interrupt safe API to enable - * interrupt entry to be shorter, faster, simpler and smaller. - * - * The Zynq implements 256 unique interrupt priorities. For the purpose of - * setting configMAX_API_CALL_INTERRUPT_PRIORITY 255 represents the lowest - * priority. - */ -#define configMAX_API_CALL_INTERRUPT_PRIORITY 18 - -#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 configPERIPHERAL_CLOCK_HZ (33333000UL) -#define configUSE_PREEMPTION 1 -#define configUSE_IDLE_HOOK 0 // TODO: For low-power, set 1 and implement vApplicationIdleHook() -#define configUSE_TICK_HOOK 0 // TODO: Set as 1 if we want to run function every tick -#define configMAX_PRIORITIES (7) -#define configTOTAL_HEAP_SIZE (125 * 1024) -#define configMAX_TASK_NAME_LEN (10) -#define configUSE_TRACE_FACILITY 1 -#define configUSE_16_BIT_TICKS 0 -#define configIDLE_SHOULD_YIELD 1 -#define configUSE_MUTEXES 1 -#define configQUEUE_REGISTRY_SIZE 8 -#define configCHECK_FOR_STACK_OVERFLOW 0 -#define configUSE_RECURSIVE_MUTEXES 1 -#define configUSE_MALLOC_FAILED_HOOK 0 -#define configUSE_APPLICATION_TASK_TAG 0 -#define configUSE_COUNTING_SEMAPHORES 1 -#define configUSE_QUEUE_SETS 1 -#define configSUPPORT_DYNAMIC_ALLOCATION 1 -#define configSUPPORT_STATIC_ALLOCATION 1 - -/* AMDC ADDITION: Need to specify this callback config so we can create message buffers with callbacks - * This is done for Inter-Core Communication (src/sys/icc.c) */ -#define configUSE_SB_COMPLETED_CALLBACK 1 - -/* Include the query-heap CLI command to query the free heap space. */ -#define configINCLUDE_QUERY_HEAP_COMMAND 1 - -/* Co-routine definitions. */ -#define configUSE_CO_ROUTINES 0 -#define configMAX_CO_ROUTINE_PRIORITIES (2) - -/* Software timer definitions. */ -#define configUSE_TIMERS 1 -#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) -#define configTIMER_QUEUE_LENGTH 5 -#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2) - -/* If configUSE_TASK_FPU_SUPPORT is set to 1 (or undefined) then each task will -be created without an FPU context, and a task must call vTaskUsesFPU() before -making use of any FPU registers. If configUSE_TASK_FPU_SUPPORT is set to 2 then -tasks are created with an FPU context by default, and calling vTaskUsesFPU() has -no effect. */ -#define configUSE_TASK_FPU_SUPPORT 2 -#define configMINIMAL_STACK_SIZE ((unsigned short) 250) // Large since all tasks have FPU context - -/* Set the following definitions to 1 to include the API function, or zero -to exclude the API function. */ -#define INCLUDE_vTaskPrioritySet 1 -#define INCLUDE_uxTaskPriorityGet 1 -#define INCLUDE_vTaskDelete 1 -#define INCLUDE_vTaskCleanUpResources 1 -#define INCLUDE_vTaskSuspend 1 -#define INCLUDE_vTaskDelayUntil 1 -#define INCLUDE_vTaskDelay 1 -#define INCLUDE_xTimerPendFunctionCall 1 -#define INCLUDE_eTaskGetState 1 -#define INCLUDE_xTaskAbortDelay 1 -#define INCLUDE_xTaskGetTaskHandle 1 -#define INCLUDE_xTaskGetHandle 1 -#define INCLUDE_xSemaphoreGetMutexHolder 1 - -/* This demo makes use of one or more example stats formatting functions. These -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 - -/* The private watchdog is used to generate run time stats. */ -/* -#include "xscuwdt.h" -extern XScuWdt xWatchDogInstance; -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 ) -*/ - -/* 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 -and one on TCP/IP). This is done to prevent an output buffer being defined by -each implementation - which would waste RAM. In this case, there is only one -command interpreter running. */ -#define configCOMMAND_INT_MAX_OUTPUT_SIZE 2096 - -/* Normal assert() semantics without relying on the provision of an assert.h -header file. */ -void vAssertCalled(const char *pcFile, unsigned long ulLine); - -// Original Implementation -//#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ ); - -#define configASSERT(x) \ - if ((x) == 0) \ - while (1) \ - ; - -/* If configTASK_RETURN_ADDRESS is not defined then a task that attempts to -return from its implementing function will end up in a "task exit error" -function - which contains a call to configASSERT(). However this can give GCC -some problems when it tries to unwind the stack, as the exit error function has -nothing to return to. To avoid this define configTASK_RETURN_ADDRESS to 0. */ -#define configTASK_RETURN_ADDRESS NULL - -/****** Hardware specific settings. *******************************************/ - -/* - * The application must provide a function that configures a peripheral to - * create the FreeRTOS tick interrupt, then define configSETUP_TICK_INTERRUPT() - * in FreeRTOSConfig.h to call the function. This file contains a function - * that is suitable for use on the Zynq MPU. FreeRTOS_Tick_Handler() must - * be installed as the peripheral's interrupt handler. - */ -void vConfigureTickInterrupt(void); -#define configSETUP_TICK_INTERRUPT() vConfigureTickInterrupt() - -void vClearTickInterrupt(void); -#define configCLEAR_TICK_INTERRUPT() vClearTickInterrupt() - -/* The following constant describe the hardware, and are correct for the -Zynq MPU. */ -#define configINTERRUPT_CONTROLLER_BASE_ADDRESS (XPAR_PS7_SCUGIC_0_DIST_BASEADDR) -#define configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET (-0xf00) -#define configUNIQUE_INTERRUPT_PRIORITIES 32 - -/****** Network configuration settings - only used when the lwIP example is -built. See the page that documents this demo on the http://www.FreeRTOS.org -website for more information. ***********************************************/ - -/* The priority for the task that unblocked by the MAC interrupt to process -received packets. */ -#define configMAC_INPUT_TASK_PRIORITY (configMAX_PRIORITIES - 1) - -/* The priority of the task that runs the lwIP stack. */ -#define configLWIP_TASK_PRIORITY (configMAX_PRIORITIES - 2) - -/* The priority of the task that uses lwIP sockets to provide a simple command -line interface. */ -#define configCLI_TASK_PRIORITY (tskIDLE_PRIORITY) - -/* MAC address configuration. */ -#define configMAC_ADDR0 0x00 -#define configMAC_ADDR1 0x13 -#define configMAC_ADDR2 0x14 -#define configMAC_ADDR3 0x15 -#define configMAC_ADDR4 0x15 -#define configMAC_ADDR5 0x16 - -/* IP address configuration. */ -#define configIP_ADDR0 172 -#define configIP_ADDR1 25 -#define configIP_ADDR2 218 -#define configIP_ADDR3 200 - -/* Netmask configuration. */ -#define configNET_MASK0 255 -#define configNET_MASK1 255 -#define configNET_MASK2 255 -#define configNET_MASK3 0 - -#endif /* FREERTOS_CONFIG_H */ +/* README!!! + * + * This configuration is copied from the FreeRTOS v10.1.1 + * based example project for the Zynq 7000 platform (for + * compatibility). However, you can add to it. + * + * Another example configuration file is available at + * "sdk/FreeRTOS-Kernel/examples/sample_configuration/FreeRTOSConfig.h" + * Because that example is in the submodule, it may update + * from time-to-time when the submodule is updated. + */ + +/* + * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#include "xparameters.h" + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html + *----------------------------------------------------------*/ + +/* + * The FreeRTOS Cortex-A port implements a full interrupt nesting model. + * + * Interrupts that are assigned a priority at or below + * configMAX_API_CALL_INTERRUPT_PRIORITY (which counter-intuitively in the ARM + * generic interrupt controller [GIC] means a priority that has a numerical + * value above configMAX_API_CALL_INTERRUPT_PRIORITY) can call FreeRTOS safe API + * functions and will nest. + * + * Interrupts that are assigned a priority above + * configMAX_API_CALL_INTERRUPT_PRIORITY (which in the GIC means a numerical + * value below configMAX_API_CALL_INTERRUPT_PRIORITY) cannot call any FreeRTOS + * API functions, will nest, and will not be masked by FreeRTOS critical + * sections (although it is necessary for interrupts to be globally disabled + * extremely briefly as the interrupt mask is updated in the GIC). + * + * FreeRTOS functions that can be called from an interrupt are those that end in + * "FromISR". FreeRTOS maintains a separate interrupt safe API to enable + * interrupt entry to be shorter, faster, simpler and smaller. + * + * The Zynq implements 256 unique interrupt priorities. For the purpose of + * setting configMAX_API_CALL_INTERRUPT_PRIORITY 255 represents the lowest + * priority. + */ +#define configMAX_API_CALL_INTERRUPT_PRIORITY 18 + +#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 configPERIPHERAL_CLOCK_HZ (33333000UL) +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 0 // TODO: For low-power, set 1 and implement vApplicationIdleHook() +#define configUSE_TICK_HOOK 0 // TODO: Set as 1 if we want to run function every tick +#define configMAX_PRIORITIES (7) +#define configTOTAL_HEAP_SIZE (125 * 1024) +#define configMAX_TASK_NAME_LEN (10) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 8 +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_MALLOC_FAILED_HOOK 0 +#define configUSE_APPLICATION_TASK_TAG 0 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_QUEUE_SETS 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 +#define configSUPPORT_STATIC_ALLOCATION 1 + +/* AMDC ADDITION: Need to specify this callback config so we can create message buffers with callbacks + * This is done for Inter-Core Communication (src/sys/icc.c) */ +#define configUSE_SB_COMPLETED_CALLBACK 1 + +/* Include the query-heap CLI command to query the free heap space. */ +#define configINCLUDE_QUERY_HEAP_COMMAND 1 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES (2) + +/* Software timer definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) +#define configTIMER_QUEUE_LENGTH 5 +#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2) + +/* If configUSE_TASK_FPU_SUPPORT is set to 1 (or undefined) then each task will +be created without an FPU context, and a task must call vTaskUsesFPU() before +making use of any FPU registers. If configUSE_TASK_FPU_SUPPORT is set to 2 then +tasks are created with an FPU context by default, and calling vTaskUsesFPU() has +no effect. */ +#define configUSE_TASK_FPU_SUPPORT 2 +#define configMINIMAL_STACK_SIZE ((unsigned short) 250) // Large since all tasks have FPU context + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 1 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xTaskAbortDelay 1 +#define INCLUDE_xTaskGetTaskHandle 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 + +/* This demo makes use of one or more example stats formatting functions. These +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 + +/* The private watchdog is used to generate run time stats. */ +/* +#include "xscuwdt.h" +extern XScuWdt xWatchDogInstance; +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 ) +*/ + +/* 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 +and one on TCP/IP). This is done to prevent an output buffer being defined by +each implementation - which would waste RAM. In this case, there is only one +command interpreter running. */ +#define configCOMMAND_INT_MAX_OUTPUT_SIZE 2096 + +/* Normal assert() semantics without relying on the provision of an assert.h +header file. */ +void vAssertCalled(const char *pcFile, unsigned long ulLine); + +// Original Implementation +//#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ ); + +#define configASSERT(x) \ + if ((x) == 0) \ + while (1) \ + ; + +/* If configTASK_RETURN_ADDRESS is not defined then a task that attempts to +return from its implementing function will end up in a "task exit error" +function - which contains a call to configASSERT(). However this can give GCC +some problems when it tries to unwind the stack, as the exit error function has +nothing to return to. To avoid this define configTASK_RETURN_ADDRESS to 0. */ +#define configTASK_RETURN_ADDRESS NULL + +/****** Hardware specific settings. *******************************************/ + +/* + * The application must provide a function that configures a peripheral to + * create the FreeRTOS tick interrupt, then define configSETUP_TICK_INTERRUPT() + * in FreeRTOSConfig.h to call the function. This file contains a function + * that is suitable for use on the Zynq MPU. FreeRTOS_Tick_Handler() must + * be installed as the peripheral's interrupt handler. + */ +void vConfigureTickInterrupt(void); +#define configSETUP_TICK_INTERRUPT() vConfigureTickInterrupt() + +void vClearTickInterrupt(void); +#define configCLEAR_TICK_INTERRUPT() vClearTickInterrupt() + +/* The following constant describe the hardware, and are correct for the +Zynq MPU. */ +#define configINTERRUPT_CONTROLLER_BASE_ADDRESS (XPAR_PS7_SCUGIC_0_DIST_BASEADDR) +#define configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET (-0xf00) +#define configUNIQUE_INTERRUPT_PRIORITIES 32 + +/****** Network configuration settings - only used when the lwIP example is +built. See the page that documents this demo on the http://www.FreeRTOS.org +website for more information. ***********************************************/ + +/* The priority for the task that unblocked by the MAC interrupt to process +received packets. */ +#define configMAC_INPUT_TASK_PRIORITY (configMAX_PRIORITIES - 1) + +/* The priority of the task that runs the lwIP stack. */ +#define configLWIP_TASK_PRIORITY (configMAX_PRIORITIES - 2) + +/* The priority of the task that uses lwIP sockets to provide a simple command +line interface. */ +#define configCLI_TASK_PRIORITY (tskIDLE_PRIORITY) + +/* MAC address configuration. */ +#define configMAC_ADDR0 0x00 +#define configMAC_ADDR1 0x13 +#define configMAC_ADDR2 0x14 +#define configMAC_ADDR3 0x15 +#define configMAC_ADDR4 0x15 +#define configMAC_ADDR5 0x16 + +/* IP address configuration. */ +#define configIP_ADDR0 172 +#define configIP_ADDR1 25 +#define configIP_ADDR2 218 +#define configIP_ADDR3 200 + +/* Netmask configuration. */ +#define configNET_MASK0 255 +#define configNET_MASK1 255 +#define configNET_MASK2 255 +#define configNET_MASK3 0 + +#endif /* FREERTOS_CONFIG_H */ diff --git a/sdk/freertos_app_cpu1/src/Xilinx.spec b/sdk/freertos_app_cpu1/src/Xilinx.spec index 8eea3774..9c27dcad 100644 --- a/sdk/freertos_app_cpu1/src/Xilinx.spec +++ b/sdk/freertos_app_cpu1/src/Xilinx.spec @@ -1,2 +1,2 @@ -*startfile: -crti%O%s crtbegin%O%s +*startfile: +crti%O%s crtbegin%O%s From 88659f10c6e7b7c469dfbd11f13399b8a5ebc472 Mon Sep 17 00:00:00 2001 From: Ryan Srichai Date: Fri, 2 Aug 2024 12:47:55 -0500 Subject: [PATCH 12/17] linux permissions on shared --- sdk/shared/FreeRTOS_tick_config.c | 276 +++++++++++++++--------------- sdk/shared/README.md | 60 +++---- 2 files changed, 168 insertions(+), 168 deletions(-) diff --git a/sdk/shared/FreeRTOS_tick_config.c b/sdk/shared/FreeRTOS_tick_config.c index b231f163..8ed8452d 100644 --- a/sdk/shared/FreeRTOS_tick_config.c +++ b/sdk/shared/FreeRTOS_tick_config.c @@ -1,138 +1,138 @@ -/* - * FreeRTOS Kernel V10.1.1 - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * 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: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * 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. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - -/* FreeRTOS includes. */ -#include "FreeRTOS.h" -#include "task.h" - -/* Xilinx includes. */ -#include "xscugic.h" -#include "xscutimer.h" - -#define XSCUTIMER_CLOCK_HZ (XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ / 2UL) - -static XScuTimer xTimer; -XScuGic xInterruptController; /* Interrupt controller instance */ - -/* - * The application must provide a function that configures a peripheral to - * create the FreeRTOS tick interrupt, then define configSETUP_TICK_INTERRUPT() - * in FreeRTOSConfig.h to call the function. This file contains a function - * that is suitable for use on the Zynq SoC. - */ -void vConfigureTickInterrupt(void) -{ - BaseType_t xStatus; - extern void FreeRTOS_Tick_Handler(void); - XScuTimer_Config *pxTimerConfig; - XScuGic_Config *pxGICConfig; - const uint8_t ucRisingEdge = 3; - - /* This function is called with the IRQ interrupt disabled, and the IRQ - interrupt should be left disabled. It is enabled automatically when the - scheduler is started. */ - - /* Ensure XScuGic_CfgInitialize() has been called. In this demo it has - already been called from prvSetupHardware() in main(). */ - pxGICConfig = XScuGic_LookupConfig(XPAR_SCUGIC_SINGLE_DEVICE_ID); - xStatus = XScuGic_CfgInitialize(&xInterruptController, pxGICConfig, pxGICConfig->CpuBaseAddress); - configASSERT(xStatus == XST_SUCCESS); - (void) xStatus; /* Remove compiler warning if configASSERT() is not defined. */ - - /* The priority must be the lowest possible. */ - XScuGic_SetPriorityTriggerType(&xInterruptController, - XPAR_SCUTIMER_INTR, - portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT, - ucRisingEdge); - - /* Install the FreeRTOS tick handler. */ - xStatus = XScuGic_Connect( - &xInterruptController, XPAR_SCUTIMER_INTR, (Xil_ExceptionHandler) FreeRTOS_Tick_Handler, (void *) &xTimer); - configASSERT(xStatus == XST_SUCCESS); - (void) xStatus; /* Remove compiler warning if configASSERT() is not defined. */ - - /* Initialise the timer. */ - pxTimerConfig = XScuTimer_LookupConfig(XPAR_SCUTIMER_DEVICE_ID); - xStatus = XScuTimer_CfgInitialize(&xTimer, pxTimerConfig, pxTimerConfig->BaseAddr); - configASSERT(xStatus == XST_SUCCESS); - (void) xStatus; /* Remove compiler warning if configASSERT() is not defined. */ - - /* Enable Auto reload mode. */ - XScuTimer_EnableAutoReload(&xTimer); - - /* Ensure there is no prescale. */ - XScuTimer_SetPrescaler(&xTimer, 0); - - /* Load the timer counter register. */ - XScuTimer_LoadTimer(&xTimer, XSCUTIMER_CLOCK_HZ / configTICK_RATE_HZ); - - /* Start the timer counter and then wait for it to timeout a number of - times. */ - XScuTimer_Start(&xTimer); - - /* Enable the interrupt for the xTimer in the interrupt controller. */ - XScuGic_Enable(&xInterruptController, XPAR_SCUTIMER_INTR); - - /* Enable the interrupt in the xTimer itself. */ - vClearTickInterrupt(); - XScuTimer_EnableInterrupt(&xTimer); -} -/*-----------------------------------------------------------*/ - -void vClearTickInterrupt(void) -{ - XScuTimer_ClearInterruptStatus(&xTimer); -} -/*-----------------------------------------------------------*/ - -/* This is the callback function which is called by the FreeRTOS Cortex-A port -layer in response to an interrupt. If the function is called -vApplicationFPUSafeIRQHandler() then it is called after the floating point -registers have been saved. If the function is called vApplicationIRQHandler() -then it will be called without first having saved the FPU registers. See -http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html for -more information */ -void vApplicationFPUSafeIRQHandler(uint32_t ulICCIAR) -{ - extern const XScuGic_Config XScuGic_ConfigTable[]; - static const XScuGic_VectorTableEntry *pxVectorTable - = XScuGic_ConfigTable[XPAR_SCUGIC_SINGLE_DEVICE_ID].HandlerTable; - uint32_t ulInterruptID; - const XScuGic_VectorTableEntry *pxVectorEntry; - - /* Re-enable interrupts. */ - __asm("cpsie i"); - - /* The ID of the interrupt is obtained by bitwise anding the ICCIAR value - with 0x3FF. */ - ulInterruptID = ulICCIAR & 0x3FFUL; - if (ulInterruptID < XSCUGIC_MAX_NUM_INTR_INPUTS) { - /* Call the function installed in the array of installed handler functions. */ - pxVectorEntry = &(pxVectorTable[ulInterruptID]); - pxVectorEntry->Handler(pxVectorEntry->CallBackRef); - } -} +/* + * FreeRTOS Kernel V10.1.1 + * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Xilinx includes. */ +#include "xscugic.h" +#include "xscutimer.h" + +#define XSCUTIMER_CLOCK_HZ (XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ / 2UL) + +static XScuTimer xTimer; +XScuGic xInterruptController; /* Interrupt controller instance */ + +/* + * The application must provide a function that configures a peripheral to + * create the FreeRTOS tick interrupt, then define configSETUP_TICK_INTERRUPT() + * in FreeRTOSConfig.h to call the function. This file contains a function + * that is suitable for use on the Zynq SoC. + */ +void vConfigureTickInterrupt(void) +{ + BaseType_t xStatus; + extern void FreeRTOS_Tick_Handler(void); + XScuTimer_Config *pxTimerConfig; + XScuGic_Config *pxGICConfig; + const uint8_t ucRisingEdge = 3; + + /* This function is called with the IRQ interrupt disabled, and the IRQ + interrupt should be left disabled. It is enabled automatically when the + scheduler is started. */ + + /* Ensure XScuGic_CfgInitialize() has been called. In this demo it has + already been called from prvSetupHardware() in main(). */ + pxGICConfig = XScuGic_LookupConfig(XPAR_SCUGIC_SINGLE_DEVICE_ID); + xStatus = XScuGic_CfgInitialize(&xInterruptController, pxGICConfig, pxGICConfig->CpuBaseAddress); + configASSERT(xStatus == XST_SUCCESS); + (void) xStatus; /* Remove compiler warning if configASSERT() is not defined. */ + + /* The priority must be the lowest possible. */ + XScuGic_SetPriorityTriggerType(&xInterruptController, + XPAR_SCUTIMER_INTR, + portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT, + ucRisingEdge); + + /* Install the FreeRTOS tick handler. */ + xStatus = XScuGic_Connect( + &xInterruptController, XPAR_SCUTIMER_INTR, (Xil_ExceptionHandler) FreeRTOS_Tick_Handler, (void *) &xTimer); + configASSERT(xStatus == XST_SUCCESS); + (void) xStatus; /* Remove compiler warning if configASSERT() is not defined. */ + + /* Initialise the timer. */ + pxTimerConfig = XScuTimer_LookupConfig(XPAR_SCUTIMER_DEVICE_ID); + xStatus = XScuTimer_CfgInitialize(&xTimer, pxTimerConfig, pxTimerConfig->BaseAddr); + configASSERT(xStatus == XST_SUCCESS); + (void) xStatus; /* Remove compiler warning if configASSERT() is not defined. */ + + /* Enable Auto reload mode. */ + XScuTimer_EnableAutoReload(&xTimer); + + /* Ensure there is no prescale. */ + XScuTimer_SetPrescaler(&xTimer, 0); + + /* Load the timer counter register. */ + XScuTimer_LoadTimer(&xTimer, XSCUTIMER_CLOCK_HZ / configTICK_RATE_HZ); + + /* Start the timer counter and then wait for it to timeout a number of + times. */ + XScuTimer_Start(&xTimer); + + /* Enable the interrupt for the xTimer in the interrupt controller. */ + XScuGic_Enable(&xInterruptController, XPAR_SCUTIMER_INTR); + + /* Enable the interrupt in the xTimer itself. */ + vClearTickInterrupt(); + XScuTimer_EnableInterrupt(&xTimer); +} +/*-----------------------------------------------------------*/ + +void vClearTickInterrupt(void) +{ + XScuTimer_ClearInterruptStatus(&xTimer); +} +/*-----------------------------------------------------------*/ + +/* This is the callback function which is called by the FreeRTOS Cortex-A port +layer in response to an interrupt. If the function is called +vApplicationFPUSafeIRQHandler() then it is called after the floating point +registers have been saved. If the function is called vApplicationIRQHandler() +then it will be called without first having saved the FPU registers. See +http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html for +more information */ +void vApplicationFPUSafeIRQHandler(uint32_t ulICCIAR) +{ + extern const XScuGic_Config XScuGic_ConfigTable[]; + static const XScuGic_VectorTableEntry *pxVectorTable + = XScuGic_ConfigTable[XPAR_SCUGIC_SINGLE_DEVICE_ID].HandlerTable; + uint32_t ulInterruptID; + const XScuGic_VectorTableEntry *pxVectorEntry; + + /* Re-enable interrupts. */ + __asm("cpsie i"); + + /* The ID of the interrupt is obtained by bitwise anding the ICCIAR value + with 0x3FF. */ + ulInterruptID = ulICCIAR & 0x3FFUL; + if (ulInterruptID < XSCUGIC_MAX_NUM_INTR_INPUTS) { + /* Call the function installed in the array of installed handler functions. */ + pxVectorEntry = &(pxVectorTable[ulInterruptID]); + pxVectorEntry->Handler(pxVectorEntry->CallBackRef); + } +} diff --git a/sdk/shared/README.md b/sdk/shared/README.md index 49cda056..acf8ca46 100644 --- a/sdk/shared/README.md +++ b/sdk/shared/README.md @@ -1,30 +1,30 @@ -# Shared Code Folder - -This folder (`AMDC-Firmware/sdk/shared`) contains source code shared by both CPU applications in the v2, FreeRTOS-based firmware. - -Shared code includes system-level source code for inter-core communication, interrupts, etc, as well as the [FreeRTOS-Kernel](https://github.com/FreeRTOS/FreeRTOS-Kernel) source code, which is available in `AMDC-Firmware/sdk/FreeRTOS-Kernel` as a [Git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules). - -### Differentiating code between CPUs - -If you need to include or run slightly different code on CPU 0 and CPU 1 in a shared source file, it can be done using the `#if` directive like so: - -```c -#include xparameters.h // Must be included to gain access to the XPAR_CPU_ID definition -#include foo.h -#include bar.h - -// Code to be included on both CPUs - -#if XPAR_CPU_ID == 0 - -// Code for CPU 0 only - -#elif XPAR_CPU_ID == 1 - -// Code for CPU 1 only - -#endif - -// More code to be included on both CPUs - -``` +# Shared Code Folder + +This folder (`AMDC-Firmware/sdk/shared`) contains source code shared by both CPU applications in the v2, FreeRTOS-based firmware. + +Shared code includes system-level source code for inter-core communication, interrupts, etc, as well as the [FreeRTOS-Kernel](https://github.com/FreeRTOS/FreeRTOS-Kernel) source code, which is available in `AMDC-Firmware/sdk/FreeRTOS-Kernel` as a [Git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules). + +### Differentiating code between CPUs + +If you need to include or run slightly different code on CPU 0 and CPU 1 in a shared source file, it can be done using the `#if` directive like so: + +```c +#include xparameters.h // Must be included to gain access to the XPAR_CPU_ID definition +#include foo.h +#include bar.h + +// Code to be included on both CPUs + +#if XPAR_CPU_ID == 0 + +// Code for CPU 0 only + +#elif XPAR_CPU_ID == 1 + +// Code for CPU 1 only + +#endif + +// More code to be included on both CPUs + +``` From b9fe11870745ce18bb8637d55db9f8e7f4e7a03b Mon Sep 17 00:00:00 2001 From: Ryan Srichai Date: Fri, 2 Aug 2024 12:50:23 -0500 Subject: [PATCH 13/17] permissions on blink --- .../src/usr/blink/task_blink.c | 184 +++++++++--------- .../src/usr/blink/task_vsi.c | 110 +++++------ .../src/usr/blink/task_vsi.h | 30 +-- 3 files changed, 162 insertions(+), 162 deletions(-) diff --git a/sdk/freertos_app_cpu0/src/usr/blink/task_blink.c b/sdk/freertos_app_cpu0/src/usr/blink/task_blink.c index 2a84c892..1293eba4 100644 --- a/sdk/freertos_app_cpu0/src/usr/blink/task_blink.c +++ b/sdk/freertos_app_cpu0/src/usr/blink/task_blink.c @@ -1,92 +1,92 @@ -#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 - -// 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, tskIDLE_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 +#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 + +// 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, tskIDLE_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/freertos_app_cpu0/src/usr/blink/task_vsi.c b/sdk/freertos_app_cpu0/src/usr/blink/task_vsi.c index e6e7bbe7..6e8c0d9a 100644 --- a/sdk/freertos_app_cpu0/src/usr/blink/task_vsi.c +++ b/sdk/freertos_app_cpu0/src/usr/blink/task_vsi.c @@ -1,55 +1,55 @@ -#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 -#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, tskIDLE_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 +#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 +#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, tskIDLE_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 index eeaf396f..c401d6f4 100644 --- a/sdk/freertos_app_cpu0/src/usr/blink/task_vsi.h +++ b/sdk/freertos_app_cpu0/src/usr/blink/task_vsi.h @@ -1,15 +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 +#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 From 9f6ec248d47bbe1a3d5f52aad1eaceb28ff3bd4f Mon Sep 17 00:00:00 2001 From: Ryan Srichai Date: Fri, 2 Aug 2024 12:51:28 -0500 Subject: [PATCH 14/17] platform config --- sdk/shared/platform_config.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sdk/shared/platform_config.h b/sdk/shared/platform_config.h index eda2e2eb..3e9b7f18 100644 --- a/sdk/shared/platform_config.h +++ b/sdk/shared/platform_config.h @@ -1,6 +1,6 @@ -#ifndef __PLATFORM_CONFIG_H_ -#define __PLATFORM_CONFIG_H_ - -#define STDOUT_IS_PS7_UART -#define UART_DEVICE_ID 0 -#endif +#ifndef __PLATFORM_CONFIG_H_ +#define __PLATFORM_CONFIG_H_ + +#define STDOUT_IS_PS7_UART +#define UART_DEVICE_ID 0 +#endif From 4fcb91f12cfc66be234278009a770db49e626562 Mon Sep 17 00:00:00 2001 From: Ryan Srichai Date: Fri, 2 Aug 2024 12:53:44 -0500 Subject: [PATCH 15/17] include projdefs in commands.h --- sdk/.vscode/settings.json | 5 +++++ sdk/shared/sys/commands.h | 2 ++ 2 files changed, 7 insertions(+) create mode 100644 sdk/.vscode/settings.json diff --git a/sdk/.vscode/settings.json b/sdk/.vscode/settings.json new file mode 100644 index 00000000..21404648 --- /dev/null +++ b/sdk/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "projdefs.h": "c" + } +} \ No newline at end of file diff --git a/sdk/shared/sys/commands.h b/sdk/shared/sys/commands.h index 65bd4852..652e6151 100644 --- a/sdk/shared/sys/commands.h +++ b/sdk/shared/sys/commands.h @@ -1,6 +1,8 @@ #ifndef COMMANDS_H #define COMMANDS_H +#include "projdefs.h" + #define COMMANDS_UPDATES_PER_SEC (10000) #define COMMANDS_INTERVAL_TICKS (pdMS_TO_TICKS(1000.0 / COMMANDS_UPDATES_PER_SEC)) From d573a30ed62c42a43596070e4b02f418299bbddc Mon Sep 17 00:00:00 2001 From: Ryan Srichai Date: Fri, 2 Aug 2024 12:54:18 -0500 Subject: [PATCH 16/17] removed vscode folder --- sdk/.vscode/settings.json | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 sdk/.vscode/settings.json diff --git a/sdk/.vscode/settings.json b/sdk/.vscode/settings.json deleted file mode 100644 index 21404648..00000000 --- a/sdk/.vscode/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "files.associations": { - "projdefs.h": "c" - } -} \ No newline at end of file From 6a946b8455a4dd88595c1dbdf5e7f522ee036214 Mon Sep 17 00:00:00 2001 From: Ryan Srichai Date: Fri, 2 Aug 2024 13:28:52 -0500 Subject: [PATCH 17/17] runtime statistics implemented, ran the code on AMDC and the tasks clobber each other and the lights look funny, but this is expected behaviour --- sdk/freertos_app_cpu0/.cproject | 27 ++++++---- sdk/freertos_app_cpu0/.project | 4 +- sdk/freertos_app_cpu0/src/FreeRTOSConfig.h | 20 ++++---- .../src/usr/blink/task_blink.c | 3 +- .../src/usr/blink/task_vsi.c | 3 +- sdk/shared/drv/timer_stats.c | 50 +++++++++++++++++++ sdk/shared/drv/timer_stats.h | 17 +++++++ sdk/shared/sys/commands.c | 3 +- sdk/shared/sys/intr.c | 2 + sdk/shared/sys/intr.h | 2 +- sdk/shared/sys/serial.c | 3 +- sdk/shared/sys/task_priority.h | 13 +++++ 12 files changed, 121 insertions(+), 26 deletions(-) create mode 100644 sdk/shared/drv/timer_stats.c create mode 100644 sdk/shared/drv/timer_stats.h create mode 100644 sdk/shared/sys/task_priority.h diff --git a/sdk/freertos_app_cpu0/.cproject b/sdk/freertos_app_cpu0/.cproject index 0d032b50..99b90ffa 100644 --- a/sdk/freertos_app_cpu0/.cproject +++ b/sdk/freertos_app_cpu0/.cproject @@ -32,21 +32,25 @@ - + - - + + - + + + + + + + - - - + @@ -61,11 +65,11 @@ - + @@ -113,7 +117,7 @@ - + @@ -152,6 +156,7 @@ + @@ -173,9 +178,11 @@ + diff --git a/sdk/freertos_app_cpu0/.project b/sdk/freertos_app_cpu0/.project index 30288dae..1cd1942e 100644 --- a/sdk/freertos_app_cpu0/.project +++ b/sdk/freertos_app_cpu0/.project @@ -27,12 +27,12 @@ FreeRTOS-Kernel 2 - C:/Users/srich008/Information/v2-staging/sdk/FreeRTOS-Kernel + C:/Users/srich008/Information/gitMistakes/freertos-singlecore-temp/sdk/FreeRTOS-Kernel shared 2 - C:/Users/srich008/Information/v2-staging/sdk/shared + 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/usr/blink/task_blink.c b/sdk/freertos_app_cpu0/src/usr/blink/task_blink.c index 1293eba4..eaedb4ae 100644 --- a/sdk/freertos_app_cpu0/src/usr/blink/task_blink.c +++ b/sdk/freertos_app_cpu0/src/usr/blink/task_blink.c @@ -7,6 +7,7 @@ #include "usr/blink/task_blink.h" #include "drv/led.h" #include "sys/defines.h" +#include "sys/task_priority.h" #include // Hold LED animation state @@ -34,7 +35,7 @@ int task_blink_init(void) } // Fill TCB with parameters xTaskCreate(task_blink, (const char *) "blink", configMINIMAL_STACK_SIZE, - NULL, tskIDLE_PRIORITY, &tcb); + NULL, BLINK_TASK_PRIORITY, &tcb); taskExists = 1; return SUCCESS; } diff --git a/sdk/freertos_app_cpu0/src/usr/blink/task_vsi.c b/sdk/freertos_app_cpu0/src/usr/blink/task_vsi.c index 6e8c0d9a..7371f0d3 100644 --- a/sdk/freertos_app_cpu0/src/usr/blink/task_vsi.c +++ b/sdk/freertos_app_cpu0/src/usr/blink/task_vsi.c @@ -6,6 +6,7 @@ #include "usr/blink/task_vsi.h" #include "drv/led.h" #include "sys/defines.h" +#include "sys/task_priority.h" #include #include @@ -27,7 +28,7 @@ void task_vsi_init(void) { // Fill TCB with parameters xTaskCreate(task_vsi, (const char *) "vsi", configMINIMAL_STACK_SIZE, - NULL, tskIDLE_PRIORITY, &tcb); + NULL, VSI_TASK_PRIORITY, &tcb); } void task_vsi(void *arg) 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/shared/sys/commands.c b/sdk/shared/sys/commands.c index 6ec9b02f..88902ffe 100644 --- a/sdk/shared/sys/commands.c +++ b/sdk/shared/sys/commands.c @@ -14,6 +14,7 @@ // #include "sys/scheduler.h" #include "sys/serial.h" #include "sys/util.h" +#include "sys/task_priority.h" #include #include #include @@ -133,7 +134,7 @@ void commands_init(void) // Command parse & exec task (UART) xTaskCreate(commands_main_uart, (const char *) "command_parse_uart", configMINIMAL_STACK_SIZE, - NULL, tskIDLE_PRIORITY, &tcb_parse_uart); + NULL, CMD_UART_TASK_PRIORITY, &tcb_parse_uart); // // Command parse task (ETH) // scheduler_tcb_init( 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/shared/sys/serial.c b/sdk/shared/sys/serial.c index 96dc21f5..a8743a01 100644 --- a/sdk/shared/sys/serial.c +++ b/sdk/shared/sys/serial.c @@ -5,6 +5,7 @@ #include "sys/serial.h" #include "drv/uart.h" #include "sys/util.h" +#include "sys/task_priority.h" #include #define OUTPUT_BUFFER_LENGTH (32 * 1024) @@ -28,7 +29,7 @@ void serial_init(void) { // Create serial task xTaskCreate(serial_main, (const char *) "uartSerial", configMINIMAL_STACK_SIZE, - NULL, tskIDLE_PRIORITY, &xSerialTaskHandle); + NULL, SERIAL_TASK_PRIORITY, &xSerialTaskHandle); } void serial_main(void *arg) 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