Skip to content

Commit

Permalink
Add RP2350 Arm and RISC-V ports (FreeRTOS#15)
Browse files Browse the repository at this point in the history
* RP2350: Clone RP2350_ARM_NTZ from ARM_CM33_NTZ in FreeRTOS-Kernel as of 31419bfce

* RP2350: Clone RP2350_RISC-V from GCC/RISC-V in FreeRTOS-Kernel as of 31419bfce

* Add two RP2350 ports:
RP2350_ARM_NTZ - Arm Secure-only Non-TrustZone port for RP2350
RP2350_RISC-V - RISC-V port for RP2350

* RP2350: Apply SMP debugging fix (FreeRTOS-Kernel #1174) to RP2350 ports
  • Loading branch information
kilograham authored Nov 14, 2024
1 parent 5382412 commit 8b2955f
Showing 32 changed files with 9,085 additions and 0 deletions.
2 changes: 2 additions & 0 deletions GCC/RP2350_ARM_NTZ/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
**/cmake-*
.idea
50 changes: 50 additions & 0 deletions GCC/RP2350_ARM_NTZ/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
cmake_minimum_required(VERSION 3.13)

if (NOT TARGET _FreeRTOS_kernel_inclusion_marker)
add_library(_FreeRTOS_kernel_inclusion_marker INTERFACE)

# Pull in PICO SDK (must be before project)
include(pico_sdk_import.cmake)
if (PICO_SDK_VERSION_STRING VERSION_LESS "2.0.0")
message(FATAL_ERROR "Require at least Raspberry Pi Pico SDK version 2.0.0")
endif()

if (NOT FREERTOS_KERNEL_PATH)
get_filename_component(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/../../../.. REALPATH)
endif ()

message(DEBUG "FREERTOS_KERNEL_PATH is ${FREERTOS_KERNEL_PATH}")
project(FreeRTOS-Kernel C CXX)

set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

pico_is_top_level_project(FREERTOS_KERNEL_TOP_LEVEL_PROJECT)

# if the SDK has already been initialized, then just add our libraries now - this allows
# this FreeRTOS port to just be added as a sub-directory or include within another project, rather than
# having to include it at the top level before pico_sdk_init()
if (TARGET _pico_sdk_inclusion_marker)
if (PICO_SDK_VERSION_STRING VERSION_LESS "1.3.2")
message(FATAL_ERROR "Require at least Raspberry Pi Pico SDK version 1.3.2 to include FreeRTOS after pico_sdk_init()")
endif()
include(${CMAKE_CURRENT_LIST_DIR}/library.cmake)
else()
# The real work gets done in library.cmake which is called at the end of pico_sdk_init
list(APPEND PICO_SDK_POST_LIST_FILES ${CMAKE_CURRENT_LIST_DIR}/library.cmake)
if (PICO_SDK_VERSION_STRING VERSION_LESS "1.3.2")
# We need to inject the following header file into ALL SDK files (which we do via the config header)
list(APPEND PICO_CONFIG_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/include/freertos_sdk_config.h)
endif()

if (FREERTOS_KERNEL_TOP_LEVEL_PROJECT)
message("FreeRTOS: initialize SDK since we're the top-level")
# Initialize the SDK
pico_sdk_init()
else()
set(FREERTOS_KERNEL_PATH ${FREERTOS_KERNEL_PATH} PARENT_SCOPE)
set(PICO_CONFIG_HEADER_FILES ${PICO_CONFIG_HEADER_FILES} PARENT_SCOPE)
set(PICO_SDK_POST_LIST_FILES ${PICO_SDK_POST_LIST_FILES} PARENT_SCOPE)
endif()
endif()
endif()
70 changes: 70 additions & 0 deletions GCC/RP2350_ARM_NTZ/FreeRTOS_Kernel_import.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# This is a copy of <FREERTOS_KERNEL_PATH>/portable/ThirdParty/GCC/RP2040/FREERTOS_KERNEL_import.cmake

# This can be dropped into an external project to help locate the FreeRTOS kernel
# It should be include()ed prior to project(). Alternatively this file may
# or the CMakeLists.txt in this directory may be included or added via add_subdirectory
# respectively.

if (DEFINED ENV{FREERTOS_KERNEL_PATH} AND (NOT FREERTOS_KERNEL_PATH))
set(FREERTOS_KERNEL_PATH $ENV{FREERTOS_KERNEL_PATH})
message("Using FREERTOS_KERNEL_PATH from environment ('${FREERTOS_KERNEL_PATH}')")
endif ()

if(PICO_PLATFORM STREQUAL "rp2040")
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "portable/ThirdParty/GCC/RP2040")
else()
if (PICO_PLATFORM STREQUAL "rp2350-riscv")
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "portable/ThirdParty/GCC/RP2350_RISC-V")
else()
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "portable/ThirdParty/GCC/RP2350_ARM_NTZ")
endif()
endif()

# undo the above
set(FREERTOS_KERNEL_RP2040_BACK_PATH "../../../..")

if (NOT FREERTOS_KERNEL_PATH)
# check if we are inside the FreeRTOS kernel tree (i.e. this file has been included directly)
get_filename_component(_ACTUAL_PATH ${CMAKE_CURRENT_LIST_DIR} REALPATH)
get_filename_component(_POSSIBLE_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH} REALPATH)
if (_ACTUAL_PATH STREQUAL _POSSIBLE_PATH)
get_filename_component(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH} REALPATH)
endif()
if (_ACTUAL_PATH STREQUAL _POSSIBLE_PATH)
get_filename_component(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH} REALPATH)
message("Setting FREERTOS_KERNEL_PATH to ${FREERTOS_KERNEL_PATH} based on location of FreeRTOS-Kernel-import.cmake")
elseif (PICO_SDK_PATH AND EXISTS "${PICO_SDK_PATH}/../FreeRTOS-Kernel")
set(FREERTOS_KERNEL_PATH ${PICO_SDK_PATH}/../FreeRTOS-Kernel)
message("Defaulting FREERTOS_KERNEL_PATH as sibling of PICO_SDK_PATH: ${FREERTOS_KERNEL_PATH}")
endif()
endif ()

if (NOT FREERTOS_KERNEL_PATH)
foreach(POSSIBLE_SUFFIX Source FreeRTOS-Kernel FreeRTOS/Source)
# check if FreeRTOS-Kernel exists under directory that included us
set(SEARCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
get_filename_component(_POSSIBLE_PATH ${SEARCH_ROOT}/${POSSIBLE_SUFFIX} REALPATH)
if (EXISTS ${_POSSIBLE_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/CMakeLists.txt)
get_filename_component(FREERTOS_KERNEL_PATH ${_POSSIBLE_PATH} REALPATH)
message("Setting FREERTOS_KERNEL_PATH to '${FREERTOS_KERNEL_PATH}' found relative to enclosing project")
break()
endif()
endforeach()
endif()

if (NOT FREERTOS_KERNEL_PATH)
message(FATAL_ERROR "FreeRTOS location was not specified. Please set FREERTOS_KERNEL_PATH.")
endif()

set(FREERTOS_KERNEL_PATH "${FREERTOS_KERNEL_PATH}" CACHE PATH "Path to the FreeRTOS Kernel")

get_filename_component(FREERTOS_KERNEL_PATH "${FREERTOS_KERNEL_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
if (NOT EXISTS ${FREERTOS_KERNEL_PATH})
message(FATAL_ERROR "Directory '${FREERTOS_KERNEL_PATH}' not found")
endif()
if (NOT EXISTS ${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/CMakeLists.txt)
message(FATAL_ERROR "Directory '${FREERTOS_KERNEL_PATH}' does not contain a '${PICO_PLATFORM}' port here: ${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}")
endif()
set(FREERTOS_KERNEL_PATH ${FREERTOS_KERNEL_PATH} CACHE PATH "Path to the FreeRTOS_KERNEL" FORCE)

add_subdirectory(${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH} FREERTOS_KERNEL)
23 changes: 23 additions & 0 deletions GCC/RP2350_ARM_NTZ/LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
BSD-3-Clause License

Copyright (c) 2020-2021 Raspberry Pi (Trading) Ltd.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
67 changes: 67 additions & 0 deletions GCC/RP2350_ARM_NTZ/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
## Overview

This directory provides an SMP FreeRTOS-Kernel port that can be used with the Raspberry Pi Pico SDK on RP2350. It supports:

* Simple CMake INTERFACE libraries, to provide the FreeRTOS-Kernel and also the individual allocator types, without copying code into the user's project.
* Running the FreeRTOS-Kernel and tasks on either core 0 or core 1, or both.
* Use of SDK synchronization primitives (such as mutexes, semaphores, queues from pico_sync) between FreeRTOS tasks and code executing on a non FreeRTOS core, or in IRQ handlers.

Note that whilst this SMP version can be run on just a single (either) core, it is probably
more efficient to use the non SMP version in the main FreeRTOS-Kernel branch in that case.

## Using this port

You can copy [FreeRTOS_Kernel_import.cmake](FreeRTOS_Kernel_import.cmake) into your project, and
add the following in your `CMakeLists.txt`:

```cmake
include(FreeRTOS_Kernel_import.cmake)
```

This will locate the FreeRTOS kernel if it is a direct sub-module of your project, or if you provide the
`FREERTOS_KERNEL_PATH` variable in your environment or via `-DFREERTOS_KERNEL_PATH=/path/to/FreeRTOS-Kernel` on the CMake command line.

**NOTE:** If you are using version 1.3.1 or older of the Raspberry Pi Pico SDK then this line must appear before the
`pico_sdk_init()` and will cause FreeRTOS to be included/required in all RP2040 targets in your project. After this SDK
version, you can include the FreeRTOS-Kernel support later in your CMake build (possibly in a subdirectory) and the
FreeRTOS-Kernel support will only apply to those targets which explicitly include FreeRTOS support.

As an alternative to the `import` statement above, you can just add this directory directly via thw following (with
the same placement restrictions related to the Raspberry Pi Pico SDK version above):

```cmake
add_subdirectory(path/to/this/directory FreeRTOS-Kernel)
```
## FreeRTOS configuration for Armv8-M

The following standard FreeRTOS ARM options are required for RP2350"

These three options must be specified as follows, as only RP2040-like FreeRTOS implementation only is supported currently; running in at a single privilege level in the secure statea.

```c
#define configENABLE_MPU 0
#define configENABLE_TRUSTZONE 0
#define configRUN_FREERTOS_SECURE_ONLY 1
```

You can set the following to enable save/restore of FPU state (you should set this is you are using floating point operations)

```c
#define configENABLE_FPU 1
```

As of right now this is the only value of configMAX_SYSCALL_INTERRUPT_PRIORITY that has been tested

```c
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 16
```

## Advanced Configuration

Some additional `config` options are defined [here](include/rp2040_config.h) which control some low level implementation details.

## Known Limitations

- Tickless idle has not currently been tested, and is likely non-functiona
- There is no TrustZone version
- There is no support for enabling MPU for user/handler mode within FreeRTOS
73 changes: 73 additions & 0 deletions GCC/RP2350_ARM_NTZ/library.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
#
# SPDX-License-Identifier: BSD-3-Clause

# Called after the Raspberry Pi Pico SDK has been initialized to add our libraries

add_library(FreeRTOS-Kernel-Core INTERFACE)
target_sources(FreeRTOS-Kernel-Core INTERFACE
${FREERTOS_KERNEL_PATH}/croutine.c
${FREERTOS_KERNEL_PATH}/event_groups.c
${FREERTOS_KERNEL_PATH}/list.c
${FREERTOS_KERNEL_PATH}/queue.c
${FREERTOS_KERNEL_PATH}/stream_buffer.c
${FREERTOS_KERNEL_PATH}/tasks.c
${FREERTOS_KERNEL_PATH}/timers.c
)
target_include_directories(FreeRTOS-Kernel-Core INTERFACE ${FREERTOS_KERNEL_PATH}/include)

if (PICO_SDK_VERSION_STRING VERSION_GREATER_EQUAL "1.3.2")
target_compile_definitions(FreeRTOS-Kernel-Core INTERFACE
PICO_CONFIG_RTOS_ADAPTER_HEADER=${CMAKE_CURRENT_LIST_DIR}/non_secure/freertos_sdk_config.h)
endif()

add_library(FreeRTOS-Kernel INTERFACE)
target_sources(FreeRTOS-Kernel INTERFACE
${CMAKE_CURRENT_LIST_DIR}/non_secure/port.c
${CMAKE_CURRENT_LIST_DIR}/non_secure/portasm.c
)

target_include_directories(FreeRTOS-Kernel INTERFACE
${CMAKE_CURRENT_LIST_DIR}/non_secure
${FREERTOS_CONFIG_FILE_DIRECTORY})

target_link_libraries(FreeRTOS-Kernel INTERFACE
FreeRTOS-Kernel-Core
pico_base_headers
hardware_clocks
hardware_exception
pico_multicore
)

target_compile_definitions(FreeRTOS-Kernel INTERFACE
LIB_FREERTOS_KERNEL=1
FREE_RTOS_KERNEL_SMP=1
)

add_library(FreeRTOS-Kernel-Static INTERFACE)
target_compile_definitions(FreeRTOS-Kernel-Static INTERFACE
configSUPPORT_STATIC_ALLOCATION=1
configKERNEL_PROVIDED_STATIC_MEMORY=1
)

target_link_libraries(FreeRTOS-Kernel-Static INTERFACE FreeRTOS-Kernel)

add_library(FreeRTOS-Kernel-Heap1 INTERFACE)
target_sources(FreeRTOS-Kernel-Heap1 INTERFACE ${FREERTOS_KERNEL_PATH}/portable/MemMang/heap_1.c)
target_link_libraries(FreeRTOS-Kernel-Heap1 INTERFACE FreeRTOS-Kernel)

add_library(FreeRTOS-Kernel-Heap2 INTERFACE)
target_sources(FreeRTOS-Kernel-Heap2 INTERFACE ${FREERTOS_KERNEL_PATH}/portable/MemMang/heap_2.c)
target_link_libraries(FreeRTOS-Kernel-Heap2 INTERFACE FreeRTOS-Kernel)

add_library(FreeRTOS-Kernel-Heap3 INTERFACE)
target_sources(FreeRTOS-Kernel-Heap3 INTERFACE ${FREERTOS_KERNEL_PATH}/portable/MemMang/heap_3.c)
target_link_libraries(FreeRTOS-Kernel-Heap3 INTERFACE FreeRTOS-Kernel)

add_library(FreeRTOS-Kernel-Heap4 INTERFACE)
target_sources(FreeRTOS-Kernel-Heap4 INTERFACE ${FREERTOS_KERNEL_PATH}/portable/MemMang/heap_4.c)
target_link_libraries(FreeRTOS-Kernel-Heap4 INTERFACE FreeRTOS-Kernel)

add_library(FreeRTOS-Kernel-Heap5 INTERFACE)
target_sources(FreeRTOS-Kernel-Heap5 INTERFACE ${FREERTOS_KERNEL_PATH}/portable/MemMang/heap_5.c)
target_link_libraries(FreeRTOS-Kernel-Heap5 INTERFACE FreeRTOS-Kernel)
77 changes: 77 additions & 0 deletions GCC/RP2350_ARM_NTZ/non_secure/freertos_sdk_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*
* 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_SDK_CONFIG_H
#define FREERTOS_SDK_CONFIG_H

#ifndef __ASSEMBLER__
#include "FreeRTOSConfig.h"
#include "rp2040_config.h"
#ifndef PICO_USE_MALLOC_MUTEX
/* malloc needs to be made thread safe */
#define PICO_USE_MALLOC_MUTEX 1
#endif /* PICO_USE_MALLOC_MUTEX */
#if ( configSUPPORT_PICO_SYNC_INTEROP == 1 )
/* increase the amount of time it may reasonably take to wake us up */
#ifndef PICO_TIME_SLEEP_OVERHEAD_ADJUST_US
#define PICO_TIME_SLEEP_OVERHEAD_ADJUST_US 150
#endif

#define lock_owner_id_t uint32_t
extern uint32_t ulPortLockGetCurrentOwnerId( void );
#define lock_get_caller_owner_id() ulPortLockGetCurrentOwnerId()
#define LOCK_INVALID_OWNER_ID ( ( uint32_t ) -1 )

struct lock_core;
#ifndef lock_internal_spin_unlock_with_wait
extern void vPortLockInternalSpinUnlockWithWait( struct lock_core * pxLock,
uint32_t ulSave );
#define lock_internal_spin_unlock_with_wait( lock, save ) vPortLockInternalSpinUnlockWithWait( lock, save )
#endif

#ifndef lock_internal_spin_unlock_with_notify
extern void vPortLockInternalSpinUnlockWithNotify( struct lock_core * pxLock,
uint32_t save );
#define lock_internal_spin_unlock_with_notify( lock, save ) vPortLockInternalSpinUnlockWithNotify( lock, save );
#endif

#ifndef lock_internal_spin_unlock_with_best_effort_wait_or_timeout
extern bool xPortLockInternalSpinUnlockWithBestEffortWaitOrTimeout( struct lock_core * pxLock,
uint32_t ulSave,
absolute_time_t uxUntil );
#define lock_internal_spin_unlock_with_best_effort_wait_or_timeout( lock, save, until ) \
xPortLockInternalSpinUnlockWithBestEffortWaitOrTimeout( lock, save, until )
#endif
#endif /* configSUPPORT_PICO_SYNC_INTEROP */

#if ( configSUPPORT_PICO_TIME_INTEROP == 1 )
extern void xPortSyncInternalYieldUntilBefore( absolute_time_t t );
#define sync_internal_yield_until_before( t ) xPortSyncInternalYieldUntilBefore( t )
#endif /* configSUPPORT_PICO_TIME_INTEROP */
#endif /* __ASSEMBLER__ */
#endif /* ifndef FREERTOS_SDK_CONFIG_H */
Loading

0 comments on commit 8b2955f

Please sign in to comment.