added freeRTOS on linux build

This commit is contained in:
Ulrich Mohr 2024-07-12 16:56:31 +02:00
parent a7336c7f75
commit 976e079d02
16 changed files with 576 additions and 321 deletions

View File

@ -71,4 +71,30 @@ Every time
make -j 8"
```
The romeo-obsw binary can now be found in the `build` directory. The next step to deploy it is here: [DEBUG_ON_ZEDBOARD.md](./DEBUG_ON_ZEDBOARD.md).
The romeo-obsw binary can now be found in the `build` directory. The next step to deploy it is here: [DEBUG_ON_ZEDBOARD.md](./DEBUG_ON_ZEDBOARD.md).
## Linux
The obsw can also be compiled and run on linux using the gcc-posix port of FreeRTOS.
### build
Once:
```sh
mkdir -p build
cd build
cmake ..
```
Every time
```sh
make -j 8"
```
### run
Run the binary
```sh
./romeo-obsw
```

View File

@ -1,8 +1,7 @@
cmake_minimum_required(VERSION 3.13)
# Project Name
project(romeo-obsw C CXX ASM)
project(romeo-obsw C ASM)
# ##############################################################################
# Pre-Sources preparation
@ -10,18 +9,13 @@ project(romeo-obsw C CXX ASM)
# Specify the C++ standard
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# Set names and variables
set(TARGET_NAME ${CMAKE_PROJECT_NAME})
# Set path names
set(FreeRTOS_PATH FreeRTOS-Kernel/)
set(MISSION_PATH mission/)
set(FreeRTOS_CONFIG_PATH bsp_z7/freeRTOS)
set(BSP_PATH bsp_z7)
set (LWIP_DIR contrib/lwip)
@ -30,14 +24,18 @@ set (LWIP_DIR contrib/lwip)
# Configuration
# ##############################################################################
set(ZYNQ_UART UART1 CACHE STRING "Which PS UART to use for stdout")
set_property(CACHE ZYNQ_UART PROPERTY STRINGS UART0 UART1)
if (${CMAKE_CROSSCOMPILING})
set(ZYNQ_UART UART1 CACHE STRING "Which PS UART to use for stdout")
set_property(CACHE ZYNQ_UART PROPERTY STRINGS UART0 UART1)
if(${ZYNQ_UART} STREQUAL UART0)
add_compile_definitions(ZYNQ_USE_UART0)
if(${ZYNQ_UART} STREQUAL UART0)
add_compile_definitions(ZYNQ_USE_UART0)
endif()
else()
unset(ZYNQ_UART)
unset(ZYNQ_UART CACHE)
endif()
# ##############################################################################
# Executable and Sources
# ##############################################################################
@ -48,7 +46,7 @@ add_executable(${TARGET_NAME})
# lwip
set (LWIP_INCLUDE_DIRS
"${LWIP_DIR}/src/include"
"${BSP_PATH}/lwip"
"bsp_z7/lwip"
)
#include(${LWIP_DIR}/src/Filelists.cmake)
set(lwip_SRCS
@ -58,30 +56,48 @@ set(lwip_SRCS
${LWIP_DIR}/src/netif/slipif.c
${LWIP_DIR}/src/apps/tftp/tftp.c
)
add_library(lwip ${lwip_SRCS})
target_include_directories(lwip PUBLIC ${LWIP_INCLUDE_DIRS})
#target_compile_options(${TARGET_NAME} PUBLIC -g -O0 -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard)
if(${CMAKE_CROSSCOMPILING})
add_library(lwip ${lwip_SRCS})
target_include_directories(lwip PUBLIC ${LWIP_INCLUDE_DIRS})
endif()
# Add freeRTOS
set(FREERTOS_PORT GCC_ARM_CA9 CACHE STRING "")
set(FREERTOS_HEAP 1 CACHE STRING "")
add_library(freertos_config INTERFACE)
target_include_directories(freertos_config SYSTEM
INTERFACE ${FreeRTOS_CONFIG_PATH}) # The config file directory
target_compile_definitions(freertos_config
INTERFACE
projCOVERAGE_TEST=0)
target_include_directories(
freertos_config INTERFACE ${BSP_PATH}/ps7_cortexa9_0/include)
# our compiler options, will trickle down through the project
target_compile_options(freertos_config INTERFACE -c -fmessage-length=0 -g -O0 -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -ffunction-sections -fdata-sections)
if(${CMAKE_CROSSCOMPILING})
#TODO: this somewhat hardcodes zynq as the only cross target
set(FREERTOS_PORT GCC_ARM_CA9 CACHE STRING "")
set(FREERTOS_HEAP 1 CACHE STRING "")
add_library(freertos_config INTERFACE)
target_include_directories(freertos_config SYSTEM
INTERFACE bsp_z7/freeRTOS) # The config file directory
target_compile_definitions(freertos_config
INTERFACE
projCOVERAGE_TEST=0)
target_include_directories(
freertos_config INTERFACE bsp_z7/ps7_cortexa9_0/include)
if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL armv7a-none-eabihf)
# our compiler options, will trickle down through the project
target_compile_options(freertos_config INTERFACE -c -fmessage-length=0 -g -O0 -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -ffunction-sections -fdata-sections)
else()
message(FATAL_ERROR "invalid architecture ${CMAKE_SYSTEM_PROCESSOR}")
endif()
add_subdirectory(bsp_z7)
target_link_options(${TARGET_NAME} PRIVATE -Wl,--cref -Wl,-Map=${TARGET_NAME}.map -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -Wl,-build-id=none -T${CMAKE_SOURCE_DIR}/bsp_z7/freeRTOS/lscript.ld -specs=${CMAKE_SOURCE_DIR}/bsp_z7/freeRTOS/Xilinx.spec )
else()
set(FREERTOS_PORT GCC_POSIX CACHE STRING "")
add_library(freertos_config INTERFACE)
target_include_directories(freertos_config SYSTEM
INTERFACE bsp_linux/freeRTOS) # The config file directory
target_compile_options(freertos_config INTERFACE -c -fmessage-length=0 -g -O0 -ffunction-sections -fdata-sections)
target_compile_definitions(freertos_config
INTERFACE
projCOVERAGE_TEST=0
projENABLE_TRACING=0)
add_subdirectory(bsp_linux)
endif()
add_subdirectory(${FreeRTOS_PATH})
add_subdirectory(bsp_z7)
add_subdirectory(common)
@ -93,14 +109,16 @@ add_subdirectory(mission_rust)
# ##############################################################################
# Add libraries for all sources.
target_link_libraries(lwip PUBLIC freertos_kernel)
target_link_libraries(${TARGET_NAME} PUBLIC freertos_kernel mission_rust lwip)
if(${CMAKE_CROSSCOMPILING})
target_link_libraries(lwip PUBLIC freertos_kernel)
target_link_libraries(${TARGET_NAME} PUBLIC lwip)
endif()
target_include_directories(
${TARGET_NAME} PUBLIC ${BSP_PATH})
target_link_libraries(${TARGET_NAME} PUBLIC freertos_kernel mission_rust)
# target_include_directories(
# ${TARGET_NAME} PUBLIC ${BSP_PATH})
target_link_options(${TARGET_NAME} PRIVATE -Wl,--cref -Wl,-Map=${TARGET_NAME}.map -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -Wl,-build-id=none -T${CMAKE_SOURCE_DIR}/${FreeRTOS_CONFIG_PATH}/lscript.ld -specs=${CMAKE_SOURCE_DIR}/${FreeRTOS_CONFIG_PATH}/Xilinx.spec )
# Removed unused sections.
target_link_options(${TARGET_NAME} PRIVATE "-Wl,--gc-sections")

1
bsp_linux/CMakeLists.txt Normal file
View File

@ -0,0 +1 @@
target_sources(${TARGET_NAME} PRIVATE main.c)

View File

@ -0,0 +1,209 @@
/*
* FreeRTOS V202212.00
* Copyright (C) 2020 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_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
* https://www.FreeRTOS.org/a00110.html
*----------------------------------------------------------*/
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
#define configTICK_RATE_HZ ( 1000 ) /* In this non-real time simulated environment the tick frequency has to be at least a multiple of the Win32 tick frequency, and therefore very slow. */
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) PTHREAD_STACK_MIN ) /* The stack size being passed is equal to the minimum stack size needed by pthread_create(). */
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 200 * 1024 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 12 )
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configCHECK_FOR_STACK_OVERFLOW 0
#define configUSE_RECURSIVE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 20
#define configUSE_APPLICATION_TASK_TAG 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configUSE_ALTERNATIVE_API 0
#define configUSE_QUEUE_SETS 1
#define configUSE_TASK_NOTIFICATIONS 1
/* The following 2 memory allocation schemes are possible for this demo:
*
* 1. Dynamic Only.
* #define configSUPPORT_STATIC_ALLOCATION 0
* #define configSUPPORT_DYNAMIC_ALLOCATION 1
*
* 2. Static and Dynamic.
* #define configSUPPORT_STATIC_ALLOCATION 1
* #define configSUPPORT_DYNAMIC_ALLOCATION 1
*
* Static only configuration is not possible for this demo as it utilizes
* dynamic allocation.
*/
#define configSUPPORT_STATIC_ALLOCATION 0
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configRECORD_STACK_HIGH_ADDRESS 1
/* Software timer related configuration options. The maximum possible task
* priority is configMAX_PRIORITIES - 1. The priority of the timer task is
* deliberately set higher to ensure it is correctly capped back to
* configMAX_PRIORITIES - 1. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
#define configTIMER_QUEUE_LENGTH 20
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 )
#define configMAX_PRIORITIES ( 7 )
/* Run time stats gathering configuration options. */
unsigned long ulGetRunTimeCounterValue( void ); /* Prototype of function that returns run time counter. */
void vConfigureTimerForRunTimeStats( void ); /* Prototype of function that initialises the run time counter. */
#define configGENERATE_RUN_TIME_STATS 1
/* Co-routine related configuration options. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* This demo can 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
/* Enables the test whereby a stack larger than the total heap size is
* requested. */
#define configSTACK_DEPTH_TYPE uint32_t
/* Set the following definitions to 1 to include the API function, or zero
* to exclude the API function. In most cases the linker will remove unused
* functions anyway. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_uxTaskGetStackHighWaterMark2 1
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1
#define INCLUDE_xTaskGetIdleTaskHandle 1
#define INCLUDE_xTaskGetHandle 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xSemaphoreGetMutexHolder 1
#define INCLUDE_xTimerPendFunctionCall 1
#define INCLUDE_xTaskAbortDelay 1
#define configINCLUDE_MESSAGE_BUFFER_AMP_DEMO 0
#if ( configINCLUDE_MESSAGE_BUFFER_AMP_DEMO == 1 )
extern void vGenerateCoreBInterrupt( void * xUpdatedMessageBuffer );
#define sbSEND_COMPLETED( pxStreamBuffer ) vGenerateCoreBInterrupt( pxStreamBuffer )
#endif /* configINCLUDE_MESSAGE_BUFFER_AMP_DEMO */
extern void vAssertCalled( const char * const pcFileName,
unsigned long ulLine );
/* projCOVERAGE_TEST should be defined on the command line so this file can be
* used with multiple project configurations. If it is
*/
#ifndef projCOVERAGE_TEST
#error projCOVERAGE_TEST should be defined to 1 or 0 on the command line.
#endif
#ifndef projENABLE_TRACING
#error projENABLE_TRACING should be defined to 1 or 0 on the command line.
#endif
#if ( projCOVERAGE_TEST == 1 )
/* Insert NOPs in empty decision paths to ensure both true and false paths
* are being tested. */
#define mtCOVERAGE_TEST_MARKER() __asm volatile ( "NOP" )
/* Ensure the tick count overflows during the coverage test. */
#define configINITIAL_TICK_COUNT 0xffffd800UL
/* Allows tests of trying to allocate more than the heap has free. */
#define configUSE_MALLOC_FAILED_HOOK 0
/* To test builds that remove the static qualifier for debug builds. */
#define portREMOVE_STATIC_QUALIFIER
#else /* if ( projCOVERAGE_TEST == 1 ) */
/* It is a good idea to define configASSERT() while developing. configASSERT()
* uses the same semantics as the standard C assert() macro. Don't define
* configASSERT() when performing code coverage tests though, as it is not
* intended to asserts() to fail, some some code is intended not to run if no
* errors are present. */
#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ )
#define configUSE_MALLOC_FAILED_HOOK 1
/* Include the FreeRTOS+Trace FreeRTOS trace macro definitions. */
#if( projENABLE_TRACING == 1 )
#include "trcRecorder.h"
#endif /* if ( projENABLE_TRACING == 1 ) */
#endif /* if ( projCOVERAGE_TEST == 1 ) */
/* networking definitions */
#define configMAC_ISR_SIMULATOR_PRIORITY ( configMAX_PRIORITIES - 1 )
/* Prototype for the function used to print out. In this case it prints to the
* console before the network is connected then a UDP port after the network has
* connected. */
extern void vLoggingPrintf( const char * pcFormatString,
... );
/* Set to 1 to print out debug messages. If ipconfigHAS_DEBUG_PRINTF is set to
* 1 then FreeRTOS_debug_printf should be defined to the function used to print
* out the debugging messages. */
#define ipconfigHAS_DEBUG_PRINTF 1
#if ( ipconfigHAS_DEBUG_PRINTF == 1 )
#define FreeRTOS_debug_printf( X ) vLoggingPrintf X
#endif
/* Set to 1 to print out non debugging messages, for example the output of the
* FreeRTOS_netstat() command, and ping replies. If ipconfigHAS_PRINTF is set to 1
* then FreeRTOS_printf should be set to the function used to print out the
* messages. */
#define ipconfigHAS_PRINTF 0
#if ( ipconfigHAS_PRINTF == 1 )
#define FreeRTOS_printf( X ) vLoggingPrintf X
#endif
#endif /* FREERTOS_CONFIG_H */

25
bsp_linux/main.c Normal file
View File

@ -0,0 +1,25 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
void mission(void);
void done() {
printf("done.");
exit(0);
}
// Don't ask me, it makes the linker happy and does not seem
// to break anything ¯\_(ツ)_/¯
void rust_eh_personality() {
puts("eh_personality");
}
void outbyte(uint8_t byte){
printf("%c", byte);
}
int main(void) {
mission();
return 0;
}

View File

@ -1,2 +1,4 @@
add_subdirectory(freeRTOS)
add_subdirectory(ps7_cortexa9_0)
add_subdirectory(ps7_cortexa9_0)
target_sources(${TARGET_NAME} PRIVATE main.c)

View File

@ -1,9 +1,10 @@
# the name of the target operating system
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR armv7a-none-eabihf)
set(CMAKE_C_COMPILER /usr/bin/arm-none-eabi-gcc)
set(CMAKE_CXX_COMPILER /usr/bin/arm-none-eabi-g++)
set(CMAKE_ASM_COMPILER arm-none-eabi-gcc)
set(CMAKE_ASM_COMPILER /usr/bin/arm-none-eabi-gcc)
# built in tests fail
set(CMAKE_C_COMPILER_WORKS 1)

View File

@ -1,65 +1,3 @@
/*
* FreeRTOS V202212.00
* Copyright (C) 2020 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/******************************************************************************
*
* See http://www.freertos.org/RTOS-Xilinx-Zynq.html for instructions.
*
* This project provides three demo applications. A simple blinky style
* project, a more comprehensive test and demo application, and an lwIP example.
* The mainSELECTED_APPLICATION setting (defined in this file) is used to
* select between the three. The simply blinky demo is implemented and
* described in main_blinky.c. The more comprehensive test and demo application
* is implemented and described in main_full.c. The lwIP example is implemented
* and described in main_lwIP.c.
*
* This file implements the code that is not demo specific, including the
* hardware setup and FreeRTOS hook functions.
*
* !!! IMPORTANT NOTE !!!
* The GCC libraries that ship with the Xilinx SDK make use of the floating
* point registers. To avoid this causing corruption it is necessary to avoid
* their use unless a task has been given a floating point context. See
* https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
* for information on how to give a task a floating point context, and how to
* handle floating point operations in interrupts. As this demo does not give
* all tasks a floating point context main.c contains very basic C
* implementations of the standard C library functions memset(), memcpy() and
* memcmp(), which are are used by FreeRTOS itself. Defining these functions in
* the project prevents the linker pulling them in from the library. Any other
* standard C library functions that are used by the application must likewise
* be defined in C.
*
* ENSURE TO READ THE DOCUMENTATION PAGE FOR THIS PORT AND DEMO APPLICATION ON
* THE http://www.FreeRTOS.org WEB SITE FOR FULL INFORMATION ON USING THIS DEMO
* APPLICATION, AND ITS ASSOCIATE FreeRTOS ARCHITECTURE PORT!
*
*/
/* Standard includes. */
#include <limits.h>
#include <stdio.h>
@ -69,17 +7,6 @@
#include "semphr.h"
#include "task.h"
// /* Standard demo includes. */
// #include "EventGroupsDemo.h"
// #include "IntSemTest.h"
// #include "QueueOverwrite.h"
// #include "QueueSet.h"
// #include "StreamBufferDemo.h"
// #include "StreamBufferInterrupt.h"
// #include "TaskNotify.h"
// #include "TimerDemo.h"
// #include "partest.h"
/* Xilinx includes. */
// #include "platform.h"
#include "xil_exception.h"
@ -88,7 +15,6 @@
#include "xscutimer.h"
#include "xuartps_hw.h"
/*
* Configure the hardware as necessary to run this demo.
*/
@ -122,7 +48,7 @@ XScuGic xInterruptController;
extern SemaphoreHandle_t malloc_mutex;
/*-----------------------------------------------------------*/
void mission(void *);
void mission(void);
void initFreeRTOSHelper();
@ -133,63 +59,9 @@ int main(void) {
// printf("Booting Software\n");
int taskParameters = 0;
static const size_t stackSizeWords = 102400;
StaticTask_t xTaskBuffer;
StackType_t xStack[stackSizeWords];
xTaskCreate(
mission, /* The function that implements the task. */
"init", /* The text name assigned to the task - for debug only as it is
not used by the kernel. */
10240, /* The size of the stack to allocate to the task. */
&taskParameters, /* The parameter passed to the task - not used in this
simple case. */
4, /* The priority assigned to the task. */
NULL);
vTaskStartScheduler();
/* If all is well, the scheduler will now be running, and the following
line will never be reached. If the following line does execute, then
there was either insufficient FreeRTOS heap memory available for the idle
and/or timer tasks to be created, or vTaskStartScheduler() was called from
User mode. See the memory management section on the FreeRTOS web site for
more details on the FreeRTOS heap http://www.freertos.org/a00111.html. The
mode from which main() is called is set in the C start up code and must be
a privileged mode (not user mode). */
for (;;)
;
/* Don't expect to reach here. */
return 0;
mission();
}
void testIp();
void rust_main();
// Marker for debugging sessions
__attribute__ ((noinline)) void done() {
asm ("");
}
void mission(void *) {
// printf("Starting Mission\n");
//testIp();
rust_main();
// printf("Started Tasks, deleting init task\n");
done();
vTaskDelete(NULL);
}
/*-----------------------------------------------------------*/
static void prvSetupHardware(void) {
BaseType_t xStatus;
XScuGic_Config *pxGICConfig;
@ -234,124 +106,6 @@ static void prvSetupHardware(void) {
}
/*-----------------------------------------------------------*/
void vApplicationMallocFailedHook(void) {
/* Called if a call to pvPortMalloc() fails because there is insufficient
free memory available in the FreeRTOS heap. pvPortMalloc() is called
internally by FreeRTOS API functions that create tasks, queues, software
timers, and semaphores. The size of the FreeRTOS heap is set by the
configTOTAL_HEAP_SIZE configuration constant in FreeRTOSConfig.h. */
taskDISABLE_INTERRUPTS();
//TODO panic
for (;;)
;
}
/*-----------------------------------------------------------*/
void vApplicationStackOverflowHook(TaskHandle_t pxTask, char *pcTaskName) {
(void)pcTaskName;
(void)pxTask;
/* Run time stack overflow checking is performed if
configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
function is called if a stack overflow is detected. */
taskDISABLE_INTERRUPTS();
//TODO panic
for (;;)
;
}
/*-----------------------------------------------------------*/
void vApplicationIdleHook(void) {
volatile size_t xFreeHeapSpace, xMinimumEverFreeHeapSpace;
/* This is just a trivial example of an idle hook. It is called on each
cycle of the idle task. It must *NOT* attempt to block. In this case the
idle task just queries the amount of FreeRTOS heap that remains. See the
memory management section on the http://www.FreeRTOS.org web site for memory
management options. If there is a lot of heap memory free then the
configTOTAL_HEAP_SIZE value in FreeRTOSConfig.h can be reduced to free up
RAM. */
// xFreeHeapSpace = xPortGetFreeHeapSize();
// xMinimumEverFreeHeapSpace = xPortGetMinimumEverFreeHeapSize();
// /* Remove compiler warning about xFreeHeapSpace being set but never used.
// */ (void)xFreeHeapSpace; (void)xMinimumEverFreeHeapSpace;
}
/*-----------------------------------------------------------*/
void rust_assert_called(const char *pcFile, unsigned long ulLine);
void vAssertCalled(const char *pcFile, unsigned long ulLine) {
rust_assert_called(pcFile, ulLine);
volatile unsigned long ul = 0;
(void)pcFile;
(void)ulLine;
taskENTER_CRITICAL();
{
/* Set ul to a non-zero value using the debugger to step out of this
function. */
while (ul == 0) {
portNOP();
}
}
taskEXIT_CRITICAL();
}
/*-----------------------------------------------------------*/
void vApplicationTickHook(void) {
#if (mainSELECTED_APPLICATION == 1)
{
/* The full demo includes a software timer demo/test that requires
prodding periodically from the tick interrupt. */
vTimerPeriodicISRTests();
/* Call the periodic queue overwrite from ISR demo. */
vQueueOverwritePeriodicISRDemo();
/* Call the periodic event group from ISR demo. */
vPeriodicEventGroupsProcessing();
/* Use task notifications from an interrupt. */
xNotifyTaskFromISR();
/* Use mutexes from interrupts. */
vInterruptSemaphorePeriodicTest();
/* Writes to stream buffer byte by byte to test the stream buffer trigger
level functionality. */
vPeriodicStreamBufferProcessing();
/* Writes a string to a string buffer four bytes at a time to demonstrate
a stream being sent from an interrupt to a task. */
vBasicStreamBufferSendFromISR();
#if (configUSE_QUEUE_SETS == 1)
{ vQueueSetAccessQueueSetFromISR(); }
#endif
/* Test flop alignment in interrupts - calling printf from an interrupt
is BAD! */
#if (configASSERT_DEFINED == 1)
{
char cBuf[20];
UBaseType_t uxSavedInterruptStatus;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{ sprintf(cBuf, "%1.3f", 1.234); }
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
configASSERT(strcmp(cBuf, "1.234") == 0);
}
#endif /* configASSERT_DEFINED */
}
#endif
}
/*-----------------------------------------------------------*/
void vInitialiseTimerForRunTimeStats(void) {
@ -371,7 +125,6 @@ void vInitialiseTimerForRunTimeStats(void) {
XScuWdt_SetTimerMode(&xWatchDogInstance);
XScuWdt_Start(&xWatchDogInstance);
}
/*-----------------------------------------------------------*/
/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
@ -428,3 +181,73 @@ void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
configMINIMAL_STACK_SIZE is specified in words, not bytes. */
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
// Marker for debugging sessions
__attribute__((noinline)) void done() { asm(""); }
void vApplicationIdleHook(void) {
volatile size_t xFreeHeapSpace, xMinimumEverFreeHeapSpace;
/* This is just a trivial example of an idle hook. It is called on each
cycle of the idle task. It must *NOT* attempt to block. In this case the
idle task just queries the amount of FreeRTOS heap that remains. See the
memory management section on the http://www.FreeRTOS.org web site for memory
management options. If there is a lot of heap memory free then the
configTOTAL_HEAP_SIZE value in FreeRTOSConfig.h can be reduced to free up
RAM. */
// xFreeHeapSpace = xPortGetFreeHeapSize();
// xMinimumEverFreeHeapSpace = xPortGetMinimumEverFreeHeapSize();
// /* Remove compiler warning about xFreeHeapSpace being set but never used.
// */ (void)xFreeHeapSpace; (void)xMinimumEverFreeHeapSpace;
}
void vApplicationTickHook(void) {
#if (mainSELECTED_APPLICATION == 1)
{
/* The full demo includes a software timer demo/test that requires
prodding periodically from the tick interrupt. */
vTimerPeriodicISRTests();
/* Call the periodic queue overwrite from ISR demo. */
vQueueOverwritePeriodicISRDemo();
/* Call the periodic event group from ISR demo. */
vPeriodicEventGroupsProcessing();
/* Use task notifications from an interrupt. */
xNotifyTaskFromISR();
/* Use mutexes from interrupts. */
vInterruptSemaphorePeriodicTest();
/* Writes to stream buffer byte by byte to test the stream buffer trigger
level functionality. */
vPeriodicStreamBufferProcessing();
/* Writes a string to a string buffer four bytes at a time to demonstrate
a stream being sent from an interrupt to a task. */
vBasicStreamBufferSendFromISR();
#if (configUSE_QUEUE_SETS == 1)
{ vQueueSetAccessQueueSetFromISR(); }
#endif
/* Test flop alignment in interrupts - calling printf from an interrupt
is BAD! */
#if (configASSERT_DEFINED == 1)
{
char cBuf[20];
UBaseType_t uxSavedInterruptStatus;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{ sprintf(cBuf, "%1.3f", 1.234); }
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
configASSERT(strcmp(cBuf, "1.234") == 0);
}
#endif /* configASSERT_DEFINED */
}
#endif
}

View File

@ -1 +1 @@
target_sources(${TARGET_NAME} PRIVATE main.c testIp.c freeRTOS_rust_helper.c)
target_sources(${TARGET_NAME} PRIVATE mission.c freeRTOS_rust_helper.c)

View File

@ -2,15 +2,17 @@
#include "semphr.h"
#include "task.h"
#include <string.h>
// TODO namespace the names
SemaphoreHandle_t global_threading_semaphore = NULL;
uint8_t global_threading_available_c() {
if (global_threading_semaphore == NULL) {
global_threading_semaphore = xSemaphoreCreateBinary();
//xSemaphoreGive(global_threading_semaphore);
// xSemaphoreGive(global_threading_semaphore);
}
if (uxSemaphoreGetCount(global_threading_semaphore) == 1) {
return 1;
@ -19,22 +21,42 @@ uint8_t global_threading_available_c() {
}
}
void enable_global_threading_c() {
xSemaphoreGive(global_threading_semaphore);
}
void enable_global_threading_c() { xSemaphoreGive(global_threading_semaphore); }
void disable_global_threading_c() {
xSemaphoreTake(global_threading_semaphore, portMAX_DELAY);
}
const char *get_task_name() { return pcTaskGetName(NULL); }
const char *INVALID_TASK = "invalid task";
const char *get_task_name() {
/* this function is called from rust's panic,
* so we need to be extra sure to not cause another
* one. pcTaskGetName will trigger an assertion
* on debug builds if no task is running so we
* check if the current task is valid before using it.
* xTaskGetCurrentTaskHandle seems to be a lightweight
* way to do that */
void *task_handle = xTaskGetCurrentTaskHandle();
if (task_handle == NULL) {
return INVALID_TASK;
}
const char *name = pcTaskGetName(NULL);
if (name == NULL) {
return INVALID_TASK;
}
if (strlen(name) > configMAX_TASK_NAME_LEN) {
return INVALID_TASK;
}
return name;
}
void stop_it() { taskENTER_CRITICAL(); }
// TODO return some error code?
void *create_task(TaskFunction_t taskFunction, void *parameter,
uint32_t stack_size) {
//TODO verify uint32_t vs configSTACK_DEPTH_TYPE
// TODO verify uint32_t vs configSTACK_DEPTH_TYPE
TaskHandle_t newTask;
BaseType_t result =
xTaskCreate(taskFunction, "rust", stack_size, parameter, 4, &newTask);
@ -46,16 +68,18 @@ void *create_task(TaskFunction_t taskFunction, void *parameter,
}
void task_delay(uint32_t milliseconds) {
//TODO verify uint32_t vs TickType_t
// TODO verify uint32_t vs TickType_t
vTaskDelay(pdMS_TO_TICKS(milliseconds));
}
void delete_task(void * task){
vTaskSuspend(task); //we can not use vDeleteTask as it would free the allocated memory which is forbidden using heap1 (which we use)
void delete_task(void *task) {
vTaskSuspend(
task); // we can not use vDeleteTask as it would free the allocated memory
// which is forbidden using heap1 (which we use)
}
void *create_queue(uint32_t length, uint32_t element_size) {
//TODO verify uint32_t vs UBaseType_t
// TODO verify uint32_t vs UBaseType_t
QueueHandle_t newQueue = xQueueCreate(length, element_size);
return newQueue;
}
@ -76,11 +100,9 @@ uint8_t queue_send(void *queue, void *message) {
}
}
void *create_mutex() {
return xSemaphoreCreateRecursiveMutex();
}
void *create_mutex() { return xSemaphoreCreateRecursiveMutex(); }
uint8_t take_mutex(void * handle) {
uint8_t take_mutex(void *handle) {
// TODO check if global semaphore is free (ie, we are doing multitasking)
// if not, pointers are invalid, bail out
if (xSemaphoreTakeRecursive(handle, portMAX_DELAY) == pdPASS) {
@ -90,7 +112,7 @@ uint8_t take_mutex(void * handle) {
}
}
uint8_t give_mutex(void * handle) {
uint8_t give_mutex(void *handle) {
// TODO check if global semaphore is free (ie, we are doing multitasking)
// if not, pointers are invalid, bail out
if (xSemaphoreGiveRecursive(handle) == pdPASS) {

102
mission/mission.c Normal file
View File

@ -0,0 +1,102 @@
/* Standard includes. */
#include <limits.h>
#include <stdio.h>
/* Scheduler include files. */
#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"
void rust_main();
// called to stop execution (either a panic or program ended)
// to be implemented by bsp (do not return from it!)
void done();
void init_task(void *) {
// printf("Starting Mission\n");
rust_main();
// printf("Started Tasks, deleting init task\n");
done();
vTaskDelete(NULL);
}
void mission(void) {
int taskParameters = 0;
static const size_t stackSizeWords = 102400;
StaticTask_t xTaskBuffer;
StackType_t xStack[stackSizeWords];
xTaskCreate(init_task, /* The function that implements the task. */
"init", /* The text name assigned to the task - for debug only as
it is not used by the kernel. */
10240, /* The size of the stack to allocate to the task. */
&taskParameters, /* The parameter passed to the task - not used in
this simple case. */
4, /* The priority assigned to the task. */
NULL);
vTaskStartScheduler();
/* If all is well, the scheduler will now be running, and the following
line will never be reached. If the following line does execute, then
there was either insufficient FreeRTOS heap memory available for the idle
and/or timer tasks to be created, or vTaskStartScheduler() was called from
User mode. See the memory management section on the FreeRTOS web site for
more details on the FreeRTOS heap http://www.freertos.org/a00111.html. The
mode from which main() is called is set in the C start up code and must be
a privileged mode (not user mode). */
done();
for (;;)
;
/* Don't expect to reach here. */
return;
}
/*-----------------------------------------------------------*/
void vApplicationStackOverflowHook(TaskHandle_t pxTask, char *pcTaskName) {
(void)pcTaskName;
(void)pxTask;
/* Run time stack overflow checking is performed if
configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
function is called if a stack overflow is detected. */
taskDISABLE_INTERRUPTS();
// TODO panic
for (;;)
;
}
/*-----------------------------------------------------------*/
void rust_alloc_failed();
void vApplicationMallocFailedHook(void) {
/* Called if a call to pvPortMalloc() fails because there is insufficient
free memory available in the FreeRTOS heap. pvPortMalloc() is called
internally by FreeRTOS API functions that create tasks, queues, software
timers, and semaphores. The size of the FreeRTOS heap is set by the
configTOTAL_HEAP_SIZE configuration constant in FreeRTOSConfig.h. */
taskDISABLE_INTERRUPTS();
rust_alloc_failed();
for (;;)
;
}
void rust_assert_called(const char *pcFile, unsigned long ulLine);
void vAssertCalled(const char *pcFile, unsigned long ulLine) {
taskDISABLE_INTERRUPTS();
rust_assert_called(pcFile, ulLine);
}
/*-----------------------------------------------------------*/
/*-----------------------------------------------------------*/

View File

@ -1,5 +0,0 @@
[build]
target = "armv7a-none-eabihf"
[unstable]
build-std = ["core"]

View File

@ -1,13 +1,33 @@
#TODO can we get CMake to configure cmake --build --clean to run cargo clean?
#TODO look into corrosion cmake plugin
add_custom_target(
mission_rust_internal
COMMAND cargo build $<$<CONFIG:Release>:--release>
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
if (${CMAKE_CROSSCOMPILING})
add_library(mission_rust INTERFACE)
add_custom_target(
mission_rust_internal
COMMAND cargo build -Zbuild-std=core --target=${CMAKE_SYSTEM_PROCESSOR} $<$<CONFIG:Release>:--release>
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
add_dependencies(mission_rust mission_rust_internal)
add_library(mission_rust INTERFACE)
target_link_libraries(mission_rust INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/target/armv7a-none-eabihf/$<IF:$<CONFIG:Release>,release,debug>/libmission_rust.a)
add_dependencies(mission_rust mission_rust_internal)
target_link_libraries(mission_rust INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/target/${CMAKE_SYSTEM_PROCESSOR}/$<IF:$<CONFIG:Release>,release,debug>/libmission_rust.a)
else()
add_custom_target(
mission_rust_internal
COMMAND cargo build $<$<CONFIG:Release>:--release>
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
add_library(mission_rust INTERFACE)
add_dependencies(mission_rust mission_rust_internal)
target_link_libraries(mission_rust INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/target/$<IF:$<CONFIG:Release>,release,debug>/libmission_rust.a)
endif()

View File

@ -6,6 +6,12 @@ edition = "2021"
[lib]
crate-type = ["staticlib"]
[profile.dev]
panic = 'abort'
[profile.release]
panic = 'abort'
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@ -24,7 +24,7 @@ fn panic(panic: &PanicInfo<'_>) -> ! {
sifln!("");
sif!("in task \"");
unsafe {
//TODO is from_ptr safe enough?
//osal::get_task_name is implemented safely in C, so we trust it
let task_name = core::ffi::CStr::from_ptr(osal::get_task_name());
let task_name_utf8 = core::str::from_utf8(task_name.to_bytes());
match task_name_utf8 {
@ -62,6 +62,11 @@ extern "C" fn rust_assert_called(ptr: *const core::ffi::c_char, line: core::ffi:
panic!("assertion failed at {file_name}:{}", line);
}
#[no_mangle]
extern "C" fn rust_alloc_failed(){
panic!("allocation failed!");
}
#[no_mangle]
extern "C" fn rust_main() {
sifln!("Rust startup 🚀");