├── .github └── workflows │ └── c-cpp.yml ├── .gitignore ├── .gitmodules ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── 0_base ├── CMakeLists.txt ├── FreeRTOSConfig.h ├── Instructions.url ├── LICENSE ├── README.md ├── demo_hw.c ├── demo_hw.h ├── main.c ├── misc │ ├── CMSIS │ │ ├── CMSDK_CM3.h │ │ ├── CMakeLists.txt │ │ ├── SMM_MPS2.h │ │ ├── cmsis.h │ │ ├── cmsis_compiler.h │ │ ├── cmsis_gcc.h │ │ ├── cmsis_iccarm.h │ │ ├── cmsis_version.h │ │ ├── core_cm3.h │ │ └── mpu_armv7.h │ ├── CMakeLists.txt │ ├── IntQueueTimer.c │ ├── IntQueueTimer.h │ ├── RegTest.c │ ├── Snapshot-Trace │ │ ├── .gitattributes │ │ ├── CMakeLists.txt │ │ ├── Doxyfile │ │ ├── Kconfig │ │ ├── LICENSE.md │ │ ├── LICENSE.spdx │ │ ├── README.md │ │ ├── config │ │ │ ├── Kconfig │ │ │ ├── trcConfig.h │ │ │ ├── trcSnapshotConfig.h │ │ │ └── trcStreamingConfig.h │ │ ├── include │ │ │ ├── trcAssert.h │ │ │ ├── trcCounter.h │ │ │ ├── trcDefines.h │ │ │ ├── trcDependency.h │ │ │ ├── trcDiagnostics.h │ │ │ ├── trcEntryTable.h │ │ │ ├── trcError.h │ │ │ ├── trcEvent.h │ │ │ ├── trcEventBuffer.h │ │ │ ├── trcExtension.h │ │ │ ├── trcHardwarePort.h │ │ │ ├── trcHeap.h │ │ │ ├── trcISR.h │ │ │ ├── trcInternalEventBuffer.h │ │ │ ├── trcInterval.h │ │ │ ├── trcMultiCoreEventBuffer.h │ │ │ ├── trcObject.h │ │ │ ├── trcPrint.h │ │ │ ├── trcRecorder.h │ │ │ ├── trcRunnable.h │ │ │ ├── trcStackMonitor.h │ │ │ ├── trcStateMachine.h │ │ │ ├── trcStaticBuffer.h │ │ │ ├── trcString.h │ │ │ ├── trcTask.h │ │ │ ├── trcTimestamp.h │ │ │ ├── trcTypes.h │ │ │ └── trcUtility.h │ │ ├── kernelports │ │ │ └── FreeRTOS │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── config │ │ │ │ ├── Kconfig │ │ │ │ ├── trcKernelPortConfig.h │ │ │ │ ├── trcKernelPortSnapshotConfig.h │ │ │ │ └── trcKernelPortStreamingConfig.h │ │ │ │ ├── include │ │ │ │ └── trcKernelPort.h │ │ │ │ └── trcKernelPort.c │ │ ├── streamports │ │ │ └── RingBuffer │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── Kconfig │ │ │ │ ├── Readme-Streamport.txt │ │ │ │ ├── config │ │ │ │ └── trcStreamPortConfig.h │ │ │ │ ├── include │ │ │ │ └── trcStreamPort.h │ │ │ │ └── trcStreamPort.c │ │ ├── trcAssert.c │ │ ├── trcCounter.c │ │ ├── trcDependency.c │ │ ├── trcDiagnostics.c │ │ ├── trcEntryTable.c │ │ ├── trcError.c │ │ ├── trcEvent.c │ │ ├── trcEventBuffer.c │ │ ├── trcExtension.c │ │ ├── trcHardwarePort.c │ │ ├── trcHeap.c │ │ ├── trcISR.c │ │ ├── trcInternalEventBuffer.c │ │ ├── trcInterval.c │ │ ├── trcMultiCoreEventBuffer.c │ │ ├── trcObject.c │ │ ├── trcPrint.c │ │ ├── trcRunnable.c │ │ ├── trcSnapshotRecorder.c │ │ ├── trcStackMonitor.c │ │ ├── trcStateMachine.c │ │ ├── trcStaticBuffer.c │ │ ├── trcStreamingRecorder.c │ │ ├── trcString.c │ │ ├── trcTask.c │ │ └── trcTimestamp.c │ ├── cmake │ │ ├── arm.cmake │ │ ├── common_demo.cmake │ │ ├── freertos.cmake │ │ └── log.cmake │ ├── mps2_m3.ld │ ├── printf-stdarg.c │ └── startup_gcc.c ├── ringbuffer.c └── ringbuffer.h ├── 10_deadlock_starvation ├── .vscode │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── 0_base ├── CMakeLists.txt ├── README.md ├── demo_chair.c ├── demo_deadlock.c ├── demo_livelock.c ├── demo_stick_prio.c └── doc │ └── HungerProblem.png ├── 10_deadlock_starvation_challenge ├── .vscode │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── 0_base ├── CMakeLists.txt ├── README.md └── demo.c ├── 11_priority_inversion ├── .vscode │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── 0_base ├── CMakeLists.txt ├── README.md ├── demo_inheritance.c └── demo_unbounded.c ├── 11_priority_inversion_challenge ├── .vscode │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── 0_base ├── CMakeLists.txt ├── README.md └── demo.c ├── 2_blinky ├── .vscode │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── 0_base ├── CMakeLists.txt ├── README.md └── demo.c ├── 3_task_scheduling ├── .vscode │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── 0_base ├── CMakeLists.txt ├── README.md ├── demo.c └── doc │ └── taskPreemption.png ├── 3_task_scheduling_challenge ├── .vscode │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── 0_base ├── CMakeLists.txt ├── README.md ├── demo.c └── doc │ └── userInputLedDelay.png ├── 4_memory ├── .vscode │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── 0_base ├── CMakeLists.txt ├── README.md ├── demo1.c ├── demo2.c ├── demo3.c ├── demo4.c ├── demo5.c └── demo6.c ├── 4_memory_challenge ├── .vscode │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── 0_base ├── CMakeLists.txt ├── README.md ├── demo.c └── doc │ └── challenge.png ├── 5_queue ├── .vscode │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── 0_base ├── CMakeLists.txt ├── README.md └── demo.c ├── 5_queue_challenge ├── .vscode │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── 0_base ├── CMakeLists.txt ├── README.md ├── demo.c └── doc │ └── challenge.png ├── 6_mutex ├── .vscode │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── 0_base ├── CMakeLists.txt ├── README.md ├── demo_mutex.c └── demo_race.c ├── 6_mutex_challenge ├── .vscode │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── 0_base ├── CMakeLists.txt ├── README.md └── demo.c ├── 7_semaphore ├── .vscode │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── 0_base ├── CMakeLists.txt ├── README.md └── demo.c ├── 7_semaphore_challenge ├── .vscode │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── 0_base ├── CMakeLists.txt ├── README.md ├── demo.c └── doc │ ├── challenge.png │ └── trace.png ├── 8_sw_timers ├── .vscode │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── 0_base ├── CMakeLists.txt ├── README.md └── demo.c ├── 8_sw_timers_challenge ├── .vscode │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── 0_base ├── CMakeLists.txt ├── README.md └── demo.c ├── 9_hw_int ├── .vscode │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── 0_base ├── CMakeLists.txt ├── README.md ├── demo_adc.c ├── demo_notify.c ├── demo_tm.c └── doc │ └── adcTrace.png ├── 9_hw_int_challenge ├── .vscode │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── 0_base ├── CMakeLists.txt ├── README.md ├── demo.c ├── demo.h ├── demo_init.c └── demo_init.h ├── README.md ├── configure.sh └── shell ├── build.sh ├── preprocess.sh ├── rebuild.sh ├── rebuild_all.sh ├── rebuild_run_qemu.sh ├── run_qemu.sh ├── screen_hw.sh └── util.sh /.github/workflows/c-cpp.yml: -------------------------------------------------------------------------------- 1 | name: C/C++ CI 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | - uses: carlosperate/arm-none-eabi-gcc-action@v1.10.0 17 | with: 18 | # GNU Embedded Toolchain for Arm release name (e.g. "10.3-2021.07"). 19 | release: "10.3-2021.10" 20 | # Name for an environmental variable to be created with the toolchain path. 21 | path-env-var: "GCC_ARM_NONE_EABI_BIN_PATH" 22 | - name: submodule_update 23 | run: git submodule update --init --recursive 24 | - name: build_all 25 | run: ./shell/rebuild_all.sh 26 | 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 0_original/build/gcc/output 2 | build/ 3 | *.bin -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "0_base/misc/FreeRTOS"] 2 | path = 0_base/misc/FreeRTOS 3 | url = https://github.com/FreeRTOS/FreeRTOS/ 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "uart.h": "c", 4 | "stdio.h": "c", 5 | "freertos.h": "c", 6 | "demo.h": "c", 7 | "stdint.h": "c", 8 | "task.h": "c", 9 | "demo_hw.h": "c", 10 | "stdarg.h": "c", 11 | "ringbuffer.h": "c" 12 | } 13 | } -------------------------------------------------------------------------------- /0_base/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/misc") 2 | 3 | # Add all source files in the current directory 4 | file(GLOB base_src "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 5 | 6 | set(src ${src} ${base_src} PARENT_SCOPE) 7 | set(inc ${inc} ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE) -------------------------------------------------------------------------------- /0_base/Instructions.url: -------------------------------------------------------------------------------- 1 | [{000214A0-0000-0000-C000-000000000046}] 2 | Prop3=19,11 3 | [InternetShortcut] 4 | IDList= 5 | URL=https://www.freertos.org/freertos-on-qemu-mps2-an385-model.html 6 | -------------------------------------------------------------------------------- /0_base/LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /0_base/README.md: -------------------------------------------------------------------------------- 1 | # 0_base 2 | 3 | Not compilable by itself. It is base for other applications. -------------------------------------------------------------------------------- /0_base/demo_hw.h: -------------------------------------------------------------------------------- 1 | // this file abstracts hw needed by demos 2 | 3 | #ifndef DEMO_HW 4 | #define DEMO_HW 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | /** 11 | * @brief printf 12 | * @warning expanded string should not be longer 99 13 | */ 14 | void demo_hw_term_printf(const char *format, ...); 15 | 16 | /** 17 | * @brief write a byte to terminal 18 | */ 19 | void demo_hw_term_writeChar(char c); 20 | 21 | /** 22 | * @brief writes null terminated buffer to stdout of your terminal 23 | */ 24 | void demo_hw_term_write(const char *const buf); 25 | 26 | /** 27 | * @brief writes null terminated buffer with newline to stdout of your terminal 28 | */ 29 | void demo_hw_term_writeLine(const char *const buf); 30 | 31 | /** 32 | * @brief read byte from stdin of your terminal 33 | * @retval 0: not read 34 | * @retval 1: read 35 | */ 36 | uint8_t demo_hw_term_readCharNonBlock(char *c); 37 | 38 | /** 39 | * @brief read from stdin of your terminal 40 | * @retval 0: if no character has been read 41 | * @retval n: number of characters read 42 | */ 43 | uint8_t demo_hw_term_readNonBlock(char *buf, uint8_t len); 44 | 45 | /** 46 | * @brief read from stdin of your terminal until buffer is full 47 | * @retval none 48 | */ 49 | void demo_hw_term_read(char *buf, uint8_t len); 50 | 51 | /** 52 | * @brief reads stdin of your terminal until new line entered 53 | * @arg buf[out]: null terminated string 54 | * @arg len : length of buf 55 | * @retval -1: it did not fit into buf 56 | * @retval n: number of characters read 57 | */ 58 | 59 | int16_t demo_hw_term_readLine(char *buf, uint8_t len); 60 | 61 | /** 62 | * @brief gets the state of the led 63 | * @retval 1: led is on 64 | * @retval 0: led is off 65 | */ 66 | uint8_t demo_hw_led_get(void); 67 | 68 | /** 69 | * @brief sets the state of the led 70 | * @arg st == 0: off 71 | * @arg st != 0: on 72 | */ 73 | void demo_hw_led_set(uint8_t st); 74 | 75 | /** 76 | * @brief toggle led 77 | */ 78 | void demo_hw_led_toggle(void); 79 | 80 | /** 81 | * @brief just returns some number. 82 | * actual value of adc is not important for the demo. 83 | */ 84 | uint8_t demo_hw_adc_read(void); 85 | 86 | /** 87 | * @brief get system on time in milliseconds 88 | * @warning this function will ovf after UINT32_MAX / (configCPU_CLOCK_HZ/CMSDK_DUALTIMER1_PRESCALE) seconds 89 | * CMSDK_DUALTIMER1 reserved as system on timer 90 | */ 91 | uint32_t demo_hw_getSysOnTimeMs(void); 92 | 93 | #endif // DEMO_HW -------------------------------------------------------------------------------- /0_base/misc/CMSIS/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(inc ${inc} "${CMAKE_CURRENT_SOURCE_DIR}" PARENT_SCOPE) -------------------------------------------------------------------------------- /0_base/misc/CMSIS/cmsis.h: -------------------------------------------------------------------------------- 1 | /* MPS2 CMSIS Library 2 | * 3 | * Copyright (c) 2006-2016 ARM Limited 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 17 | * 3. Neither the name of the copyright holder nor the names of its contributors 18 | * may be used to endorse or promote products derived from this software without 19 | * specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 25 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | * POSSIBILITY OF SUCH DAMAGE. 32 | ******************************************************************************* 33 | * A generic CMSIS include header, pulling in MPS2 specifics 34 | *******************************************************************************/ 35 | 36 | #ifndef MBED_CMSIS_H 37 | #define MBED_CMSIS_H 38 | 39 | #include "SMM_MPS2.h" 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /0_base/misc/CMSIS/cmsis_version.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file cmsis_version.h 3 | * @brief CMSIS Core(M) Version definitions 4 | * @version V5.0.4 5 | * @date 23. July 2019 6 | ******************************************************************************/ 7 | /* 8 | * Copyright (c) 2009-2019 ARM Limited. All rights reserved. 9 | * 10 | * SPDX-License-Identifier: Apache-2.0 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the License); you may 13 | * not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 20 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | 25 | #if defined ( __ICCARM__ ) 26 | #pragma system_include /* treat file as system include file for MISRA check */ 27 | #elif defined (__clang__) 28 | #pragma clang system_header /* treat file as system include file */ 29 | #endif 30 | 31 | #ifndef __CMSIS_VERSION_H 32 | #define __CMSIS_VERSION_H 33 | 34 | /* CMSIS Version definitions */ 35 | #define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */ 36 | #define __CM_CMSIS_VERSION_SUB ( 4U) /*!< [15:0] CMSIS Core(M) sub version */ 37 | #define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \ 38 | __CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */ 39 | #endif 40 | -------------------------------------------------------------------------------- /0_base/misc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(CMSIS) 2 | add_subdirectory(Snapshot-Trace) 3 | 4 | file(GLOB misc_src "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 5 | 6 | set(src ${src} ${misc_src} PARENT_SCOPE) 7 | set(inc ${inc} ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE) -------------------------------------------------------------------------------- /0_base/misc/IntQueueTimer.c: -------------------------------------------------------------------------------- 1 | void vInitialiseTimerForIntQueueTest( void ) { 2 | // dummy 3 | } 4 | 5 | __attribute__((weak)) void TIMER0_Handler( void ) 6 | { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /0_base/misc/IntQueueTimer.h: -------------------------------------------------------------------------------- 1 | #ifndef INTQUEUETIMER_H 2 | #define INTQUEUETIMER_H 3 | void vInitialiseTimerForIntQueueTest( void ); 4 | #endif //INTQUEUETIMER_H -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(streamports/RingBuffer) 2 | add_subdirectory(kernelports/FreeRTOS) 3 | 4 | file(GLOB snapshot_trace_src "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 5 | 6 | set(src 7 | ${src} 8 | ${snapshot_trace_src} 9 | PARENT_SCOPE) 10 | set(inc 11 | ${inc} 12 | "${CMAKE_CURRENT_SOURCE_DIR}/include" 13 | "${CMAKE_CURRENT_SOURCE_DIR}/config" 14 | PARENT_SCOPE 15 | ) -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/Kconfig: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 Percepio AB 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | menu "Trace Recorder" 5 | choice PERCEPIO_TRC_CFG_RECORDER_RTOS 6 | prompt "Recorder RTOS" 7 | default PERCEPIO_TRC_CFG_RECORDER_RTOS_FREERTOS 8 | 9 | config PERCEPIO_TRC_CFG_RECORDER_RTOS_FREERTOS 10 | bool "FreeRTOS" 11 | 12 | config PERCEPIO_TRC_CFG_RECORDER_RTOS_THREADX 13 | bool "ThreadX" 14 | 15 | config PERCEPIO_TRC_CFG_RECORDER_RTOS_ZEPHYR 16 | bool "Zephyr" 17 | endchoice 18 | 19 | if PERCEPIO_TRC_CFG_RECORDER_RTOS_FREERTOS 20 | rsource "kernelports/FreeRTOS/config/Kconfig" 21 | endif # PERCEPIO_TRC_CFG_RECORDER_RTOS_FREERTOS 22 | 23 | if PERCEPIO_TRC_CFG_RECORDER_RTOS_THREADX 24 | rsource "kernelports/ThreadX/config/Kconfig" 25 | endif # PERCEPIO_TRC_CFG_RECORDER_RTOS_THREADX 26 | 27 | if PERCEPIO_TRC_CFG_RECORDER_RTOS_ZEPHYR 28 | rsource "kernelports/Zephyr/config/Kconfig" 29 | endif # PERCEPIO_TRC_CFG_RECORDER_RTOS_ZEPHYR 30 | endmenu # "Trace Recorder" 31 | -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/LICENSE.spdx: -------------------------------------------------------------------------------- 1 | SPDXVersion: SPDX-2.2 2 | DataLicense: CC0-1.0 3 | Creator: Organization: Percepio AB () 4 | PackageName: TraceRecorderSource 5 | PackageOriginator: Percepio AB 6 | PackageDownloadLocation: git+https://github.com/percepio/TraceRecorderSource.git 7 | PackageLicenseDeclared: Apache-2.0 8 | PackageCopyrightText: Copyright 2023 Percepio AB 9 | PackageSummary: Trace Recorder 10 | PackageDescription: A generic software Trace Recorder that can generate trace events and transmit or store them. -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/README.md: -------------------------------------------------------------------------------- 1 | [Trace Recorder source code for use with Percepio's Tracealyzer.](./FreeRTOS/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace) 2 | 3 | Read more at https://percepio.com/tracealyzer/ and https://percepio.com/gettingstarted. 4 | 5 | Repository at https://github.com/percepio/TraceRecorderSource 6 | -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/config/trcStreamingConfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Trace Recorder for Tracealyzer v4.8.0.hotfix1 3 | * Copyright 2023 Percepio AB 4 | * www.percepio.com 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | * 8 | * Configuration parameters for the trace recorder library in streaming mode. 9 | * Read more at http://percepio.com/2016/10/05/rtos-tracing/ 10 | */ 11 | 12 | #ifndef TRC_STREAMING_CONFIG_H 13 | #define TRC_STREAMING_CONFIG_H 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | /** 20 | * @def TRC_CFG_ENTRY_SLOTS 21 | * @brief The maximum number of objects and symbols that can be stored. This includes: 22 | * - Task names 23 | * - Named ISRs (vTraceSetISRProperties) 24 | * - Named kernel objects (vTraceStoreKernelObjectName) 25 | * - User event channels (xTraceStringRegister) 26 | * 27 | * If this value is too small, not all symbol names will be stored and the 28 | * trace display will be affected. In that case, there will be warnings 29 | * (as User Events) from TzCtrl task, that monitors this. 30 | */ 31 | #define TRC_CFG_ENTRY_SLOTS 50 32 | 33 | /** 34 | * @def TRC_CFG_ENTRY_SYMBOL_MAX_LENGTH 35 | * @brief The maximum length of symbol names, including: 36 | * - Task names 37 | * - Named ISRs (vTraceSetISRProperties) 38 | * - Named kernel objects (vTraceStoreKernelObjectName) 39 | * - User event channel names (xTraceStringRegister) 40 | * 41 | * If longer symbol names are used, they will be truncated by the recorder, 42 | * which will affect the trace display. In that case, there will be warnings 43 | * (as User Events) from TzCtrl task, that monitors this. 44 | */ 45 | #define TRC_CFG_ENTRY_SYMBOL_MAX_LENGTH 28 46 | 47 | #ifdef __cplusplus 48 | } 49 | #endif 50 | 51 | #endif /* TRC_STREAMING_CONFIG_H */ 52 | -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/include/trcDependency.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Percepio Trace Recorder for Tracealyzer v4.8.0.hotfix1 3 | * Copyright 2023 Percepio AB 4 | * www.percepio.com 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | */ 8 | 9 | /** 10 | * @file 11 | * 12 | * @brief Public trace dependency APIs. 13 | */ 14 | 15 | #ifndef TRC_DEPENDENCY_H 16 | #define TRC_DEPENDENCY_H 17 | 18 | #if (TRC_USE_TRACEALYZER_RECORDER == 1) 19 | 20 | #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) 21 | 22 | #include 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /** 29 | * @defgroup trace_dependency_apis Trace Dependency APIs 30 | * @ingroup trace_recorder_apis 31 | * @{ 32 | */ 33 | 34 | /** 35 | * @brief Registers a dependency. 36 | * 37 | * @param[in] szName Name. 38 | * @param[in] uxDependencyType The type of dependency. 39 | * TRC_DEPENDENCY_TYPE_ELF: .elf file. Currently the only supported type. 40 | * 41 | * @retval TRC_FAIL Failure 42 | * @retval TRC_SUCCESS Success 43 | */ 44 | traceResult xTraceDependencyRegister(const char* szName, TraceUnsignedBaseType_t uxDependencyType); 45 | 46 | /** @} */ 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #else 53 | 54 | #ifndef xTraceDependencyRegister 55 | #define xTraceDependencyRegister(szName, uxDependencyType) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_4((void)(szName), (void)(uxRegisterMethod), (void)(pxRunnableHandle), TRC_SUCCESS) 56 | #endif 57 | 58 | #endif 59 | 60 | #endif 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/include/trcError.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Percepio Trace Recorder for Tracealyzer v4.8.0.hotfix1 3 | * Copyright 2023 Percepio AB 4 | * www.percepio.com 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | */ 8 | 9 | /** 10 | * @file 11 | * 12 | * @brief Public trace error APIs. 13 | */ 14 | 15 | #ifndef TRC_ERROR_H 16 | #define TRC_ERROR_H 17 | 18 | #if (TRC_USE_TRACEALYZER_RECORDER == 1) 19 | 20 | #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) 21 | 22 | #include 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /** 29 | * @defgroup trace_assert_apis Trace Asserts APIs 30 | * @ingroup trace_recorder_apis 31 | * @{ 32 | */ 33 | 34 | typedef struct TraceErrorData /* Aligned */ 35 | { 36 | uint32_t uiErrorAndWarningFlags; 37 | uint32_t uiErrorCode; 38 | TraceStringHandle_t xWarningChannel; 39 | } TraceErrorData_t; 40 | 41 | /** 42 | * @internal Initializes the error system 43 | * 44 | * @param[in] pxBuffer Pointer to buffer 45 | * 46 | * @retval TRC_FAIL Failure 47 | * @retval TRC_SUCCESS Success 48 | */ 49 | traceResult xTraceErrorInitialize(TraceErrorData_t* pxBuffer); 50 | 51 | /** 52 | * @brief Register a warning 53 | * 54 | * @param[in] uiErrorCode Label 55 | * 56 | * @retval TRC_FAIL Failure 57 | * @retval TRC_SUCCESS Success 58 | */ 59 | traceResult xTraceWarning(uint32_t uiErrorCode); 60 | 61 | /** 62 | * @brief Register an error 63 | * 64 | * @param[in] uiErrorCode Error code 65 | * 66 | * @retval TRC_FAIL Failure 67 | * @retval TRC_SUCCESS Success 68 | */ 69 | traceResult xTraceError(uint32_t uiErrorCode); 70 | 71 | /** 72 | * @brief Retrieve the string for the last error 73 | * 74 | * @param[out] pszError Error string pointer 75 | * 76 | * @retval TRC_FAIL Failure 77 | * @retval TRC_SUCCESS Success 78 | */ 79 | traceResult xTraceErrorGetLast(const char** pszError); 80 | 81 | /** 82 | * @brief Clears any errors 83 | * 84 | * @retval TRC_FAIL Failure 85 | * @retval TRC_SUCCESS Success 86 | */ 87 | traceResult xTraceErrorClear(void); 88 | 89 | /** @} */ 90 | 91 | #ifdef __cplusplus 92 | } 93 | #endif 94 | 95 | #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ 96 | 97 | #endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ 98 | 99 | #endif /* TRC_ERROR_H*/ 100 | -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/include/trcExtension.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Percepio Trace Recorder for Tracealyzer v4.8.0.hotfix1 3 | * Copyright 2023 Percepio AB 4 | * www.percepio.com 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | */ 8 | 9 | /** 10 | * @file 11 | * 12 | * @brief Public trace extension APIs. 13 | */ 14 | 15 | #ifndef TRC_EXTENSION_H 16 | #define TRC_EXTENSION_H 17 | 18 | #if (TRC_USE_TRACEALYZER_RECORDER == 1) 19 | 20 | #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) 21 | 22 | #include 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | #define TRC_EXTENSION_STATE_INDEX_VERSION 0 29 | #define TRC_EXTENSION_STATE_INDEX_BASE_EVENT_ID 1 30 | #define TRC_EXTENSION_STATE_INDEX_EVENT_COUNT 2 31 | 32 | /** 33 | * @defgroup trace_extension_apis Trace Extension APIs 34 | * @ingroup trace_recorder_apis 35 | * @{ 36 | */ 37 | 38 | typedef struct TraceExtensionData /* Aligned */ 39 | { 40 | TraceUnsignedBaseType_t uxNextFreeExtensionEventId; 41 | } TraceExtensionData_t; 42 | 43 | /** 44 | * @brief Initializes the Extension trace system 45 | * 46 | * @param[in] pxBuffer Pointer to memory that is used by the extension trace system 47 | * 48 | * @retval TRC_FAIL Failure 49 | * @retval TRC_SUCCESS Success 50 | */ 51 | traceResult xTraceExtensionInitialize(TraceExtensionData_t* const pxBuffer); 52 | 53 | /** 54 | * @brief Creates trace extension. 55 | * 56 | * @param[in] szName Name. 57 | * @param[in] uiMajor Major version. 58 | * @param[in] uiMinor Minor version. 59 | * @param[in] uiPatch Patch version. 60 | * @param[in] uiEventCount Event count. 61 | * @param[out] pxExtensionHandle Pointer to uninitialized extension handle. 62 | * 63 | * @retval TRC_FAIL Failure 64 | * @retval TRC_SUCCESS Success 65 | */ 66 | traceResult xTraceExtensionCreate(const char *szName, uint8_t uiMajor, uint8_t uiMinor, uint16_t uiPatch, uint32_t uiEventCount, TraceExtensionHandle_t *pxExtensionHandle); 67 | 68 | /** 69 | * @brief Gets extension base event id. 70 | * 71 | * @param[in] xExtensionHandle Pointer to initialized extension handle. 72 | * @param[out] puiBaseEventId Base event id. 73 | * 74 | * @retval TRC_FAIL Failure 75 | * @retval TRC_SUCCESS Success 76 | */ 77 | traceResult xTraceExtensionGetBaseEventId(TraceExtensionHandle_t xExtensionHandle, uint32_t *puiBaseEventId); 78 | 79 | /** 80 | * @brief Gets extension configuration name. 81 | * 82 | * @param[in] xExtensionHandle Pointer to initialized extension handle. 83 | * @param[out] pszName Name. 84 | * 85 | * @retval TRC_FAIL Failure 86 | * @retval TRC_SUCCESS Success 87 | */ 88 | traceResult xTraceExtensionGetConfigName(TraceExtensionHandle_t xExtensionHandle, const char** pszName); 89 | 90 | /** 91 | * @brief Returns extension event id. 92 | * 93 | * @param[in] xExtensionHandle Pointer to initialized extension handle. 94 | * @param[in] uiLocalEventId Local event id. 95 | * 96 | * @returns Extension event id 97 | */ 98 | #define xTraceExtensionGetEventId(xExtensionHandle, uiLocalEventId) ((uint32_t)xTraceEntryGetStateReturn((TraceEntryHandle_t)(xExtensionHandle), TRC_EXTENSION_STATE_INDEX_BASE_EVENT_ID) + (uiLocalEventId)) 99 | 100 | /** @} */ 101 | 102 | #ifdef __cplusplus 103 | } 104 | #endif 105 | 106 | #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ 107 | 108 | #endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ 109 | 110 | #endif /* TRC_EXTENSION_H */ 111 | -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/include/trcStateMachine.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Percepio Trace Recorder for Tracealyzer v4.8.0.hotfix1 3 | * Copyright 2023 Percepio AB 4 | * www.percepio.com 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | */ 8 | 9 | /** 10 | * @file 11 | * 12 | * @brief Public trace state machine APIs. 13 | */ 14 | 15 | #ifndef TRC_STATE_MACHINE_H 16 | #define TRC_STATE_MACHINE_H 17 | 18 | #include 19 | 20 | #if (TRC_USE_TRACEALYZER_RECORDER == 1) 21 | 22 | #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /** 29 | * @defgroup trace_state_machine_apis Trace State Machine APIs 30 | * @ingroup trace_recorder_apis 31 | * @{ 32 | */ 33 | 34 | /** 35 | * @brief Creates trace state machine. 36 | * 37 | * @param[in] szName Name. 38 | * @param[out] pxStateMachineHandle Pointer to uninitialized trace state machine. 39 | * 40 | * @retval TRC_FAIL Failure 41 | * @retval TRC_SUCCESS Success 42 | */ 43 | traceResult xTraceStateMachineCreate(const char *szName, TraceStateMachineHandle_t *pxStateMachineHandle); 44 | 45 | /** 46 | * @brief Creates trace state machine state. 47 | * 48 | * @param[in] xStateMachineHandle Pointer to initialized trace state machine. 49 | * @param[in] szName Name. 50 | * @param[out] pxStateHandle Pointer to uninitialized trace state machine state. 51 | * 52 | * @retval TRC_FAIL Failure 53 | * @retval TRC_SUCCESS Success 54 | */ 55 | traceResult xTraceStateMachineStateCreate(TraceStateMachineHandle_t xStateMachineHandle, const char *szName, TraceStateMachineStateHandle_t *pxStateHandle); 56 | 57 | /** 58 | * @brief Sets trace state machine state. 59 | * 60 | * @param[in] xStateMachineHandle Pointer to initialized trace state machine. 61 | * @param[in] xStateHandle Pointer to initialized trace state machine state. 62 | * 63 | * @retval TRC_FAIL Failure 64 | * @retval TRC_SUCCESS Success 65 | */ 66 | traceResult xTraceStateMachineSetState(TraceStateMachineHandle_t xStateMachineHandle, TraceStateMachineStateHandle_t xStateHandle); 67 | 68 | /** @} */ 69 | 70 | #ifdef __cplusplus 71 | } 72 | #endif 73 | 74 | #else 75 | 76 | /** 77 | * @brief Disabled by TRC_CFG_RECORDER_MODE 78 | */ 79 | #define xTraceStateMachineCreate(__szName, __pxStateMachineHandle) ((void)(__szName), *(__pxStateMachineHandle) = 0, TRC_SUCCESS) 80 | 81 | /** 82 | * @brief Disabled by TRC_CFG_RECORDER_MODE 83 | */ 84 | #define xTraceStateMachineStateCreate(__xStateMachineHandle, __szName, __pxStateHandle) ((void)(__xStateMachineHandle), (void)(__szName), *(__pxStateHandle) = 0, TRC_SUCCESS) 85 | 86 | /** 87 | * @brief Disabled by TRC_CFG_RECORDER_MODE 88 | */ 89 | #define xTraceStateMachineSetState(__xStateMachineHandle, __xStateHandle) ((void)(__xStateMachineHandle), (void)(__xStateHandle), TRC_SUCCESS) 90 | 91 | #endif 92 | 93 | #endif 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/include/trcStaticBuffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Percepio Trace Recorder for Tracealyzer v4.8.0.hotfix1 3 | * Copyright 2023 Percepio AB 4 | * www.percepio.com 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | */ 8 | 9 | /** 10 | * @file 11 | * 12 | * @brief Public trace static buffer APIs. 13 | */ 14 | 15 | #ifndef TRC_STATIC_BUFFER_H 16 | #define TRC_STATIC_BUFFER_H 17 | 18 | #if (TRC_USE_TRACEALYZER_RECORDER == 1) 19 | 20 | #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) 21 | 22 | #include 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /** 29 | * @defgroup trace_static_buffer_apis Trace Static Buffer APIs 30 | * @ingroup trace_recorder_apis 31 | * @{ 32 | */ 33 | 34 | /* A buffer type that is maximum size */ 35 | typedef uint8_t TraceStaticBuffer_t[TRC_MAX_BLOB_SIZE]; 36 | 37 | /** 38 | * @internal Trace Core Static Buffer Core Structure 39 | */ 40 | typedef struct TraceCoreStaticBufferCore /* Aligned */ 41 | { 42 | TraceStaticBuffer_t dummyEvents[(TRC_CFG_MAX_ISR_NESTING) + 1]; /**< */ 43 | } TraceCoreStaticBuffer_t; 44 | 45 | /** 46 | * @internal Trace Static Buffer Table Structure 47 | */ 48 | typedef struct TraceStaticBufferTable /* Aligned */ 49 | { 50 | TraceCoreStaticBuffer_t coreDummyEvents[TRC_CFG_CORE_COUNT]; /**< Temporary buffers used for event or blob creation. */ 51 | } TraceStaticBufferTable_t; 52 | 53 | extern TraceStaticBufferTable_t* pxTraceStaticBufferTable; 54 | 55 | /** 56 | * @internal Initialize trace static buffer. 57 | * 58 | * @param[in] pxBuffer Pointer to memory that will be used by the 59 | * trace static buffer. 60 | * 61 | * @retval TRC_FAIL Failure 62 | * @retval TRC_SUCCESS Success 63 | */ 64 | traceResult xTraceStaticBufferInitialize(TraceStaticBufferTable_t* pxBuffer); 65 | 66 | #if ((TRC_CFG_USE_TRACE_ASSERT) == 1) 67 | 68 | /** 69 | * @brief Gets trace static buffer. 70 | * 71 | * @param[out] ppvBuffer Buffer. 72 | * 73 | * @retval TRC_FAIL Failure 74 | * @retval TRC_SUCCESS Success 75 | */ 76 | traceResult xTraceStaticBufferGet(void **ppvBuffer); 77 | 78 | #else /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */ 79 | 80 | /** 81 | * @brief Gets trace static buffer. 82 | * 83 | * @param[out] ppvBuffer Buffer. 84 | * 85 | * @retval TRC_FAIL Failure 86 | * @retval TRC_SUCCESS Success 87 | */ 88 | #define xTraceStaticBufferGet(ppvBuffer) (*(ppvBuffer) = (void*)&pxTraceStaticBufferTable->coreDummyEvents[TRC_CFG_GET_CURRENT_CORE()].dummyEvents[xTraceISRGetCurrentNestingReturned() + 1], TRC_SUCCESS) 89 | 90 | #endif /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */ 91 | 92 | /** @} */ 93 | 94 | #ifdef __cplusplus 95 | } 96 | #endif 97 | 98 | #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ 99 | 100 | #endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ 101 | 102 | #endif /* TRC_STATIC_BUFFER_H */ 103 | -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/include/trcString.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Percepio Trace Recorder for Tracealyzer v4.8.0.hotfix1 3 | * Copyright 2023 Percepio AB 4 | * www.percepio.com 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | */ 8 | 9 | /** 10 | * @file 11 | * 12 | * @brief Public trace string APIs. 13 | */ 14 | 15 | #ifndef TRC_STRING_H 16 | #define TRC_STRING_H 17 | 18 | #if (TRC_USE_TRACEALYZER_RECORDER == 1) 19 | 20 | #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) 21 | 22 | #include 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /** 29 | * @defgroup trace_string_apis Trace String APIs 30 | * @ingroup trace_recorder_apis 31 | * @{ 32 | */ 33 | 34 | /** 35 | * @brief Registers a trace string. 36 | * 37 | * This routine registers a strings in the recorder, e.g. for names of user 38 | * event channels. 39 | * 40 | * Example: 41 | * TraceStringHandle_t myEventHandle; 42 | * xTraceStringRegister("MyUserEvent", &myEventHandle); 43 | * ... 44 | * xTracePrintF(myEventHandle, "My value is: %d", myValue); 45 | * 46 | * @param[in] szString String. 47 | * @param[out] pString Pointer to uninitialized trace string. 48 | * 49 | * @retval TRC_FAIL Failure 50 | * @retval TRC_SUCCESS Success 51 | */ 52 | traceResult xTraceStringRegister(const char *szString, TraceStringHandle_t* pString); 53 | 54 | /** 55 | * @brief Registers a trace string. 56 | * 57 | * @deprecated Remains for backward compability with pre v4.6 versions 58 | * of the recorder. 59 | * 60 | * @param[in] name Name. 61 | * 62 | * @return TraceStringHandle_t 63 | */ 64 | TraceStringHandle_t xTraceRegisterString(const char *name); 65 | 66 | /** @} */ 67 | 68 | #ifdef __cplusplus 69 | } 70 | #endif 71 | 72 | #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ 73 | 74 | #endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ 75 | 76 | #endif /* TRC_STRING_H */ 77 | -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/include/trcTypes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Percepio Trace Recorder for Tracealyzer v4.8.0.hotfix1 3 | * Copyright 2023 Percepio AB 4 | * www.percepio.com 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | * 8 | * The common types. 9 | */ 10 | 11 | #ifndef TRC_TYPES_H 12 | #define TRC_TYPES_H 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | #ifndef TRC_BASE_TYPE 23 | #define TRC_BASE_TYPE int32_t 24 | #endif 25 | 26 | #ifndef TRC_UNSIGNED_BASE_TYPE 27 | #define TRC_UNSIGNED_BASE_TYPE uint32_t 28 | #endif 29 | 30 | typedef TRC_UNSIGNED_BASE_TYPE TraceUnsignedBaseType_t; 31 | 32 | typedef TRC_BASE_TYPE TraceBaseType_t; 33 | 34 | #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) 35 | typedef void* TraceHandleBaseType_t; 36 | #else 37 | typedef TraceUnsignedBaseType_t TraceHandleBaseType_t; 38 | #endif 39 | 40 | typedef TraceUnsignedBaseType_t traceResult; 41 | 42 | typedef TraceHandleBaseType_t TraceEventHandle_t; 43 | 44 | typedef TraceHandleBaseType_t TraceISRHandle_t; 45 | 46 | typedef TraceHandleBaseType_t TraceEntryHandle_t; 47 | 48 | typedef TraceHandleBaseType_t TraceTaskHandle_t; 49 | 50 | typedef TraceHandleBaseType_t TraceObjectHandle_t; 51 | 52 | typedef TraceHandleBaseType_t TraceExtensionHandle_t; 53 | 54 | typedef TraceHandleBaseType_t TraceHeapHandle_t; 55 | 56 | typedef TraceHandleBaseType_t TraceIntervalChannelSetHandle_t; 57 | 58 | typedef TraceHandleBaseType_t TraceIntervalChannelHandle_t; 59 | 60 | typedef TraceHandleBaseType_t TraceIntervalInstanceHandle_t; 61 | 62 | typedef TraceHandleBaseType_t TraceStateMachineHandle_t; 63 | 64 | typedef TraceHandleBaseType_t TraceStateMachineStateHandle_t; 65 | 66 | typedef TraceHandleBaseType_t TraceStringHandle_t; 67 | 68 | typedef TraceHandleBaseType_t TraceCounterHandle_t; 69 | 70 | typedef TraceHandleBaseType_t TraceRunnableHandle_t; 71 | 72 | typedef TraceHandleBaseType_t TraceRunnableStaticSetHandle_t; 73 | 74 | typedef void (*TraceCounterCallback_t)(TraceCounterHandle_t xCounterHandle); 75 | 76 | /* DEPRECATED. Backwards compatibility */ 77 | typedef TraceStringHandle_t traceString; 78 | 79 | #ifdef __cplusplus 80 | } 81 | #endif 82 | 83 | #endif /* TRC_TYPES_H */ 84 | -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/include/trcUtility.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Percepio Trace Recorder for Tracealyzer v4.8.0.hotfix1 3 | * Copyright 2023 Percepio AB 4 | * www.percepio.com 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | * 8 | * The interface for trace utility functions. 9 | */ 10 | 11 | #ifndef TRC_UTILITY_H 12 | #define TRC_UTILITY_H 13 | 14 | #ifndef TRC_MEMCPY 15 | #define TRC_MEMCPY(dst, src, size) \ 16 | { \ 17 | uint32_t __i; \ 18 | for (__i = 0; __i < size; __i++) { \ 19 | ((uint8_t*)(dst))[__i] = ((uint8_t*)(src))[__i]; \ 20 | } \ 21 | } 22 | #endif 23 | 24 | #define TRC_STRCAT(dst, dst_size, pDstLength, src) \ 25 | { \ 26 | TraceUnsignedBaseType_t uxTRC_STRCAT_INDEX = 0; \ 27 | while (*(pDstLength) < (dst_size)) \ 28 | { \ 29 | dst[*(pDstLength)] = src[uxTRC_STRCAT_INDEX]; \ 30 | if (dst[*(pDstLength)] == 0) \ 31 | break; \ 32 | (*(pDstLength))++; \ 33 | uxTRC_STRCAT_INDEX++; \ 34 | } \ 35 | } 36 | 37 | #if (defined(TRC_CFG_USE_GCC_STATEMENT_EXPR) && TRC_CFG_USE_GCC_STATEMENT_EXPR == 1) || __GNUC__ || __IAR_SYSTEMS_ICC__ || __TI_ARM__ 38 | #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_1(e1) __extension__({e1;}) 39 | #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(e1, e2) __extension__({e1; e2;}) 40 | #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_3(e1, e2, e3) __extension__({e1; e2; e3;}) 41 | #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_4(e1, e2, e3, e4) __extension__({e1; e2; e3; e4;}) 42 | #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_5(e1, e2, e3, e4, e5) __extension__({e1; e2; e3; e4; e5;}) 43 | #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_6(e1, e2, e3, e4, e5, e6) __extension__({e1; e2; e3; e4; e5; e6;}) 44 | #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_7(e1, e2, e3, e4, e5, e6, e7) __extension__({e1; e2; e3; e4; e5; e6; e7;}) 45 | #else 46 | #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_1(e1) (e1) 47 | #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(e1, e2) (e1, e2) 48 | #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_3(e1, e2, e3) (e1, e2, e3) 49 | #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_4(e1, e2, e3, e4) (e1, e2, e3, e4) 50 | #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_5(e1, e2, e3, e4, e5) (e1, e2, e3, e4, e5) 51 | #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_6(e1, e2, e3, e4, e5, e6) (e1, e2, e3, e4, e5, e6) 52 | #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_7(e1, e2, e3, e4, e5, e6, e7) (e1, e2, e3, e4, e5, e6, e7) 53 | #endif 54 | 55 | #endif /* TRC_UTILITY_H */ 56 | -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/kernelports/FreeRTOS/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(inc 2 | ${inc} 3 | "${CMAKE_CURRENT_SOURCE_DIR}/config" 4 | "${CMAKE_CURRENT_SOURCE_DIR}/include" 5 | PARENT_SCOPE 6 | ) 7 | 8 | set(src 9 | ${src} 10 | "${CMAKE_CURRENT_SOURCE_DIR}/trcKernelPort.c" 11 | PARENT_SCOPE 12 | ) -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/kernelports/FreeRTOS/config/trcKernelPortSnapshotConfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Trace Recorder for Tracealyzer v4.8.0.hotfix1 3 | * Copyright 2023 Percepio AB 4 | * www.percepio.com 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | * 8 | * Kernel port configuration parameters for snapshot mode. 9 | */ 10 | 11 | #ifndef TRC_KERNEL_PORT_SNAPSHOT_CONFIG_H 12 | #define TRC_KERNEL_PORT_SNAPSHOT_CONFIG_H 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | /** 19 | * @def TRC_CFG_NTASK, TRC_CFG_NISR, TRC_CFG_NQUEUE, TRC_CFG_NSEMAPHORE... 20 | * @brief A group of macros which should be defined as integer values, zero or larger. 21 | * 22 | * These define the capacity of the Object Property Table, i.e., the maximum 23 | * number of objects active at any given point, within each object class (e.g., 24 | * task, queue, semaphore, ...). 25 | * 26 | * If tasks or other objects are deleted in your system, this 27 | * setting does not limit the total amount of objects created, only the number 28 | * of objects that have been successfully created but not yet deleted. 29 | * 30 | * Using too small values will cause vTraceError to be called, which stores an 31 | * error message in the trace that is shown when opening the trace file. The 32 | * error message can also be retrieved using xTraceGetLastError. 33 | * 34 | * It can be wise to start with large values for these constants, 35 | * unless you are very confident on these numbers. Then do a recording and 36 | * check the actual usage by selecting View menu -> Trace Details -> 37 | * Resource Usage -> Object Table. 38 | */ 39 | #define TRC_CFG_NTASK 15 40 | #define TRC_CFG_NISR 5 41 | #define TRC_CFG_NQUEUE 10 42 | #define TRC_CFG_NSEMAPHORE 10 43 | #define TRC_CFG_NMUTEX 10 44 | #define TRC_CFG_NTIMER 5 45 | #define TRC_CFG_NEVENTGROUP 5 46 | #define TRC_CFG_NSTREAMBUFFER 5 47 | #define TRC_CFG_NMESSAGEBUFFER 5 48 | 49 | /** 50 | * @def TRC_CFG_NAME_LEN_TASK, TRC_CFG_NAME_LEN_QUEUE, ... 51 | * @brief Macros that specify the maximum lengths (number of characters) for names of 52 | * kernel objects, such as tasks and queues. If longer names are used, they will 53 | * be truncated when stored in the recorder. 54 | */ 55 | #define TRC_CFG_NAME_LEN_TASK 15 56 | #define TRC_CFG_NAME_LEN_ISR 15 57 | #define TRC_CFG_NAME_LEN_QUEUE 15 58 | #define TRC_CFG_NAME_LEN_SEMAPHORE 15 59 | #define TRC_CFG_NAME_LEN_MUTEX 15 60 | #define TRC_CFG_NAME_LEN_TIMER 15 61 | #define TRC_CFG_NAME_LEN_EVENTGROUP 15 62 | #define TRC_CFG_NAME_LEN_STREAMBUFFER 15 63 | #define TRC_CFG_NAME_LEN_MESSAGEBUFFER 15 64 | 65 | #ifdef __cplusplus 66 | } 67 | #endif 68 | 69 | #endif /* TRC_KERNEL_PORT_SNAPSHOT_CONFIG_H */ 70 | -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/kernelports/FreeRTOS/config/trcKernelPortStreamingConfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Trace Recorder for Tracealyzer v4.8.0.hotfix1 3 | * Copyright 2023 Percepio AB 4 | * www.percepio.com 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | * 8 | * Kernel port configuration parameters for streaming mode. 9 | */ 10 | 11 | #ifndef TRC_KERNEL_PORT_STREAMING_CONFIG_H 12 | #define TRC_KERNEL_PORT_STREAMING_CONFIG_H 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | /* Nothing yet */ 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif /* TRC_KERNEL_PORT_STREAMING_CONFIG_H */ 25 | -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/streamports/RingBuffer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(inc 2 | ${inc} 3 | "${CMAKE_CURRENT_SOURCE_DIR}/config" 4 | "${CMAKE_CURRENT_SOURCE_DIR}/include" 5 | PARENT_SCOPE 6 | ) 7 | 8 | set(src 9 | ${src} 10 | "${CMAKE_CURRENT_SOURCE_DIR}/trcStreamPort.c" 11 | PARENT_SCOPE 12 | ) -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/streamports/RingBuffer/Kconfig: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 Percepio AB 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | menu "Ring Buffer Config" 5 | config PERCEPIO_TRC_CFG_STREAM_PORT_RINGBUFFER_SIZE 6 | int "Buffer size" 7 | default 10240 8 | range 0 10485760 9 | help 10 | Defines the size of the ring buffer use for storing trace events. 11 | 12 | choice PERCEPIO_TRC_CFG_STREAM_PORT_RINGBUFFER_MODE 13 | prompt "Ring Buffer Mode" 14 | default PERCEPIO_TRC_STREAM_PORT_RINGBUFFER_MODE_OVERWRITE_WHEN_FULL 15 | help 16 | With PERCEPIO_TRC_CFG_STREAM_PORT_RINGBUFFER_MODE set to PERCEPIO_TRC_STREAM_PORT_RINGBUFFER_MODE_OVERWRITE_WHEN_FULL, the 17 | events are stored in a ring buffer, i.e., where the oldest events are 18 | overwritten when the buffer becomes full. This allows you to get the last 19 | events leading up to an interesting state, e.g., an error, without having 20 | to store the whole run since startup. 21 | 22 | When PERCEPIO_TRC_CFG_STREAM_PORT_RINGBUFFER_MODE is PERCEPIO_TRC_STREAM_PORT_RINGBUFFER_MODE_STOP_WHEN_FULL, the 23 | recording is stopped when the buffer becomes full. This is useful for 24 | recording events following a specific state, e.g., the startup sequence. 25 | 26 | config PERCEPIO_TRC_STREAM_PORT_RINGBUFFER_MODE_OVERWRITE_WHEN_FULL 27 | bool "Overwrite when full" 28 | 29 | config PERCEPIO_TRC_STREAM_PORT_RINGBUFFER_MODE_STOP_WHEN_FULL 30 | bool "Stop when full" 31 | endchoice 32 | endmenu # "Ring Buffer Config" 33 | -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/streamports/RingBuffer/Readme-Streamport.txt: -------------------------------------------------------------------------------- 1 | Tracealyzer Stream Port for Ring Buffer 2 | ------------------------------------------------- 3 | 4 | This directory contains a "stream port" for the Tracealyzer recorder library, 5 | i.e., the specific code needed to use a particular interface for streaming a 6 | Tracealyzer RTOS trace. The stream port is defined by a set of macros in 7 | trcStreamPort.h, found in the "include" directory. 8 | 9 | This particular stream port is for streaming to a ring buffer. 10 | 11 | To use this stream port, make sure that include/trcStreamPort.h is found 12 | by the compiler (i.e., add this folder to your project's include paths) and 13 | add all included source files to your build. Make sure no other versions of 14 | trcStreamPort.h are included by mistake! 15 | 16 | See also http://percepio.com/2016/10/05/rtos-tracing. 17 | 18 | Percepio AB 19 | www.percepio.com -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/streamports/RingBuffer/config/trcStreamPortConfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Trace Recorder for Tracealyzer v4.8.0.hotfix1 3 | * Copyright 2023 Percepio AB 4 | * www.percepio.com 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | * 8 | * The configuration for trace streaming ("stream ports"). 9 | */ 10 | 11 | #ifndef TRC_STREAM_PORT_CONFIG_H 12 | #define TRC_STREAM_PORT_CONFIG_H 13 | 14 | #if (TRC_USE_TRACEALYZER_RECORDER == 1) 15 | 16 | #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) 17 | 18 | #include 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | /* Type flags */ 25 | #define TRC_STREAM_PORT_RINGBUFFER_MODE_STOP_WHEN_FULL (0U) 26 | #define TRC_STREAM_PORT_RINGBUFFER_MODE_OVERWRITE_WHEN_FULL (1U) 27 | 28 | /** 29 | * @def TRC_CFG_STREAM_PORT_BUFFER_SIZE 30 | * 31 | * @brief Defines the size of the ring buffer use for storing trace events. 32 | */ 33 | #define TRC_CFG_STREAM_PORT_BUFFER_SIZE 10240 34 | 35 | /** 36 | * @def TRC_CFG_STREAM_PORT_BUFFER_MODE 37 | * 38 | * @brief Configures the behavior of the ring buffer when full. 39 | * 40 | * With TRC_CFG_STREAM_PORT_MODE set to TRC_STREAM_PORT_RINGBUFFER_MODE_OVERWRITE_WHEN_FULL, the 41 | * events are stored in a ring buffer, i.e., where the oldest events are 42 | * overwritten when the buffer becomes full. This allows you to get the last 43 | * events leading up to an interesting state, e.g., an error, without having 44 | * to store the whole run since startup. 45 | * 46 | * When TRC_CFG_STREAM_PORT_MODE is TRC_STREAM_PORT_RINGBUFFER_MODE_STOP_WHEN_FULL, the 47 | * recording is stopped when the buffer becomes full. This is useful for 48 | * recording events following a specific state, e.g., the startup sequence. 49 | */ 50 | #define TRC_CFG_STREAM_PORT_RINGBUFFER_MODE TRC_STREAM_PORT_RINGBUFFER_MODE_OVERWRITE_WHEN_FULL 51 | 52 | #ifdef __cplusplus 53 | } 54 | #endif 55 | 56 | #endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ 57 | 58 | #endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/ 59 | 60 | #endif /* TRC_STREAM_PORT_CONFIG_H */ 61 | -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/trcDependency.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Trace Recorder for Tracealyzer v4.8.0.hotfix1 3 | * Copyright 2023 Percepio AB 4 | * www.percepio.com 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | * 8 | * The implementation of dependencies. 9 | */ 10 | #include 11 | 12 | #if (TRC_USE_TRACEALYZER_RECORDER == 1) 13 | 14 | #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) 15 | 16 | #define TRC_DEPENDENCY_STATE_INDEX_TYPE 0UL 17 | 18 | /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ 19 | traceResult xTraceDependencyRegister(const char* szName, TraceUnsignedBaseType_t uxDependencyType) 20 | { 21 | TraceObjectHandle_t xObjectHandle; 22 | TraceUnsignedBaseType_t auxStates[TRC_ENTRY_TABLE_STATE_COUNT] = { 0UL }; 23 | 24 | /* This should never fail */ 25 | TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_CORE)); 26 | 27 | /* This should never fail */ 28 | TRC_ASSERT(szName != (void*)0); 29 | 30 | /* This should never fail */ 31 | TRC_ASSERT(szName[0] != (char)0); /*cstat !MISRAC2004-17.4_b Checking first character*/ /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ 32 | 33 | switch (uxDependencyType) 34 | { 35 | case TRC_DEPENDENCY_TYPE_ELF: 36 | auxStates[TRC_DEPENDENCY_STATE_INDEX_TYPE] = uxDependencyType; 37 | break; 38 | default: 39 | return TRC_FAIL; 40 | break; 41 | } 42 | 43 | return xTraceObjectRegisterInternal(PSF_EVENT_DEPENDENCY_REGISTER, (void*)0, szName, 1u, auxStates, TRC_ENTRY_OPTION_DEPENDENCY, &xObjectHandle); 44 | } 45 | 46 | #endif 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/trcHeap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Percepio Trace Recorder for Tracealyzer v4.8.0.hotfix1 3 | * Copyright 2023 Percepio AB 4 | * www.percepio.com 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | * 8 | * The implementation for heaps. 9 | */ 10 | 11 | #include 12 | 13 | #if (TRC_USE_TRACEALYZER_RECORDER == 1) 14 | 15 | #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) 16 | 17 | #if (TRC_USE_HEAPS == 1) 18 | 19 | /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ 20 | traceResult xTraceHeapCreate(const char *szName, TraceUnsignedBaseType_t uxCurrent, TraceUnsignedBaseType_t uxHighWaterMark, TraceUnsignedBaseType_t uxMax, TraceHeapHandle_t *pxHeapHandle) 21 | { 22 | TraceUnsignedBaseType_t uxStates[3]; 23 | 24 | uxStates[TRC_HEAP_STATE_INDEX_CURRENT] = uxCurrent; 25 | uxStates[TRC_HEAP_STATE_INDEX_HIGHWATERMARK] = uxHighWaterMark; 26 | uxStates[TRC_HEAP_STATE_INDEX_MAX] = uxMax; 27 | 28 | return xTraceObjectRegisterInternal(PSF_EVENT_HEAP_CREATE, (void*)0, szName, 3u, uxStates, TRC_ENTRY_OPTION_HEAP, (TraceObjectHandle_t*)pxHeapHandle); 29 | } 30 | 31 | traceResult xTraceHeapAlloc(TraceHeapHandle_t xHeapHandle, void *pvAddress, TraceUnsignedBaseType_t uxSize) 32 | { 33 | TraceUnsignedBaseType_t uxCurrent, uxHighWaterMark; 34 | 35 | if (xHeapHandle == 0) 36 | { 37 | /* This can happen */ 38 | return TRC_FAIL; 39 | } 40 | 41 | /* If the address is null we assume this was a failed alloc attempt */ 42 | if (pvAddress != (void*)0) 43 | { 44 | /* This should never fail */ 45 | TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetState(xHeapHandle, TRC_HEAP_STATE_INDEX_CURRENT, &uxCurrent) == TRC_SUCCESS); 46 | 47 | /* This should never fail */ 48 | TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetState(xHeapHandle, TRC_HEAP_STATE_INDEX_HIGHWATERMARK, &uxHighWaterMark) == TRC_SUCCESS); 49 | 50 | uxCurrent += uxSize; 51 | 52 | if (uxCurrent > uxHighWaterMark) 53 | { 54 | uxHighWaterMark = uxCurrent; 55 | /* This should never fail */ 56 | TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetState(xHeapHandle, TRC_HEAP_STATE_INDEX_HIGHWATERMARK, uxHighWaterMark) == TRC_SUCCESS); 57 | } 58 | 59 | /* This should never fail */ 60 | TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetState(xHeapHandle, TRC_HEAP_STATE_INDEX_CURRENT, uxCurrent) == TRC_SUCCESS); 61 | } 62 | 63 | (void)xTraceEventCreate2((pvAddress != (void*)0) ? PSF_EVENT_MALLOC : PSF_EVENT_MALLOC_FAILED, (TraceUnsignedBaseType_t)pvAddress, uxSize); /*cstat !MISRAC2004-11.3 !MISRAC2012-Rule-11.4 !MISRAC2012-Rule-11.6 Suppress conversion from pointer to integer check*/ 64 | 65 | return TRC_SUCCESS; 66 | } 67 | 68 | traceResult xTraceHeapFree(TraceHeapHandle_t xHeapHandle, void *pvAddress, TraceUnsignedBaseType_t uxSize) 69 | { 70 | TraceUnsignedBaseType_t uxCurrent; 71 | 72 | if (xHeapHandle == 0) 73 | { 74 | /* This can happen */ 75 | return TRC_FAIL; 76 | } 77 | 78 | /* If the address is null we assume this was a failed alloc attempt */ 79 | if (pvAddress != (void*)0) 80 | { 81 | /* This should never fail */ 82 | TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetState(xHeapHandle, TRC_HEAP_STATE_INDEX_CURRENT, &uxCurrent) == TRC_SUCCESS); 83 | 84 | uxCurrent -= uxSize; 85 | 86 | /* This should never fail */ 87 | TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetState(xHeapHandle, TRC_HEAP_STATE_INDEX_CURRENT, uxCurrent) == TRC_SUCCESS); 88 | } 89 | 90 | (void)xTraceEventCreate2((pvAddress != (void*)0) ? PSF_EVENT_FREE : PSF_EVENT_FREE_FAILED, (TraceUnsignedBaseType_t)pvAddress, uxSize); /*cstat !MISRAC2004-11.3 !MISRAC2012-Rule-11.4 !MISRAC2012-Rule-11.6 Suppress conversion from pointer to integer check*/ 91 | 92 | return TRC_SUCCESS; 93 | } 94 | 95 | #endif /* (TRC_USE_HEAPS == 1) */ 96 | 97 | #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ 98 | 99 | #endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ 100 | -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/trcRunnable.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Percepio Trace Recorder for Tracealyzer v4.8.0.hotfix1 3 | * Copyright 2023 Percepio AB 4 | * www.percepio.com 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | * 8 | * The implementation for strings. 9 | */ 10 | 11 | #include 12 | 13 | #if (TRC_USE_TRACEALYZER_RECORDER == 1) 14 | 15 | #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) 16 | 17 | #define TRC_RUNNABLE_STATE_INDEX_OWNER_TASK 0UL 18 | 19 | /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ 20 | traceResult xTraceRunnableRegister(const char* szName, TraceRunnableRegisterMethod_t uxRegisterMethod, TraceRunnableHandle_t *pxRunnableHandle) 21 | { 22 | TraceEntryHandle_t xEntryHandle; 23 | TraceEventHandle_t xEventHandle = 0; 24 | int32_t i; 25 | uint32_t uiLength, uiValue = 0u; 26 | 27 | /* This should never fail */ 28 | TRC_ASSERT(szName != (void*)0); 29 | 30 | /* This should never fail */ 31 | TRC_ASSERT(pxRunnableHandle != (void*)0); 32 | 33 | for (i = 0; (szName[i] != (char)0) && (i < (int32_t)(TRC_ENTRY_TABLE_SLOT_SYMBOL_SIZE)); i++) {} /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ /*cstat !MISRAC2004-17.4_b We need to access every character in the string*/ 34 | 35 | uiLength = (uint32_t)i; 36 | 37 | if (uxRegisterMethod == TRC_RUNNABLE_REGISTER_METHOD_USE_ENTRY_TABLE) 38 | { 39 | /* Check if we have already created an entry previously */ 40 | if (*pxRunnableHandle == (void*)0) 41 | { 42 | /* We need to check this */ 43 | if (xTraceEntryCreate(&xEntryHandle) == TRC_FAIL) 44 | { 45 | return TRC_FAIL; 46 | } 47 | 48 | TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetOptions(xEntryHandle, TRC_ENTRY_OPTION_RUNNABLE) == TRC_SUCCESS); 49 | 50 | TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetState(xEntryHandle, TRC_RUNNABLE_STATE_INDEX_OWNER_TASK, (TraceUnsignedBaseType_t)xTraceTaskGetCurrentReturn()) == TRC_SUCCESS); /*cstat !MISRAC2004-11.3 !MISRAC2012-Rule-11.4 !MISRAC2012-Rule-11.6 We need the address of the task*/ 51 | 52 | /* The address to the available symbol table slot is the address we use */ 53 | /* This should never fail */ 54 | TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetSymbol(xEntryHandle, szName, uiLength) == TRC_SUCCESS); 55 | 56 | *pxRunnableHandle = (TraceRunnableHandle_t)xEntryHandle; 57 | } 58 | } 59 | else if (uxRegisterMethod == TRC_RUNNABLE_REGISTER_METHOD_USE_STRING_ADDRESS) 60 | { 61 | *pxRunnableHandle = (TraceRunnableHandle_t)szName; /*cstat !MISRAC2004-11.5 !MISRAC2012-Rule-11.8 We need the address of the string*/ 62 | } 63 | else if (uxRegisterMethod == TRC_RUNNABLE_REGISTER_METHOD_USE_HANDLE_ADDRESS) 64 | { 65 | /* The handle address should be a unique value that we can use as handle */ 66 | *pxRunnableHandle = (TraceRunnableHandle_t)pxRunnableHandle; 67 | } 68 | else 69 | { 70 | return TRC_FAIL; 71 | } 72 | 73 | /* We need to check this */ 74 | if (xTraceEventBegin(PSF_EVENT_RUNNABLE_REGISTER, sizeof(void*) + uiLength, &xEventHandle) == TRC_SUCCESS) 75 | { 76 | (void)xTraceEventAddPointer(xEventHandle, (void*)*pxRunnableHandle); 77 | (void)xTraceEventAddString(xEventHandle, szName, uiLength); 78 | 79 | /* Check if we can truncate */ 80 | (void)xTraceEventPayloadRemaining(xEventHandle, &uiValue); 81 | if (uiValue > 0u) 82 | { 83 | (void)xTraceEventAdd8(xEventHandle, 0u); 84 | } 85 | 86 | (void)xTraceEventEnd(xEventHandle); /*cstat !MISRAC2012-Rule-17.7 Suppress ignored return value check (inside macro)*/ 87 | } 88 | 89 | return TRC_SUCCESS; 90 | } 91 | 92 | #endif 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/trcStateMachine.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Trace Recorder for Tracealyzer v4.8.0.hotfix1 3 | * Copyright 2023 Percepio AB 4 | * www.percepio.com 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | * 8 | * The implementation of state machines. 9 | */ 10 | 11 | #include 12 | 13 | #if (TRC_USE_TRACEALYZER_RECORDER == 1) 14 | 15 | #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) 16 | 17 | #define TRC_STATE_MACHINE_STATE_INDEX 0u 18 | #define TRC_STATE_MACHINE_INDEX 0u 19 | 20 | /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ 21 | traceResult xTraceStateMachineCreate(const char *szName, TraceStateMachineHandle_t *pxStateMachineHandle) 22 | { 23 | TraceObjectHandle_t xObjectHandle; 24 | 25 | /* This should never fail */ 26 | TRC_ASSERT(pxStateMachineHandle != (void*)0); 27 | 28 | /* We need to check this */ 29 | if (xTraceObjectRegister(PSF_EVENT_STATEMACHINE_CREATE , (void*)0, szName, 0u, &xObjectHandle) == TRC_FAIL) 30 | { 31 | return TRC_FAIL; 32 | } 33 | 34 | /* This should never fail */ 35 | TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetOptions((TraceEntryHandle_t)xObjectHandle, (uint32_t)TRC_ENTRY_OPTION_STATE_MACHINE) == TRC_SUCCESS); 36 | 37 | *pxStateMachineHandle = (TraceStateMachineHandle_t)xObjectHandle; 38 | 39 | return TRC_SUCCESS; 40 | } 41 | 42 | /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ 43 | traceResult xTraceStateMachineStateCreate(TraceStateMachineHandle_t xStateMachineHandle, const char* szName, TraceStateMachineStateHandle_t* pxStateHandle) 44 | { 45 | TraceObjectHandle_t xObjectHandle; 46 | 47 | /* This should never fail */ 48 | TRC_ASSERT(xStateMachineHandle != 0); 49 | 50 | /* This should never fail */ 51 | TRC_ASSERT(pxStateHandle != (void*)0); 52 | 53 | /* We need to check this */ 54 | if (xTraceObjectRegister(PSF_EVENT_STATEMACHINE_STATE_CREATE, (void*)0, szName, (TraceUnsignedBaseType_t)xStateMachineHandle, &xObjectHandle) == TRC_FAIL) /*cstat !MISRAC2004-11.3 !MISRAC2012-Rule-11.4 Suppress conversion from pointer to integer check*/ 55 | { 56 | return TRC_FAIL; 57 | } 58 | 59 | /* This should never fail */ 60 | TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetOptions((TraceEntryHandle_t)xObjectHandle, (uint32_t)TRC_ENTRY_OPTION_STATE_MACHINE_STATE) == TRC_SUCCESS); 61 | 62 | *pxStateHandle = (TraceStateMachineHandle_t)xObjectHandle; 63 | 64 | return TRC_SUCCESS; 65 | } 66 | 67 | traceResult xTraceStateMachineSetState(TraceStateMachineHandle_t xStateMachineHandle, TraceStateMachineStateHandle_t xStateHandle) 68 | { 69 | /* This should never fail */ 70 | TRC_ASSERT(xStateMachineHandle != 0); 71 | 72 | /* This should never fail */ 73 | TRC_ASSERT(xStateHandle != 0); 74 | 75 | /* Verify that this state machine state was meant to be used with this state machine */ 76 | /* This should never fail */ 77 | TRC_ASSERT(xStateMachineHandle == (TraceStateMachineHandle_t)xTraceEntryGetStateReturn((TraceEntryHandle_t)xStateHandle, TRC_STATE_MACHINE_INDEX)); 78 | 79 | /* This should never fail */ 80 | TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetState((TraceEntryHandle_t)xStateMachineHandle, TRC_STATE_MACHINE_STATE_INDEX, (TraceUnsignedBaseType_t)xStateHandle) == TRC_SUCCESS); /*cstat !MISRAC2004-11.3 !MISRAC2012-Rule-11.4 Suppress conversion from pointer to integer check*/ 81 | 82 | (void)xTraceEventCreate2(PSF_EVENT_STATEMACHINE_STATECHANGE, (TraceUnsignedBaseType_t)xStateMachineHandle, (TraceUnsignedBaseType_t)xStateHandle); /*cstat !MISRAC2004-11.3 !MISRAC2012-Rule-11.4 Suppress conversion from pointer to integer check*/ 83 | 84 | return TRC_SUCCESS; 85 | } 86 | 87 | #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ 88 | 89 | #endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ 90 | -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/trcStaticBuffer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Percepio Trace Recorder for Tracealyzer v4.8.0.hotfix1 3 | * Copyright 2023 Percepio AB 4 | * www.percepio.com 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | * 8 | * The implementation for the static buffer. 9 | */ 10 | 11 | #include 12 | 13 | #if (TRC_USE_TRACEALYZER_RECORDER == 1) 14 | 15 | #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) 16 | 17 | TraceStaticBufferTable_t *pxTraceStaticBufferTable TRC_CFG_RECORDER_DATA_ATTRIBUTE; 18 | 19 | traceResult xTraceStaticBufferInitialize(TraceStaticBufferTable_t *pxBuffer) 20 | { 21 | /* This should never fail */ 22 | TRC_ASSERT(pxBuffer != (void*)0); 23 | 24 | pxTraceStaticBufferTable = pxBuffer; 25 | 26 | xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_STATIC_BUFFER); 27 | 28 | return TRC_SUCCESS; 29 | } 30 | 31 | #if ((TRC_CFG_USE_TRACE_ASSERT) == 1) 32 | 33 | /* Returns a pointer to a maximum sized static buffer */ 34 | traceResult xTraceStaticBufferGet(void **ppvBuffer) 35 | { 36 | int32_t ISR_nesting; 37 | 38 | /* This should never fail */ 39 | TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_STATIC_BUFFER)); 40 | 41 | TRC_ASSERT(ppvBuffer != (void*)0); 42 | 43 | TRC_ASSERT(xTraceISRGetCurrentNesting(&ISR_nesting) == TRC_SUCCESS); 44 | 45 | /* Task dummy events begin at 0, ISR dummy events begin at index 1 */ 46 | *ppvBuffer = (void*)&pxTraceStaticBufferTable->coreDummyEvents[TRC_CFG_GET_CURRENT_CORE()].dummyEvents[ISR_nesting + 1]; 47 | 48 | return TRC_SUCCESS; 49 | } 50 | 51 | #endif /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */ 52 | 53 | #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ 54 | 55 | #endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ 56 | -------------------------------------------------------------------------------- /0_base/misc/Snapshot-Trace/trcString.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Percepio Trace Recorder for Tracealyzer v4.8.0.hotfix1 3 | * Copyright 2023 Percepio AB 4 | * www.percepio.com 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | * 8 | * The implementation for strings. 9 | */ 10 | 11 | #include 12 | 13 | #if (TRC_USE_TRACEALYZER_RECORDER == 1) 14 | 15 | #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) 16 | 17 | /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ 18 | traceResult xTraceStringRegister(const char* szString, TraceStringHandle_t *pString) 19 | { 20 | TraceEntryHandle_t xEntryHandle; 21 | TraceEventHandle_t xEventHandle = 0; 22 | int32_t i; 23 | uint32_t uiLength, uiValue = 0u; 24 | 25 | /* This should never fail */ 26 | TRC_ASSERT(szString != (void*)0); 27 | 28 | /* This should never fail */ 29 | TRC_ASSERT(pString != (void*)0); 30 | 31 | /* We need to check this */ 32 | if (xTraceEntryCreate(&xEntryHandle) == TRC_FAIL) 33 | { 34 | return TRC_FAIL; 35 | } 36 | 37 | for (i = 0; (szString[i] != (char)0) && (i < (int32_t)(TRC_ENTRY_TABLE_SLOT_SYMBOL_SIZE)); i++) {} /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ /*cstat !MISRAC2004-17.4_b We need to access every character in the string*/ 38 | 39 | uiLength = (uint32_t)i; 40 | 41 | /* The address to the available symbol table slot is the address we use */ 42 | /* This should never fail */ 43 | TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetSymbol(xEntryHandle, szString, uiLength) == TRC_SUCCESS); 44 | 45 | *pString = (TraceStringHandle_t)xEntryHandle; 46 | 47 | /* We need to check this */ 48 | if (xTraceEventBegin(PSF_EVENT_OBJ_NAME, sizeof(void*) + uiLength, &xEventHandle) == TRC_SUCCESS) 49 | { 50 | (void)xTraceEventAddPointer(xEventHandle, (void*)xEntryHandle); 51 | (void)xTraceEventAddString(xEventHandle, szString, uiLength); 52 | 53 | /* Check if we can truncate */ 54 | (void)xTraceEventPayloadRemaining(xEventHandle, &uiValue); 55 | if (uiValue > 0u) 56 | { 57 | (void)xTraceEventAdd8(xEventHandle, 0u); 58 | } 59 | 60 | (void)xTraceEventEnd(xEventHandle); /*cstat !MISRAC2012-Rule-17.7 Suppress ignored return value check (inside macro)*/ 61 | } 62 | 63 | return TRC_SUCCESS; 64 | } 65 | 66 | /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ 67 | TraceStringHandle_t xTraceRegisterString(const char *name) 68 | { 69 | TraceStringHandle_t trcStr = 0; 70 | (void)xTraceStringRegister(name, &trcStr); 71 | 72 | return trcStr; 73 | } 74 | 75 | #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ 76 | 77 | #endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ 78 | -------------------------------------------------------------------------------- /0_base/misc/cmake/arm.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_AR $ENV{GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-ar${CMAKE_EXECUTABLE_SUFFIX}) 2 | set(CMAKE_ASM_COMPILER $ENV{GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gcc${CMAKE_EXECUTABLE_SUFFIX}) 3 | set(CMAKE_C_COMPILER $ENV{GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gcc${CMAKE_EXECUTABLE_SUFFIX}) 4 | set(CMAKE_LINKER $ENV{GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gcc${CMAKE_EXECUTABLE_SUFFIX}) 5 | set(CMAKE_OBJCOPY $ENV{GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-objcopy${CMAKE_EXECUTABLE_SUFFIX} CACHE INTERNAL "") 6 | set(CMAKE_RANLIB $ENV{GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-ranlib${CMAKE_EXECUTABLE_SUFFIX} CACHE INTERNAL "") 7 | set(CMAKE_SIZE $ENV{GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-size${CMAKE_EXECUTABLE_SUFFIX} CACHE INTERNAL "") 8 | set(CMAKE_STRIP $ENV{GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-strip${CMAKE_EXECUTABLE_SUFFIX} CACHE INTERNAL "") 9 | 10 | set(CMAKE_C_FLAGS "-ffreestanding \ 11 | -mthumb \ 12 | -mcpu=cortex-m3 \ 13 | -Wall -Wextra -Wshadow \ 14 | -Wno-unused-parameter \ 15 | -ggdb \ 16 | -Og \ 17 | -ffunction-sections \ 18 | -fdata-sections" CACHE INTERNAL "") 19 | 20 | set(CMAKE_EXE_LINKER_FLAGS "-T ${CMAKE_SOURCE_DIR}/0_base/misc/mps2_m3.ld \ 21 | -Xlinker -Map=${prj}.map \ 22 | -Xlinker --gc-sections \ 23 | -Xlinker --print-memory-usage \ 24 | -nostartfiles \ 25 | -specs=nano.specs -specs=nosys.specs") 26 | -------------------------------------------------------------------------------- /0_base/misc/cmake/common_demo.cmake: -------------------------------------------------------------------------------- 1 | set(freertos_demo_common_root "${freertos_root}/FreeRTOS/Demo/Common") 2 | 3 | set(common_demo_dir ${freertos_demo_common_root}/Minimal) 4 | set(common_demo_inc ${freertos_demo_common_root}/include) 5 | 6 | set(common_demo_src 7 | ${common_demo_dir}/AbortDelay.c 8 | ${common_demo_dir}/BlockQ.c 9 | ${common_demo_dir}/blocktim.c 10 | ${common_demo_dir}/countsem.c 11 | ${common_demo_dir}/death.c 12 | ${common_demo_dir}/dynamic.c 13 | ${common_demo_dir}/EventGroupsDemo.c 14 | ${common_demo_dir}/GenQTest.c 15 | ${common_demo_dir}/integer.c 16 | ${common_demo_dir}/IntQueue.c 17 | ${common_demo_dir}/IntSemTest.c 18 | ${common_demo_dir}/MessageBufferAMP.c 19 | ${common_demo_dir}/MessageBufferDemo.c 20 | ${common_demo_dir}/PollQ.c 21 | ${common_demo_dir}/QPeek.c 22 | ${common_demo_dir}/QueueOverwrite.c 23 | ${common_demo_dir}/QueueSet.c 24 | ${common_demo_dir}/QueueSetPolling.c 25 | ${common_demo_dir}/recmutex.c 26 | ${common_demo_dir}/semtest.c 27 | ${common_demo_dir}/StaticAllocation.c 28 | ${common_demo_dir}/StreamBufferDemo.c 29 | ${common_demo_dir}/StreamBufferInterrupt.c 30 | ${common_demo_dir}/TaskNotify.c 31 | ${common_demo_dir}/TaskNotifyArray.c 32 | ${common_demo_dir}/TimerDemo.c 33 | ) 34 | 35 | set(src ${src} ${common_demo_src}) 36 | set(inc ${inc} ${common_demo_inc}) -------------------------------------------------------------------------------- /0_base/misc/cmake/freertos.cmake: -------------------------------------------------------------------------------- 1 | set(kernel_dir "${freertos_root}/FreeRTOS/Source/") 2 | 3 | set(kernel_inc 4 | ${kernel_dir}/include 5 | ${kernel_dir}/portable/GCC/ARM_CM3 6 | ) 7 | 8 | set(kernel_src 9 | ${kernel_dir}/tasks.c 10 | ${kernel_dir}/list.c 11 | ${kernel_dir}/queue.c 12 | ${kernel_dir}/timers.c 13 | ${kernel_dir}/event_groups.c 14 | ${kernel_dir}/stream_buffer.c 15 | ${kernel_dir}/portable/MemMang/heap_4.c 16 | ${kernel_dir}/portable/GCC/ARM_CM3/port.c 17 | ) 18 | 19 | set(src ${src} ${kernel_src}) 20 | set(inc ${inc} ${kernel_inc}) -------------------------------------------------------------------------------- /0_base/misc/cmake/log.cmake: -------------------------------------------------------------------------------- 1 | file(WRITE "${CMAKE_BINARY_DIR}/source_files.txt" "") 2 | # Print each source file to a file 3 | foreach(file ${src}) 4 | file(APPEND "${CMAKE_BINARY_DIR}/source_files.txt" "${file}\n") 5 | endforeach() 6 | 7 | file(WRITE "${CMAKE_BINARY_DIR}/include_files.txt" "") 8 | # Print each include directory to a file 9 | foreach(file ${inc}) 10 | file(APPEND "${CMAKE_BINARY_DIR}/include_files.txt" "${file}\n") 11 | endforeach() 12 | -------------------------------------------------------------------------------- /0_base/misc/mps2_m3.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * FreeRTOS V202212.00 3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | * this software and associated documentation files (the "Software"), to deal in 7 | * the Software without restriction, including without limitation the rights to 8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | * the Software, and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in all 13 | * copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | * 22 | * https://www.FreeRTOS.org 23 | * https://github.com/FreeRTOS 24 | * 25 | */ 26 | 27 | MEMORY 28 | { 29 | FLASH (xr) : ORIGIN = 0x00000000, LENGTH = 4M /* to 0x00003FFF = 0x007FFFFF*/ 30 | RAM (rw) : ORIGIN = 0x20000000, LENGTH = 4M /* to 0x21FFFFFF = 0xFFFFFF */ 31 | } 32 | ENTRY(Reset_Handler) 33 | 34 | _Min_Heap_Size = 0x8 ; /* Not used as building heap_4.c */ 35 | _Min_Stack_Size = 0x400 ; /* Required amount of stack. Used by main(), then re-used as the interrupt stack after the kernel starts. */ 36 | _estack = ORIGIN(RAM) + LENGTH(RAM); 37 | 38 | 39 | SECTIONS 40 | { 41 | .isr_vector : 42 | { 43 | __vector_table = .; 44 | KEEP(*(.isr_vector)) 45 | . = ALIGN(4); 46 | } > FLASH 47 | 48 | .text : 49 | { 50 | *(.text) 51 | *(.rodata*) 52 | *(.constdata*) 53 | _etext = .; 54 | _sidata = .; 55 | } > FLASH 56 | 57 | .data : 58 | { 59 | . = ALIGN(8); 60 | _data = .; 61 | _sdata = .; 62 | *(vtable) 63 | *(.data) 64 | _edata = .; 65 | } > RAM 66 | 67 | .bss : 68 | { 69 | . = ALIGN(8); 70 | _bss = .; 71 | _sbss = .; 72 | *(.bss) 73 | _ebss = .; 74 | } > RAM 75 | 76 | .heap : 77 | { 78 | . = ALIGN(8); 79 | PROVIDE ( end = . ); 80 | PROVIDE ( _end = . ); 81 | _heap_bottom = .; 82 | . = . + _Min_Heap_Size; 83 | _heap_top = .; 84 | . = . + _Min_Stack_Size; 85 | . = ALIGN(8); 86 | } >RAM 87 | 88 | /* Set stack top to end of RAM, and stack limit move down by 89 | * size of stack_dummy section */ 90 | __StackTop = ORIGIN(RAM) + LENGTH(RAM); 91 | __StackLimit = __StackTop - _Min_Stack_Size; 92 | PROVIDE(__stack = __StackTop); 93 | 94 | /* Check if data + heap + stack exceeds RAM limit */ 95 | ASSERT(__StackLimit >= _heap_top, "region RAM overflowed with stack") 96 | 97 | } 98 | -------------------------------------------------------------------------------- /0_base/ringbuffer.c: -------------------------------------------------------------------------------- 1 | //copied from https://github.com/AndersKaloer/Ring-Buffer/tree/master 2 | #include "ringbuffer.h" 3 | 4 | /** 5 | * @file 6 | * Implementation of ring buffer functions. 7 | */ 8 | 9 | void ring_buffer_init(ring_buffer_t *buffer, char *buf, size_t buf_size) { 10 | RING_BUFFER_ASSERT(RING_BUFFER_IS_POWER_OF_TWO(buf_size) == 1); 11 | buffer->buffer = buf; 12 | buffer->buffer_mask = buf_size - 1; 13 | buffer->tail_index = 0; 14 | buffer->head_index = 0; 15 | } 16 | 17 | void ring_buffer_queue(ring_buffer_t *buffer, char data) { 18 | /* Is buffer full? */ 19 | if(ring_buffer_is_full(buffer)) { 20 | /* Is going to overwrite the oldest byte */ 21 | /* Increase tail index */ 22 | buffer->tail_index = ((buffer->tail_index + 1) & RING_BUFFER_MASK(buffer)); 23 | } 24 | 25 | /* Place data in buffer */ 26 | buffer->buffer[buffer->head_index] = data; 27 | buffer->head_index = ((buffer->head_index + 1) & RING_BUFFER_MASK(buffer)); 28 | } 29 | 30 | void ring_buffer_queue_arr(ring_buffer_t *buffer, const char *data, ring_buffer_size_t size) { 31 | /* Add bytes; one by one */ 32 | ring_buffer_size_t i; 33 | for(i = 0; i < size; i++) { 34 | ring_buffer_queue(buffer, data[i]); 35 | } 36 | } 37 | 38 | uint8_t ring_buffer_dequeue(ring_buffer_t *buffer, char *data) { 39 | if(ring_buffer_is_empty(buffer)) { 40 | /* No items */ 41 | return 0; 42 | } 43 | 44 | *data = buffer->buffer[buffer->tail_index]; 45 | buffer->tail_index = ((buffer->tail_index + 1) & RING_BUFFER_MASK(buffer)); 46 | return 1; 47 | } 48 | 49 | ring_buffer_size_t ring_buffer_dequeue_arr(ring_buffer_t *buffer, char *data, ring_buffer_size_t len) { 50 | if(ring_buffer_is_empty(buffer)) { 51 | /* No items */ 52 | return 0; 53 | } 54 | 55 | char *data_ptr = data; 56 | ring_buffer_size_t cnt = 0; 57 | while((cnt < len) && ring_buffer_dequeue(buffer, data_ptr)) { 58 | cnt++; 59 | data_ptr++; 60 | } 61 | return cnt; 62 | } 63 | 64 | uint8_t ring_buffer_peek(ring_buffer_t *buffer, char *data, ring_buffer_size_t index) { 65 | if(index >= ring_buffer_num_items(buffer)) { 66 | /* No items at index */ 67 | return 0; 68 | } 69 | 70 | /* Add index to pointer */ 71 | ring_buffer_size_t data_index = ((buffer->tail_index + index) & RING_BUFFER_MASK(buffer)); 72 | *data = buffer->buffer[data_index]; 73 | return 1; 74 | } 75 | 76 | extern inline uint8_t ring_buffer_is_empty(ring_buffer_t *buffer); 77 | extern inline uint8_t ring_buffer_is_full(ring_buffer_t *buffer); 78 | extern inline ring_buffer_size_t ring_buffer_num_items(ring_buffer_t *buffer); 79 | 80 | -------------------------------------------------------------------------------- /10_deadlock_starvation/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch_QEMU", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/demo", 12 | "cwd": "${workspaceFolder}", 13 | "miDebuggerPath": "${env:GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gdb-py", 14 | "miDebuggerServerAddress": "localhost:1234", 15 | "stopAtEntry": true, 16 | "preLaunchTask": "Run_QEMU", 17 | }, 18 | ] 19 | } -------------------------------------------------------------------------------- /10_deadlock_starvation/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Clean_Build", 8 | "type": "shell", 9 | "command": "${workspaceFolder}/../shell/rebuild.sh ${workspaceFolder}" 10 | }, 11 | { 12 | "label": "Run_QEMU", 13 | "type": "shell", 14 | "command": "${workspaceFolder}/../shell/rebuild_run_qemu.sh ${workspaceFolder} debug", 15 | "isBackground": true, 16 | "problemMatcher": [ 17 | { 18 | "pattern": [ 19 | { 20 | "regexp": ".", 21 | "file": 1, 22 | "location": 2, 23 | "message": 3 24 | } 25 | ], 26 | "background": { 27 | "activeOnStart": true, 28 | "beginsPattern": ".", 29 | "endsPattern": "QEMU_started", 30 | } 31 | } 32 | ] 33 | }, 34 | ] 35 | } -------------------------------------------------------------------------------- /10_deadlock_starvation/0_base: -------------------------------------------------------------------------------- 1 | ../0_base -------------------------------------------------------------------------------- /10_deadlock_starvation/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(prj demo) 4 | 5 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/arm.cmake") 6 | set(freertos_root "${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/FreeRTOS") 7 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/common_demo.cmake") 8 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/freertos.cmake") 9 | 10 | # Set the project name 11 | project(${prj}) 12 | 13 | set(demo_src "") 14 | 15 | if(DEMO_DEADLOCK_C) 16 | message(STATUS "demo_deadlock.c is going to be used") 17 | set(demo_src "demo_deadlock.c") 18 | endif() 19 | 20 | if(DEMO_STICK_PRIO_C) 21 | message(STATUS "demo_stick_prio.c is going to be used") 22 | set(demo_src "demo_stick_prio.c") 23 | endif() 24 | 25 | if(DEMO_CHAIR_C) 26 | message(STATUS "demo_chair.c is going to be used") 27 | set(demo_src "demo_chair.c") 28 | endif() 29 | 30 | if(DEMO_LIVELOCK_C) 31 | message(STATUS "demo_livelock.c is going to be used") 32 | set(demo_src "demo_livelock.c") 33 | endif() 34 | 35 | if(NOT demo_src) 36 | message(WARNING "No demo source file specified.") 37 | message(STATUS "demo_deadlock.c is going to be used") 38 | set(demo_src "demo_deadlock.c") 39 | endif() 40 | 41 | add_subdirectory(0_base) 42 | 43 | # Add all source files in the current directory 44 | set(demo_src "${CMAKE_CURRENT_SOURCE_DIR}/${demo_src}") 45 | 46 | set(src ${src} ${demo_src}) 47 | set(inc ${inc} ${CMAKE_CURRENT_SOURCE_DIR}) 48 | 49 | # Add the executable 50 | add_executable(${prj} ${src}) 51 | # Include directories 52 | target_include_directories(${prj} PUBLIC ${inc}) 53 | 54 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/log.cmake") 55 | -------------------------------------------------------------------------------- /10_deadlock_starvation/README.md: -------------------------------------------------------------------------------- 1 | # 10_deadlock_starvation (Dining Philosopher Problem) 2 | 3 | ![Dining Philosopher Problem](./doc/HungerProblem.png "Dining Philosopher Problem") 4 | Story: 5 | There are 5 philosopher and a table at dining hall. There are 5 chop sticks and a noodle on top of table. Philosopher are hungry. They need to share chop sticks to eat the noodle. They need 2 chopstick to be able to eat noodle. Since they can concurrently take chop sticks, they may block each other. Demos below demonstrates how to solve this problem. 6 | 7 | demo_chair.c 8 | If philosopher sits on even numbered chair, s/he gets left chop stick first. S/he gets right chopstick after left chopstick. Starts eating and after some time leaves chopstick at the table to share. If philosopher sits on odd numbered chair, order picking chopsticks is vice versa. 9 | ``` 10 | ../shell/rebuild_run_qemu.sh . -DDEMO_CHAIR_C:BOOL=ON 11 | ``` 12 | 13 | demo_deadlock.c 14 | Each philosophers gets chopstick to their left and then tries to get right one. Since all of them got left chopstick and not willing to share they are blocked. They go hungry. 15 | ``` 16 | ../shell/rebuild_run_qemu.sh . -DDEMO_DEADLOCK_C:BOOL=ON 17 | ``` 18 | 19 | demo_livelock.c 20 | Each philosophers tries to get chopstick to their left and then tries to get right one. If they can not get it for some time, they get disappointed and leaves the chop stick back at the table. 21 | 22 | In this demo, all of them gets first chop stick at the same time and leaves at the same time. None of them have 2 chop stick to be able eat at a given time. They go hungry. 23 | ``` 24 | ../shell/rebuild_run_qemu.sh . -DDEMO_LIVELOCK_C:BOOL=ON 25 | ``` 26 | 27 | demo_stick_prio.c 28 | A priority is given to each chop stick. Philosopher needs to pickup the chop stick with highest priority first. 29 | ``` 30 | ../shell/rebuild_run_qemu.sh . -DDEMO_STICK_PRIO_C:BOOL=ON 31 | ``` 32 | 33 | [Introduction to RTOS Part 10 - Deadlock and Starvation](https://www.youtube.com/watch?v=hRsWi4HIENc&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=10) 34 | 35 | 36 | ## Terminal Output 37 | Making sense of terminal output: 38 | * **waiting** s/he has no chop stick, just waits to get it 39 | * **got left** s/he got the left chop stick 40 | * **:)** s/he similing because gets to eat 41 | * **:D** s/he laughes because ate something 42 | * **gave left** s/he put back left chop stick at the table 43 | * **:/ left** s/he is dissapointed because: 44 | * put back the chop stick at the table without eating 45 | * was not able to get it in first place 46 | * led toggle is their party light 47 | 48 | Happy log from DEMO_CHAIR_C 49 | ``` 50 | Hypatia waiting 51 | Confucius waiting 52 | Antisthenes waiting 53 | Cruz waiting 54 | Douglass waiting 55 | Hypatia got left 56 | Antisthenes got right 57 | Cruz got left 58 | Hypatia :) 59 | Antisthenes :) 60 | Hypatia :D 61 | Antisthenes :D 62 | Hypatia gave right 63 | Antisthenes gave left 64 | Cruz :) 65 | Hypatia gave left 66 | Hypatia waiting 67 | Confucius got right 68 | Antisthenes gave right 69 | Antisthenes waiting 70 | Confucius :) 71 | Cruz :D 72 | ``` 73 | 74 | ## Notes 75 | Use demo_init function in demo.c to implement your demo application. 76 | Run in debug console to dump the trace 77 | -exec dump binary value trace.bin *RecorderDataPtr -------------------------------------------------------------------------------- /10_deadlock_starvation/doc/HungerProblem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aslansq/freertos_intro_qemu/28e98a29457cd92d517eebcb9b67189bbf197faa/10_deadlock_starvation/doc/HungerProblem.png -------------------------------------------------------------------------------- /10_deadlock_starvation_challenge/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch_QEMU", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/demo", 12 | "cwd": "${workspaceFolder}", 13 | "miDebuggerPath": "${env:GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gdb-py", 14 | "miDebuggerServerAddress": "localhost:1234", 15 | "stopAtEntry": true, 16 | "preLaunchTask": "Run_QEMU", 17 | }, 18 | ] 19 | } -------------------------------------------------------------------------------- /10_deadlock_starvation_challenge/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Clean_Build", 8 | "type": "shell", 9 | "command": "${workspaceFolder}/../shell/rebuild.sh ${workspaceFolder}" 10 | }, 11 | { 12 | "label": "Run_QEMU", 13 | "type": "shell", 14 | "command": "${workspaceFolder}/../shell/rebuild_run_qemu.sh ${workspaceFolder} debug", 15 | "isBackground": true, 16 | "problemMatcher": [ 17 | { 18 | "pattern": [ 19 | { 20 | "regexp": ".", 21 | "file": 1, 22 | "location": 2, 23 | "message": 3 24 | } 25 | ], 26 | "background": { 27 | "activeOnStart": true, 28 | "beginsPattern": ".", 29 | "endsPattern": "QEMU_started", 30 | } 31 | } 32 | ] 33 | }, 34 | ] 35 | } -------------------------------------------------------------------------------- /10_deadlock_starvation_challenge/0_base: -------------------------------------------------------------------------------- 1 | ../0_base -------------------------------------------------------------------------------- /10_deadlock_starvation_challenge/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(prj demo) 4 | 5 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/arm.cmake") 6 | set(freertos_root "${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/FreeRTOS") 7 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/common_demo.cmake") 8 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/freertos.cmake") 9 | 10 | # Set the project name 11 | project(${prj}) 12 | 13 | add_subdirectory(0_base) 14 | 15 | # Add all source files in the current directory 16 | set(demo_src "${CMAKE_CURRENT_SOURCE_DIR}/demo.c") 17 | 18 | set(src ${src} ${demo_src}) 19 | set(inc ${inc} ${CMAKE_CURRENT_SOURCE_DIR}) 20 | 21 | # Add the executable 22 | add_executable(${prj} ${src}) 23 | # Include directories 24 | target_include_directories(${prj} PUBLIC ${inc}) 25 | 26 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/log.cmake") 27 | -------------------------------------------------------------------------------- /10_deadlock_starvation_challenge/README.md: -------------------------------------------------------------------------------- 1 | # 10_deadlock_starvation_challenge (Dining Philosopher Problem Arbitrator Solution) 2 | ``` 3 | ../shell/rebuild_run_qemu.sh . 4 | ``` 5 | Challenge of [Introduction to RTOS Part 10 - Deadlock and Starvation](https://www.youtube.com/watch?v=hRsWi4HIENc&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=10) 6 | 7 | 8 | ## Terminal Output 9 | ``` 10 | Douglass waiting 11 | Hypatia waiting 12 | Confucius waiting 13 | Antisthenes waiting 14 | Cruz waiting 15 | Cruz got left 16 | Cruz :) 17 | Cruz :D 18 | Cruz gave right 19 | Cruz gave left 20 | Douglass got left 21 | Douglass :) 22 | Cruz waiting 23 | Douglass :D 24 | Douglass gave right 25 | Douglass gave left 26 | Douglass waiting 27 | Hypatia got left 28 | Hypatia :) 29 | Hypatia :D 30 | Hypatia gave right 31 | Hypatia gave left 32 | Confucius got left 33 | Confucius :) 34 | Hypatia waiting 35 | Confucius :D 36 | Confucius gave right 37 | Confucius gave left 38 | Antisthenes got left 39 | Antisthenes :) 40 | Confucius waiting 41 | Antisthenes :D 42 | Antisthenes gave right 43 | Antisthenes gave left 44 | ``` 45 | ## Notes 46 | Use demo_init function in demo.c to implement your demo application. 47 | Run in debug console to dump the trace 48 | -exec dump binary value trace.bin *RecorderDataPtr -------------------------------------------------------------------------------- /11_priority_inversion/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch_QEMU", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/demo", 12 | "cwd": "${workspaceFolder}", 13 | "miDebuggerPath": "${env:GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gdb-py", 14 | "miDebuggerServerAddress": "localhost:1234", 15 | "stopAtEntry": true, 16 | "preLaunchTask": "Run_QEMU", 17 | }, 18 | ] 19 | } -------------------------------------------------------------------------------- /11_priority_inversion/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Clean_Build", 8 | "type": "shell", 9 | "command": "${workspaceFolder}/../shell/rebuild.sh ${workspaceFolder} -DDEMO_UNBOUNDED_C:BOOL=ON" 10 | }, 11 | { 12 | "label": "Run_QEMU", 13 | "type": "shell", 14 | "command": "${workspaceFolder}/../shell/rebuild_run_qemu.sh ${workspaceFolder} debug -DDEMO_UNBOUNDED_C:BOOL=ON", 15 | "isBackground": true, 16 | "problemMatcher": [ 17 | { 18 | "pattern": [ 19 | { 20 | "regexp": ".", 21 | "file": 1, 22 | "location": 2, 23 | "message": 3 24 | } 25 | ], 26 | "background": { 27 | "activeOnStart": true, 28 | "beginsPattern": ".", 29 | "endsPattern": "QEMU_started", 30 | } 31 | } 32 | ] 33 | }, 34 | ] 35 | } -------------------------------------------------------------------------------- /11_priority_inversion/0_base: -------------------------------------------------------------------------------- 1 | ../0_base -------------------------------------------------------------------------------- /11_priority_inversion/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(prj demo) 4 | 5 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/arm.cmake") 6 | set(freertos_root "${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/FreeRTOS") 7 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/common_demo.cmake") 8 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/freertos.cmake") 9 | 10 | # Set the project name 11 | project(${prj}) 12 | 13 | set(demo_src "") 14 | 15 | if(DEMO_UNBOUNDED_C) 16 | message(STATUS "demo_unbounded.c is going to be used") 17 | set(demo_src "demo_unbounded.c") 18 | endif() 19 | 20 | if(DEMO_INHERITANCE_C) 21 | message(STATUS "demo_inheritance.c is going to be used") 22 | set(demo_src "demo_inheritance.c") 23 | endif() 24 | 25 | if(NOT demo_src) 26 | message(WARNING "No demo source file specified.") 27 | message(STATUS "demo_unbounded.c is going to be used") 28 | set(demo_src "demo_unbounded.c") 29 | endif() 30 | 31 | add_subdirectory(0_base) 32 | 33 | # Add all source files in the current directory 34 | set(demo_src "${CMAKE_CURRENT_SOURCE_DIR}/${demo_src}") 35 | 36 | set(src ${src} ${demo_src}) 37 | set(inc ${inc} ${CMAKE_CURRENT_SOURCE_DIR}) 38 | 39 | # Add the executable 40 | add_executable(${prj} ${src}) 41 | # Include directories 42 | target_include_directories(${prj} PUBLIC ${inc}) 43 | 44 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/log.cmake") 45 | -------------------------------------------------------------------------------- /11_priority_inversion/README.md: -------------------------------------------------------------------------------- 1 | # 11_priority_inversion 2 | ``` 3 | ../shell/rebuild_run_qemu.sh . -DDEMO_UNBOUNDED_C:BOOL=ON 4 | ``` 5 | ``` 6 | ../shell/rebuild_run_qemu.sh . -DDEMO_INHERITANCE_C:BOOL=ON 7 | ``` 8 | [Introduction to RTOS Part 11 - Priority Inversion](https://www.youtube.com/watch?v=C2xKhxROmhA&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=11) 9 | 10 | 11 | ## Terminal Output 12 | 13 | DEMO_UNBOUNDED_C 14 | (H) lock acquired. Wait time: 5001 15 | ``` 16 | (L) trying to acquire lock. 17 | 18 | (L) lock acquired. Wait time: 0 19 | (H) trying to acquire lock. 20 | 21 | (M) worky work. 22 | 23 | (M) sleppy. 24 | 25 | (L) lock released. 26 | 27 | (H) lock acquired. Wait time: 5001 28 | (H) lock released. 29 | 30 | (H) sleepy. 31 | ``` 32 | 33 | DEMO_INHERITANCE_C: It is still priority inversion but bounded. 34 | (H) lock acquired. Wait time: 241 35 | ``` 36 | (L) trying to acquire lock. 37 | 38 | (L) lock acquired. Wait time: 1 39 | (H) trying to acquire lock. 40 | 41 | (L) lock released. 42 | 43 | (H) lock acquired. Wait time: 241 44 | (H) lock released. 45 | 46 | (H) sleepy. 47 | 48 | (M) worky work. 49 | ``` 50 | ## Notes 51 | Use demo_init function in demo.c to implement your demo application. 52 | Run in debug console to dump the trace 53 | -exec dump binary value trace.bin *RecorderDataPtr -------------------------------------------------------------------------------- /11_priority_inversion_challenge/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch_QEMU", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/demo", 12 | "cwd": "${workspaceFolder}", 13 | "miDebuggerPath": "${env:GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gdb-py", 14 | "miDebuggerServerAddress": "localhost:1234", 15 | "stopAtEntry": true, 16 | "preLaunchTask": "Run_QEMU", 17 | }, 18 | ] 19 | } -------------------------------------------------------------------------------- /11_priority_inversion_challenge/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Clean_Build", 8 | "type": "shell", 9 | "command": "${workspaceFolder}/../shell/rebuild.sh ${workspaceFolder}" 10 | }, 11 | { 12 | "label": "Run_QEMU", 13 | "type": "shell", 14 | "command": "${workspaceFolder}/../shell/rebuild_run_qemu.sh ${workspaceFolder} debug", 15 | "isBackground": true, 16 | "problemMatcher": [ 17 | { 18 | "pattern": [ 19 | { 20 | "regexp": ".", 21 | "file": 1, 22 | "location": 2, 23 | "message": 3 24 | } 25 | ], 26 | "background": { 27 | "activeOnStart": true, 28 | "beginsPattern": ".", 29 | "endsPattern": "QEMU_started", 30 | } 31 | } 32 | ] 33 | }, 34 | ] 35 | } -------------------------------------------------------------------------------- /11_priority_inversion_challenge/0_base: -------------------------------------------------------------------------------- 1 | ../0_base -------------------------------------------------------------------------------- /11_priority_inversion_challenge/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(prj demo) 4 | 5 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/arm.cmake") 6 | set(freertos_root "${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/FreeRTOS") 7 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/common_demo.cmake") 8 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/freertos.cmake") 9 | 10 | # Set the project name 11 | project(${prj}) 12 | 13 | add_subdirectory(0_base) 14 | 15 | # Add all source files in the current directory 16 | set(demo_src "${CMAKE_CURRENT_SOURCE_DIR}/demo.c") 17 | 18 | set(src ${src} ${demo_src}) 19 | set(inc ${inc} ${CMAKE_CURRENT_SOURCE_DIR}) 20 | 21 | # Add the executable 22 | add_executable(${prj} ${src}) 23 | # Include directories 24 | target_include_directories(${prj} PUBLIC ${inc}) 25 | 26 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/log.cmake") 27 | -------------------------------------------------------------------------------- /11_priority_inversion_challenge/README.md: -------------------------------------------------------------------------------- 1 | # 11_priority_inversion 2 | ``` 3 | ../shell/rebuild_run_qemu.sh . 4 | ``` 5 | Challenge of [Introduction to RTOS Part 11 - Priority Inversion](https://www.youtube.com/watch?v=C2xKhxROmhA&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=11) 6 | 7 | ## Note 8 | When xTaskGetTickCount is used like in video, systick interrupt is disabled and xTickCount gets never updated. 9 | This happens at least for my setup, if you have solution to this feel free to open PR to me. 10 | As a workaround I used demo_hw_getSysOnTimeMs which is not depended on an interrupt. Anyways this does not effect concept of tutorial. 11 | 12 | ## Terminal Output 13 | 14 | ``` 15 | (L) lock acquired. Wait time: 1 16 | 17 | (L) lock released. 18 | 19 | 20 | (L) sleepy. 21 | 22 | 23 | (H) trying to acquire lock. 24 | 25 | 26 | (H) lock acquired. Wait time: 0 27 | 28 | (H) lock released. 29 | 30 | 31 | (H) sleepy. 32 | 33 | 34 | (M) worky work. 35 | 36 | 37 | (H) trying to acquire lock. 38 | 39 | 40 | (H) lock acquired. Wait time: 0 41 | 42 | (H) lock released. 43 | 44 | 45 | (H) sleepy. 46 | ``` 47 | 48 | ## Notes 49 | Use demo_init function in demo.c to implement your demo application. 50 | Run in debug console to dump the trace 51 | -exec dump binary value trace.bin *RecorderDataPtr -------------------------------------------------------------------------------- /2_blinky/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch_QEMU", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/demo", 12 | "cwd": "${workspaceFolder}", 13 | "miDebuggerPath": "${env:GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gdb-py", 14 | "miDebuggerServerAddress": "localhost:1234", 15 | "stopAtEntry": true, 16 | "preLaunchTask": "Run_QEMU", 17 | }, 18 | ] 19 | } -------------------------------------------------------------------------------- /2_blinky/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "freertos.h": "c", 4 | "demo_hw.h": "c" 5 | } 6 | } -------------------------------------------------------------------------------- /2_blinky/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Clean_Build", 8 | "type": "shell", 9 | "command": "${workspaceFolder}/../shell/rebuild.sh ${workspaceFolder}" 10 | }, 11 | { 12 | "label": "Run_QEMU", 13 | "type": "shell", 14 | "command": "${workspaceFolder}/../shell/rebuild_run_qemu.sh ${workspaceFolder} debug", 15 | "isBackground": true, 16 | "problemMatcher": [ 17 | { 18 | "pattern": [ 19 | { 20 | "regexp": ".", 21 | "file": 1, 22 | "location": 2, 23 | "message": 3 24 | } 25 | ], 26 | "background": { 27 | "activeOnStart": true, 28 | "beginsPattern": ".", 29 | "endsPattern": "QEMU_started", 30 | } 31 | } 32 | ] 33 | }, 34 | ] 35 | } -------------------------------------------------------------------------------- /2_blinky/0_base: -------------------------------------------------------------------------------- 1 | ../0_base -------------------------------------------------------------------------------- /2_blinky/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(prj demo) 4 | 5 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/arm.cmake") 6 | set(freertos_root "${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/FreeRTOS") 7 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/common_demo.cmake") 8 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/freertos.cmake") 9 | 10 | # Set the project name 11 | project(${prj}) 12 | 13 | add_subdirectory(0_base) 14 | 15 | # Add all source files in the current directory 16 | file(GLOB demo_src "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 17 | 18 | set(src ${src} ${demo_src}) 19 | set(inc ${inc} ${CMAKE_CURRENT_SOURCE_DIR}) 20 | 21 | # Add the executable 22 | add_executable(${prj} ${src}) 23 | # Include directories 24 | target_include_directories(${prj} PUBLIC ${inc}) 25 | 26 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/log.cmake") 27 | -------------------------------------------------------------------------------- /2_blinky/README.md: -------------------------------------------------------------------------------- 1 | # 2_blinky 2 | 3 | Blinks every 1 second. 4 | ``` 5 | ../shell/rebuild_run_qemu.sh . 6 | ``` 7 | 8 | ## Terminal Output 9 | ``` 10 | led: 0 11 | ``` 12 | ## Notes 13 | Use demo_init function in demo.c to implement your demo application. 14 | Run in debug console to dump the trace 15 | -exec dump binary value trace.bin *RecorderDataPtr -------------------------------------------------------------------------------- /2_blinky/demo.c: -------------------------------------------------------------------------------- 1 | /* Kernel includes. */ 2 | #include "FreeRTOS.h" 3 | #include "task.h" 4 | // demo hardware 5 | #include "demo_hw.h" 6 | #include "timers.h" 7 | 8 | #define DEFAULT_TASK_LOOP_PRIORITY (tskIDLE_PRIORITY + 1) 9 | #define DEFAULT_TASK_STACK_SIZE (1024u) 10 | 11 | static void _blinkTask(void * pvParameters); 12 | 13 | void demo_init(void) { 14 | xTaskCreate( 15 | _blinkTask, // pvTaskCode 16 | "blink", // pcName 17 | DEFAULT_TASK_STACK_SIZE, // uxStackDepth 18 | NULL, // pvParameters 19 | DEFAULT_TASK_LOOP_PRIORITY, // uxPriority 20 | NULL // pxCreatedTask 21 | ); 22 | 23 | vTaskStartScheduler(); 24 | 25 | for( ; ; ) 26 | { 27 | } 28 | } 29 | 30 | static void _blinkTask( void * pvParameters ) { 31 | /* Prevent the compiler warning about the unused parameter. */ 32 | (void)pvParameters; 33 | uint32_t sysOnTime = 0; 34 | for( ;; ) { 35 | sysOnTime = demo_hw_getSysOnTimeMs(); 36 | demo_hw_term_printf("SysOnTime: %d ms\n", (int)sysOnTime); 37 | vTaskDelay( pdMS_TO_TICKS( 1000 ) ); 38 | demo_hw_led_toggle(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /3_task_scheduling/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch_QEMU", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/demo", 12 | "cwd": "${workspaceFolder}", 13 | "miDebuggerPath": "${env:GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gdb-py", 14 | "miDebuggerServerAddress": "localhost:1234", 15 | "stopAtEntry": true, 16 | "preLaunchTask": "Run_QEMU", 17 | }, 18 | ] 19 | } -------------------------------------------------------------------------------- /3_task_scheduling/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Clean_Build", 8 | "type": "shell", 9 | "command": "${workspaceFolder}/../shell/rebuild.sh ${workspaceFolder}" 10 | }, 11 | { 12 | "label": "Run_QEMU", 13 | "type": "shell", 14 | "command": "${workspaceFolder}/../shell/rebuild_run_qemu.sh ${workspaceFolder} debug", 15 | "isBackground": true, 16 | "problemMatcher": [ 17 | { 18 | "pattern": [ 19 | { 20 | "regexp": ".", 21 | "file": 1, 22 | "location": 2, 23 | "message": 3 24 | } 25 | ], 26 | "background": { 27 | "activeOnStart": true, 28 | "beginsPattern": ".", 29 | "endsPattern": "QEMU_started", 30 | } 31 | } 32 | ] 33 | }, 34 | ] 35 | } -------------------------------------------------------------------------------- /3_task_scheduling/0_base: -------------------------------------------------------------------------------- 1 | ../0_base -------------------------------------------------------------------------------- /3_task_scheduling/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(prj demo) 4 | 5 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/arm.cmake") 6 | set(freertos_root "${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/FreeRTOS") 7 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/common_demo.cmake") 8 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/freertos.cmake") 9 | 10 | # Set the project name 11 | project(${prj}) 12 | 13 | add_subdirectory(0_base) 14 | 15 | # Add all source files in the current directory 16 | file(GLOB demo_src "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 17 | 18 | set(src ${src} ${demo_src}) 19 | set(inc ${inc} ${CMAKE_CURRENT_SOURCE_DIR}) 20 | 21 | # Add the executable 22 | add_executable(${prj} ${src}) 23 | # Include directories 24 | target_include_directories(${prj} PUBLIC ${inc}) 25 | 26 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/log.cmake") 27 | -------------------------------------------------------------------------------- /3_task_scheduling/README.md: -------------------------------------------------------------------------------- 1 | # 3_task_scheduling 2 | 3 | ``` 4 | ../shell/rebuild_run_qemu.sh . 5 | ``` 6 | [Introduction to RTOS Part 3 - Task Scheduling | Digi-Key Electronics](https://www.youtube.com/watch?v=95yUbClyf3E&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=3) 7 | 8 | Task2 has higher priority and preempts task1. 9 | ![Task2 preempts Task1](./doc/taskPreemption.png "Task2 preempts Task1") 10 | 11 | ## Terminal Output 12 | ``` 13 | *Bar*kad*eer* b*rig* Ar*r b*oo*ty *rum*. 14 | 15 | Barkadeer brig Arr booty rum. 16 | ******** 17 | B*ar*kad*ee*r *bri*g *Arr* b*oot*y *ru*m. 18 | 19 | Barkadeer brig Arr booty rum. 20 | ******** 21 | B*ar*kad*ee*r b*ri*g A*rr* bo*oty* r*um.* 22 | 23 | Barkadeer brig Arr booty rum. 24 | ******** 25 | B*ar*ka*dee*r *br*ig *Ar*r b*oo*ty* ru*m.* 26 | Task1 deleted.*********** 27 | ``` 28 | 29 | ## Notes 30 | Use demo_init function in demo.c to implement your demo application. 31 | Run in debug console to dump the trace 32 | -exec dump binary value trace.bin *RecorderDataPtr -------------------------------------------------------------------------------- /3_task_scheduling/demo.c: -------------------------------------------------------------------------------- 1 | /* Kernel includes. */ 2 | #include "FreeRTOS.h" 3 | #include "task.h" 4 | #include "demo_hw.h" 5 | 6 | 7 | #define LOOP_PRIORITY (tskIDLE_PRIORITY + 1) 8 | #define TASK1_PRIORITY (tskIDLE_PRIORITY + 2) 9 | #define TASK2_PRIORITY (tskIDLE_PRIORITY + 3) 10 | #define DEFAULT_TASK_STACK_SIZE (1024u) 11 | 12 | static void _task1(void *parameter); 13 | static void _task2(void *parameter); 14 | static void _loop(void *parameter); 15 | static void _slowTermWriteLine(const char *s); 16 | 17 | TaskHandle_t _task1Handle = NULL; 18 | TaskHandle_t _task2Handle = NULL; 19 | 20 | void demo_init(void) { 21 | xTaskCreate(_task1, 22 | "_task1", 23 | DEFAULT_TASK_STACK_SIZE, 24 | NULL, 25 | TASK1_PRIORITY, 26 | &_task1Handle); 27 | 28 | xTaskCreate(_task2, 29 | "_task2", 30 | DEFAULT_TASK_STACK_SIZE, 31 | NULL, 32 | TASK2_PRIORITY, 33 | &_task2Handle); 34 | 35 | xTaskCreate(_loop, 36 | "_loop", 37 | DEFAULT_TASK_STACK_SIZE, 38 | NULL, 39 | LOOP_PRIORITY, 40 | NULL); 41 | 42 | /* Start the tasks and timer running. */ 43 | vTaskStartScheduler(); 44 | } 45 | 46 | static void _slowTermWriteChar(const char c) { 47 | int j; 48 | for(j = 0; j < 10000000; j++) { 49 | __asm__("nop"); 50 | } 51 | demo_hw_term_writeChar(c); 52 | } 53 | 54 | static void _slowTermWriteLine(const char *s) { 55 | for (size_t i = 0; s[i] != '\0'; i++) { 56 | _slowTermWriteChar(s[i]); 57 | } 58 | demo_hw_term_writeChar('\n'); 59 | } 60 | 61 | 62 | static void _loop(void *parameter) { 63 | /* Prevent the compiler warning about the unused parameter. */ 64 | (void)parameter; 65 | uint8_t i = 0; 66 | while(1) { 67 | for(i = 0; i < 3; ++i) 68 | { 69 | vTaskSuspend( _task2Handle ); 70 | vTaskDelay( pdMS_TO_TICKS( 2000 ) ); 71 | vTaskResume( _task2Handle ); 72 | vTaskDelay( pdMS_TO_TICKS( 2000 ) ); 73 | } 74 | 75 | if(_task1Handle != NULL) { 76 | vTaskDelete(_task1Handle); 77 | _task1Handle = NULL; 78 | demo_hw_term_writeLine("Task1 deleted."); 79 | } 80 | } 81 | } 82 | 83 | static void _task1( void * parameter ) { 84 | /* Prevent the compiler warning about the unused parameter. */ 85 | (void)parameter; 86 | for( ;; ) { 87 | _slowTermWriteLine("Barkadeer brig Arr booty rum."); 88 | vTaskDelay( pdMS_TO_TICKS( 1000 ) ); 89 | } 90 | } 91 | 92 | static void _task2( void * parameter ) { 93 | /* Prevent the compiler warning about the unused parameter. */ 94 | (void)parameter; 95 | for( ;; ) { 96 | vTaskDelay( pdMS_TO_TICKS( 100 ) ); 97 | _slowTermWriteChar('*'); 98 | } 99 | } -------------------------------------------------------------------------------- /3_task_scheduling/doc/taskPreemption.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aslansq/freertos_intro_qemu/28e98a29457cd92d517eebcb9b67189bbf197faa/3_task_scheduling/doc/taskPreemption.png -------------------------------------------------------------------------------- /3_task_scheduling_challenge/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch_QEMU", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/demo", 12 | "cwd": "${workspaceFolder}", 13 | "miDebuggerPath": "${env:GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gdb-py", 14 | "miDebuggerServerAddress": "localhost:1234", 15 | "stopAtEntry": true, 16 | "preLaunchTask": "Run_QEMU", 17 | }, 18 | ] 19 | } -------------------------------------------------------------------------------- /3_task_scheduling_challenge/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Clean_Build", 8 | "type": "shell", 9 | "command": "${workspaceFolder}/../shell/rebuild.sh ${workspaceFolder}" 10 | }, 11 | { 12 | "label": "Run_QEMU", 13 | "type": "shell", 14 | "command": "${workspaceFolder}/../shell/rebuild_run_qemu.sh ${workspaceFolder} debug", 15 | "isBackground": true, 16 | "problemMatcher": [ 17 | { 18 | "pattern": [ 19 | { 20 | "regexp": ".", 21 | "file": 1, 22 | "location": 2, 23 | "message": 3 24 | } 25 | ], 26 | "background": { 27 | "activeOnStart": true, 28 | "beginsPattern": ".", 29 | "endsPattern": "QEMU_started", 30 | } 31 | } 32 | ] 33 | }, 34 | ] 35 | } -------------------------------------------------------------------------------- /3_task_scheduling_challenge/0_base: -------------------------------------------------------------------------------- 1 | ../0_base -------------------------------------------------------------------------------- /3_task_scheduling_challenge/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(prj demo) 4 | 5 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/arm.cmake") 6 | set(freertos_root "${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/FreeRTOS") 7 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/common_demo.cmake") 8 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/freertos.cmake") 9 | 10 | # Set the project name 11 | project(${prj}) 12 | 13 | add_subdirectory(0_base) 14 | 15 | # Add all source files in the current directory 16 | file(GLOB demo_src "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 17 | 18 | set(src ${src} ${demo_src}) 19 | set(inc ${inc} ${CMAKE_CURRENT_SOURCE_DIR}) 20 | 21 | # Add the executable 22 | add_executable(${prj} ${src}) 23 | # Include directories 24 | target_include_directories(${prj} PUBLIC ${inc}) 25 | 26 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/log.cmake") 27 | -------------------------------------------------------------------------------- /3_task_scheduling_challenge/README.md: -------------------------------------------------------------------------------- 1 | # 3_task_scheduling 2 | 3 | ``` 4 | ../shell/rebuild_run_qemu.sh . 5 | ``` 6 | 7 | Challenge of [Introduction to RTOS Part 3 - Task Scheduling | Digi-Key Electronics](https://www.youtube.com/watch?v=95yUbClyf3E&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=3) 8 | 9 | At highligted timestamp, I(the user) entered 100 ms request. You could see context switch of led task timestamp are now 100ms intervals. 10 | ![User selectable blink rate](./doc/userInputLedDelay.png "User selectable blink rate") 11 | 12 | ## Terminal Output 13 | ``` 14 | Enter LED delay(ms): 15 | Led delay updated to(ms): 100 16 | ``` 17 | 18 | ## Notes 19 | Use demo_init function in demo.c to implement your demo application. 20 | Run in debug console to dump the trace 21 | -exec dump binary value trace.bin *RecorderDataPtr -------------------------------------------------------------------------------- /3_task_scheduling_challenge/demo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* Kernel includes. */ 6 | #include "FreeRTOS.h" 7 | #include "task.h" 8 | #include "demo_hw.h" 9 | 10 | #define TASK_INPUT_PRIORITY (tskIDLE_PRIORITY + 1) 11 | #define TASK_LED_PRIORITY (tskIDLE_PRIORITY + 1) 12 | #define DEFAULT_TASK_STACK_SIZE 1024 13 | 14 | static void _taskInput(void *parameter); 15 | static void _taskLed(void *parameter); 16 | 17 | static int _ledDelay = 1000; 18 | 19 | void demo_init(void) { 20 | xTaskCreate(_taskInput, 21 | "in", 22 | DEFAULT_TASK_STACK_SIZE, 23 | NULL, 24 | TASK_INPUT_PRIORITY, 25 | NULL); 26 | 27 | xTaskCreate(_taskLed, 28 | "led", 29 | DEFAULT_TASK_STACK_SIZE, 30 | NULL, 31 | TASK_LED_PRIORITY, 32 | NULL); 33 | 34 | /* Start the tasks and timer running. */ 35 | vTaskStartScheduler(); 36 | } 37 | 38 | static void _taskInput( void * parameter ) { 39 | /* Prevent the compiler warning about the unused parameter. */ 40 | (void)parameter; 41 | demo_hw_term_writeLine("Enter LED delay(ms):"); 42 | int inledDelay = 0; 43 | int r; 44 | char buf[50]; 45 | 46 | for( ;; ) { 47 | r = demo_hw_term_readLine(buf, sizeof(buf)); 48 | if(r >= 0) { 49 | inledDelay = atoi(buf); 50 | _ledDelay = inledDelay; 51 | demo_hw_term_printf("Led delay updated to(ms): %d", _ledDelay); 52 | demo_hw_term_writeChar('\n'); 53 | } 54 | } 55 | } 56 | 57 | static void _taskLed( void * parameter ) { 58 | /* Prevent the compiler warning about the unused parameter. */ 59 | (void)parameter; 60 | for( ;; ) { 61 | demo_hw_led_toggle(); 62 | vTaskDelay( pdMS_TO_TICKS( _ledDelay ) ); 63 | } 64 | } -------------------------------------------------------------------------------- /3_task_scheduling_challenge/doc/userInputLedDelay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aslansq/freertos_intro_qemu/28e98a29457cd92d517eebcb9b67189bbf197faa/3_task_scheduling_challenge/doc/userInputLedDelay.png -------------------------------------------------------------------------------- /4_memory/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch_QEMU", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/demo", 12 | "cwd": "${workspaceFolder}", 13 | "miDebuggerPath": "${env:GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gdb-py", 14 | "miDebuggerServerAddress": "localhost:1234", 15 | "stopAtEntry": true, 16 | "preLaunchTask": "Run_QEMU", 17 | }, 18 | ] 19 | } -------------------------------------------------------------------------------- /4_memory/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Clean_Build", 8 | "type": "shell", 9 | "command": "${workspaceFolder}/../shell/rebuild.sh ${workspaceFolder} -DDEMO_1_C:BOOL=ON" 10 | }, 11 | { 12 | "label": "Run_QEMU", 13 | "type": "shell", 14 | "command": "${workspaceFolder}/../shell/rebuild_run_qemu.sh ${workspaceFolder} debug -DDEMO_1_C:BOOL=ON", 15 | "isBackground": true, 16 | "problemMatcher": [ 17 | { 18 | "pattern": [ 19 | { 20 | "regexp": ".", 21 | "file": 1, 22 | "location": 2, 23 | "message": 3 24 | } 25 | ], 26 | "background": { 27 | "activeOnStart": true, 28 | "beginsPattern": ".", 29 | "endsPattern": "QEMU_started", 30 | } 31 | } 32 | ] 33 | }, 34 | ] 35 | } -------------------------------------------------------------------------------- /4_memory/0_base: -------------------------------------------------------------------------------- 1 | ../0_base -------------------------------------------------------------------------------- /4_memory/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(prj demo) 4 | 5 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/arm.cmake") 6 | set(freertos_root "${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/FreeRTOS") 7 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/common_demo.cmake") 8 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/freertos.cmake") 9 | 10 | # Set the project name 11 | project(${prj}) 12 | 13 | set(demo_src "") 14 | 15 | if(DEMO_1_C) 16 | message(STATUS "demo1.c is going to be used") 17 | set(demo_src "demo1.c") 18 | endif() 19 | 20 | if(DEMO_2_C) 21 | message(STATUS "demo2.c is going to be used") 22 | set(demo_src "demo2.c") 23 | endif() 24 | 25 | if(DEMO_3_C) 26 | message(STATUS "demo3.c is going to be used") 27 | set(demo_src "demo3.c") 28 | endif() 29 | 30 | if(DEMO_4_C) 31 | message(STATUS "demo4.c is going to be used") 32 | set(demo_src "demo4.c") 33 | endif() 34 | 35 | if(DEMO_5_C) 36 | message(STATUS "demo5.c is going to be used") 37 | set(demo_src "demo5.c") 38 | endif() 39 | 40 | if(DEMO_6_C) 41 | message(STATUS "demo6.c is going to be used") 42 | set(demo_src "demo6.c") 43 | endif() 44 | 45 | if(NOT demo_src) 46 | message(WARNING "No demo source file specified.") 47 | message(STATUS "demo1.c is going to be used") 48 | set(demo_src "demo1.c") 49 | endif() 50 | 51 | add_subdirectory(0_base) 52 | 53 | # Add all source files in the current directory 54 | set(demo_src "${CMAKE_CURRENT_SOURCE_DIR}/${demo_src}") 55 | 56 | set(src ${src} ${demo_src}) 57 | set(inc ${inc} ${CMAKE_CURRENT_SOURCE_DIR}) 58 | 59 | # Add the executable 60 | add_executable(${prj} ${src}) 61 | # Include directories 62 | target_include_directories(${prj} PUBLIC ${inc}) 63 | 64 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/log.cmake") 65 | -------------------------------------------------------------------------------- /4_memory/README.md: -------------------------------------------------------------------------------- 1 | # 4_memory 2 | 3 | [Introduction to RTOS Part 4 - Memory Management ](https://www.youtube.com/watch?v=Qske3yZRW5I&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=4) 4 | 5 | This file demonstrates memory management in FreeRTOS 6 | Explanation of demos: 7 | 8 | DEMO_1_C overflow stack by recursive call 9 | ``` 10 | ../shell/rebuild_run_qemu.sh . -DDEMO_1_C:BOOL=ON 11 | ``` 12 | 13 | DEMO_2_C allocating huge array in stack to ovf 14 | ``` 15 | ../shell/rebuild_run_qemu.sh . -DDEMO_2_C:BOOL=ON 16 | ``` 17 | 18 | DEMO_3_C ovf heap u32 at a time 19 | ``` 20 | ../shell/rebuild_run_qemu.sh . -DDEMO_3_C:BOOL=ON 21 | ``` 22 | 23 | DEMO_4_C ovf heap in single shot 24 | ``` 25 | ../shell/rebuild_run_qemu.sh . -DDEMO_4_C:BOOL=ON 26 | ``` 27 | 28 | DEMO_5_C properly malloc and free. this should be fine 29 | ``` 30 | ../shell/rebuild_run_qemu.sh . -DDEMO_5_C:BOOL=ON 31 | ``` 32 | 33 | DEMO_6_C overflow of static stack by recursive call 34 | ``` 35 | ../shell/rebuild_run_qemu.sh . -DDEMO_6_C:BOOL=ON 36 | ``` 37 | 38 | default DEMO_1_C 39 | ``` 40 | ../shell/rebuild_run_qemu.sh . 41 | ``` 42 | 43 | ## Terminal Output 44 | Terminal output of DEMO_1_C: 45 | ``` 46 | rem: 0 tec: 574 47 | rem: 0 tec: 575 48 | re 49 | 50 | Stack overflow in A 51 | ``` 52 | 53 | ## Notes 54 | Use demo_init function in demo.c to implement your demo application. 55 | Run in debug console to dump the trace 56 | -exec dump binary value trace.bin *RecorderDataPtr -------------------------------------------------------------------------------- /4_memory/demo1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Kernel includes. */ 5 | #include "FreeRTOS.h" 6 | #include "task.h" 7 | #include "demo_hw.h" 8 | 9 | #define DEFAULT_PRIORITY (tskIDLE_PRIORITY + 1) 10 | #define DEFAULT_STACK_SIZE (1024u) 11 | 12 | static void _taskA( void * pvParameters ); 13 | 14 | void demo_init(void) { 15 | 16 | xTaskCreate(_taskA, 17 | "A", 18 | DEFAULT_STACK_SIZE, 19 | NULL, 20 | DEFAULT_PRIORITY, 21 | NULL ); 22 | 23 | vTaskStartScheduler(); 24 | 25 | for( ; ; ) 26 | { 27 | } 28 | } 29 | 30 | // demo 1 : overflow stack by recursive call 31 | static void _taskA( void * pvParameters ) { 32 | // this made static, so it does not effect stack 33 | static int taskEntryCount = 0; 34 | for( ;; ) { 35 | demo_hw_term_printf("rem: %d tec: %d\n", (int)uxTaskGetStackHighWaterMark(NULL), taskEntryCount++); 36 | // lets ovf to see what happens to RTOS 37 | _taskA(NULL); 38 | } 39 | } 40 | //rem: 0 tec: 574 41 | //rem: 0 tec: 575 42 | //re 43 | // 44 | //Stack overflow in A 45 | -------------------------------------------------------------------------------- /4_memory/demo2.c: -------------------------------------------------------------------------------- 1 | #include "demo_hw.h" 2 | 3 | /* Kernel includes. */ 4 | #include "FreeRTOS.h" 5 | #include "task.h" 6 | 7 | #define DEFAULT_PRIORITY (tskIDLE_PRIORITY + 1) 8 | #define DEFAULT_STACK_SIZE (1024u) 9 | 10 | static void _taskA( void * pvParameters ); 11 | static void _taskB( void * pvParameters ); 12 | 13 | void demo_init(void) { 14 | 15 | xTaskCreate(_taskA, 16 | "A", 17 | DEFAULT_STACK_SIZE, 18 | NULL, 19 | DEFAULT_PRIORITY, 20 | NULL ); 21 | 22 | xTaskCreate(_taskB, 23 | "B", 24 | DEFAULT_STACK_SIZE, 25 | NULL, 26 | DEFAULT_PRIORITY, 27 | NULL ); 28 | 29 | vTaskStartScheduler(); 30 | 31 | for( ; ; ) 32 | { 33 | } 34 | } 35 | 36 | // This task survives, if there is no other task. 37 | // demo 2 : allocating huge array in stack to ovf. 38 | static void _taskA( void * pvParameters ) { 39 | uint32_t myHugeArray[DEFAULT_STACK_SIZE+1]; 40 | demo_hw_term_printf("remStack: %d\n", (int)uxTaskGetStackHighWaterMark(NULL)); 41 | uint32_t anotherU32 = 0; 42 | demo_hw_term_printf("remStack: %d\n", (int)uxTaskGetStackHighWaterMark(NULL)); 43 | uint32_t idx = 0; 44 | 45 | while(1) { // to see if task survives and prints remaining stack constantly 46 | // implementing sth so compiler does not optimize out 47 | myHugeArray[idx] = idx; 48 | myHugeArray[idx]++; 49 | myHugeArray[idx]--; 50 | anotherU32++; 51 | idx++; 52 | if(idx == (DEFAULT_STACK_SIZE+1)) { 53 | idx = 0; 54 | } 55 | 56 | int remStack = (int)uxTaskGetStackHighWaterMark(NULL); 57 | if (remStack) { 58 | demo_hw_term_printf("remStack: %d\n", remStack); 59 | } else { 60 | demo_hw_term_printf("no remStack\n"); 61 | } 62 | } 63 | } 64 | 65 | // output when when _taskB defined. 66 | //no remStack 67 | //no 68 | // 69 | //Stack overflow in A 70 | // dummy task. purpose of this function: context switching happens between A and B 71 | static void _taskB( void * pvParameters ) { 72 | uint32_t arr[DEFAULT_STACK_SIZE/2]; 73 | uint32_t idx = 0; 74 | for(;;) { 75 | // implementing sth so compiler does not optimize out 76 | arr[idx] = idx; 77 | arr[idx]++; 78 | arr[idx]--; 79 | idx++; 80 | if(idx == DEFAULT_STACK_SIZE/2) { 81 | idx = 0; 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /4_memory/demo3.c: -------------------------------------------------------------------------------- 1 | /* Kernel includes. */ 2 | #include "FreeRTOS.h" 3 | #include "task.h" 4 | #include "demo_hw.h" 5 | 6 | #define DEFAULT_PRIORITY (tskIDLE_PRIORITY + 1) 7 | #define DEFAULT_STACK_SIZE (1024u) 8 | 9 | static void _taskA( void * pvParameters ); 10 | 11 | void demo_init(void) { 12 | 13 | xTaskCreate(_taskA, 14 | "A", 15 | DEFAULT_STACK_SIZE, 16 | NULL, 17 | DEFAULT_PRIORITY, 18 | NULL ); 19 | 20 | vTaskStartScheduler(); 21 | 22 | for( ; ; ) 23 | { 24 | } 25 | } 26 | 27 | // demo 3 : ovf heap u32 at a time 28 | static void _taskA( void * pvParameters ) { 29 | for(;;) { 30 | // lets ovf heap u32 at a time 31 | uint32_t *ptr = (uint32_t *)pvPortMalloc(sizeof(uint32_t)); 32 | if(ptr != NULL) { // doing sth so compiler does not complain 33 | ptr[0]++; 34 | } 35 | uint32_t remHeap = xPortGetFreeHeapSize(); 36 | if(remHeap) { 37 | demo_hw_term_printf("remHeap %d\n", (int)remHeap); 38 | } else { 39 | demo_hw_term_printf("no remHeap\n"); 40 | } 41 | } 42 | } 43 | //remHeap 40 44 | //remHeap 24 45 | //no heapRem 46 | // 47 | // 48 | //Malloc failed 49 | -------------------------------------------------------------------------------- /4_memory/demo4.c: -------------------------------------------------------------------------------- 1 | /* Kernel includes. */ 2 | #include "FreeRTOS.h" 3 | #include "task.h" 4 | #include "demo_hw.h" 5 | 6 | #define DEFAULT_PRIORITY (tskIDLE_PRIORITY + 1) 7 | #define DEFAULT_STACK_SIZE (1024u) 8 | 9 | static void _taskA( void * pvParameters ); 10 | 11 | void demo_init(void) { 12 | 13 | xTaskCreate(_taskA, 14 | "A", 15 | DEFAULT_STACK_SIZE, 16 | NULL, 17 | DEFAULT_PRIORITY, 18 | NULL ); 19 | 20 | vTaskStartScheduler(); 21 | 22 | for( ; ; ) 23 | { 24 | } 25 | } 26 | 27 | // demo 4: ovf heap in single shot 28 | static void _taskA( void * pvParameters ) { 29 | // heap ovf single shot 30 | uint32_t *ptr = (uint32_t *)pvPortMalloc(sizeof(uint32_t)*UINT32_MAX); 31 | if(ptr != NULL) { // doing sth so compiler does not complain 32 | ptr[0]++; 33 | } 34 | uint32_t remHeap = xPortGetFreeHeapSize(); 35 | if(remHeap) { 36 | demo_hw_term_printf("remHeap %d\n", (int)remHeap); 37 | } else { 38 | demo_hw_term_printf("no heapRem\n"); 39 | } 40 | for(;;) { 41 | } 42 | } 43 | // 44 | // 45 | //Malloc failed 46 | -------------------------------------------------------------------------------- /4_memory/demo5.c: -------------------------------------------------------------------------------- 1 | #include "FreeRTOS.h" 2 | #include "task.h" 3 | #include "demo_hw.h" 4 | 5 | #define DEFAULT_PRIORITY (tskIDLE_PRIORITY + 1) 6 | #define DEFAULT_STACK_SIZE (1024u) 7 | 8 | static void _taskA( void * pvParameters ); 9 | 10 | void demo_init(void) { 11 | 12 | xTaskCreate(_taskA, 13 | "A", 14 | DEFAULT_STACK_SIZE, 15 | NULL, 16 | DEFAULT_PRIORITY, 17 | NULL ); 18 | 19 | vTaskStartScheduler(); 20 | 21 | for( ; ; ) 22 | { 23 | } 24 | } 25 | 26 | // demo 5: heap alloc and free. this should be fine 27 | static void _taskA( void * pvParameters ) { 28 | for(;;) { 29 | // lets ovf heap u32 at a time 30 | uint32_t *ptr = (uint32_t *)pvPortMalloc(sizeof(uint32_t)); 31 | if(ptr != NULL) { // doing sth so compiler does not complain 32 | ptr[0]++; 33 | } 34 | uint32_t remHeap = xPortGetFreeHeapSize(); 35 | if(remHeap) { 36 | demo_hw_term_printf("remHeap %d\n", (int)remHeap); 37 | } else { 38 | demo_hw_term_printf("no heapRem\n"); 39 | } 40 | vPortFree(ptr); 41 | } 42 | } 43 | // it is fine, it just repeats below line 44 | //remHeap 57192 45 | //remHeap 57192 46 | //remHeap 57192 47 | -------------------------------------------------------------------------------- /4_memory/demo6.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Kernel includes. */ 5 | #include "FreeRTOS.h" 6 | #include "task.h" 7 | #include "demo_hw.h" 8 | 9 | #define DEFAULT_PRIORITY (tskIDLE_PRIORITY + 1) 10 | #define DEFAULT_STACK_SIZE (1024u) 11 | 12 | static void _taskA( void * pvParameters ); 13 | 14 | /* Structure that will hold the TCB of the task being created. */ 15 | static StaticTask_t _taskA_buffer; 16 | static StackType_t _taskA_stack[DEFAULT_STACK_SIZE]; 17 | 18 | void demo_init(void) { 19 | 20 | xTaskCreateStatic( 21 | _taskA, 22 | "A", 23 | DEFAULT_STACK_SIZE, 24 | NULL, 25 | DEFAULT_PRIORITY, 26 | _taskA_stack, 27 | &_taskA_buffer ); 28 | 29 | vTaskStartScheduler(); 30 | 31 | for( ; ; ) 32 | { 33 | } 34 | } 35 | 36 | // demo 6 : overflow of static stack by recursive call 37 | static void _taskA( void * pvParameters ) { 38 | (void)pvParameters; 39 | // these made static, so it does not effect stack 40 | static int taskEntryCount = 0; 41 | static int remStack; 42 | remStack = (int)uxTaskGetStackHighWaterMark(NULL); 43 | for( ;; ) { 44 | if(remStack) { 45 | demo_hw_term_printf("rem: %d tec: %d\n", remStack, taskEntryCount); 46 | } else { 47 | demo_hw_term_printf("no remStack tec: %d\n", taskEntryCount); 48 | } 49 | taskEntryCount++; 50 | // lets ovf to see what happens to RTOS 51 | _taskA(NULL); 52 | } 53 | } 54 | // it goes to hardfault instead of stack ovf hook. who knows why 55 | //rem: 0 tec: 497 56 | //rem: 0 tec: 498 57 | //rem: 0 tec: 499 58 | //Calling prvGetRegistersFromStack() from fault handle 59 | -------------------------------------------------------------------------------- /4_memory_challenge/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch_QEMU", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/demo", 12 | "cwd": "${workspaceFolder}", 13 | "miDebuggerPath": "${env:GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gdb-py", 14 | "miDebuggerServerAddress": "localhost:1234", 15 | "stopAtEntry": true, 16 | "preLaunchTask": "Run_QEMU", 17 | }, 18 | ] 19 | } -------------------------------------------------------------------------------- /4_memory_challenge/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Clean_Build", 8 | "type": "shell", 9 | "command": "${workspaceFolder}/../shell/rebuild.sh ${workspaceFolder}" 10 | }, 11 | { 12 | "label": "Run_QEMU", 13 | "type": "shell", 14 | "command": "${workspaceFolder}/../shell/rebuild_run_qemu.sh ${workspaceFolder} debug", 15 | "isBackground": true, 16 | "problemMatcher": [ 17 | { 18 | "pattern": [ 19 | { 20 | "regexp": ".", 21 | "file": 1, 22 | "location": 2, 23 | "message": 3 24 | } 25 | ], 26 | "background": { 27 | "activeOnStart": true, 28 | "beginsPattern": ".", 29 | "endsPattern": "QEMU_started", 30 | } 31 | } 32 | ] 33 | }, 34 | ] 35 | } -------------------------------------------------------------------------------- /4_memory_challenge/0_base: -------------------------------------------------------------------------------- 1 | ../0_base -------------------------------------------------------------------------------- /4_memory_challenge/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(prj demo) 4 | 5 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/arm.cmake") 6 | set(freertos_root "${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/FreeRTOS") 7 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/common_demo.cmake") 8 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/freertos.cmake") 9 | 10 | # Set the project name 11 | project(${prj}) 12 | 13 | add_subdirectory(0_base) 14 | 15 | # Add all source files in the current directory 16 | file(GLOB demo_src "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 17 | 18 | set(src ${src} ${demo_src}) 19 | set(inc ${inc} ${CMAKE_CURRENT_SOURCE_DIR}) 20 | 21 | # Add the executable 22 | add_executable(${prj} ${src}) 23 | # Include directories 24 | target_include_directories(${prj} PUBLIC ${inc}) 25 | 26 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/log.cmake") 27 | -------------------------------------------------------------------------------- /4_memory_challenge/README.md: -------------------------------------------------------------------------------- 1 | # 4_memory_challenge 2 | 3 | ``` 4 | ../shell/rebuild_run_qemu.sh . 5 | ``` 6 | 7 | Challenge of [Introduction to RTOS Part 4 - Memory Management ](https://www.youtube.com/watch?v=Qske3yZRW5I&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=4) 8 | 9 | ![Read user input in task A and print in task B](./doc/challenge.png "Read user input in task A and print in task B") 10 | 11 | ## Terminal Output 12 | 13 | ## Notes 14 | Use demo_init function in demo.c to implement your demo application. 15 | Run in debug console to dump the trace 16 | -exec dump binary value trace.bin *RecorderDataPtr -------------------------------------------------------------------------------- /4_memory_challenge/demo.c: -------------------------------------------------------------------------------- 1 | /* Kernel includes. */ 2 | #include "FreeRTOS.h" 3 | #include "task.h" 4 | #include "demo_hw.h" 5 | #include "string.h" 6 | 7 | #define DEFAULT_PRIORITY (tskIDLE_PRIORITY + 1) 8 | #define DEFAULT_STACK_SIZE (1024u) 9 | 10 | char *_msg = NULL; 11 | uint8_t _msgReadyFlag = 0; 12 | 13 | static void _taskA( void * pvParameters ); 14 | static void _taskB( void * pvParameters ); 15 | 16 | void demo_init(void) { 17 | 18 | xTaskCreate(_taskA, 19 | "A", 20 | DEFAULT_STACK_SIZE, 21 | NULL, 22 | DEFAULT_PRIORITY, 23 | NULL ); 24 | 25 | xTaskCreate(_taskB, 26 | "B", 27 | DEFAULT_STACK_SIZE, 28 | NULL, 29 | DEFAULT_PRIORITY, 30 | NULL ); 31 | 32 | vTaskStartScheduler(); 33 | 34 | for( ; ; ) { 35 | } 36 | } 37 | 38 | static void _taskA( void * pvParameters ) { 39 | static char buf[200]; 40 | for( ; ; ) { 41 | demo_hw_term_readLine(buf, 200); 42 | size_t msgSize = (strlen(buf)+1) * sizeof(char); // +1 for null 43 | _msg = (char *) pvPortMalloc(msgSize); 44 | memcpy(_msg, buf, msgSize); 45 | _msgReadyFlag = 1; 46 | } 47 | } 48 | 49 | static void _taskB( void * pvParameters ) { 50 | for( ; ; ) { 51 | if(_msgReadyFlag && _msg != NULL) { 52 | demo_hw_term_printf("%s\n", _msg); 53 | vPortFree(_msg); 54 | _msg = NULL; 55 | _msgReadyFlag = 0; 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /4_memory_challenge/doc/challenge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aslansq/freertos_intro_qemu/28e98a29457cd92d517eebcb9b67189bbf197faa/4_memory_challenge/doc/challenge.png -------------------------------------------------------------------------------- /5_queue/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch_QEMU", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/demo", 12 | "cwd": "${workspaceFolder}", 13 | "miDebuggerPath": "${env:GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gdb-py", 14 | "miDebuggerServerAddress": "localhost:1234", 15 | "stopAtEntry": true, 16 | "preLaunchTask": "Run_QEMU", 17 | }, 18 | ] 19 | } -------------------------------------------------------------------------------- /5_queue/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Clean_Build", 8 | "type": "shell", 9 | "command": "${workspaceFolder}/../shell/rebuild.sh ${workspaceFolder}" 10 | }, 11 | { 12 | "label": "Run_QEMU", 13 | "type": "shell", 14 | "command": "${workspaceFolder}/../shell/rebuild_run_qemu.sh ${workspaceFolder} debug", 15 | "isBackground": true, 16 | "problemMatcher": [ 17 | { 18 | "pattern": [ 19 | { 20 | "regexp": ".", 21 | "file": 1, 22 | "location": 2, 23 | "message": 3 24 | } 25 | ], 26 | "background": { 27 | "activeOnStart": true, 28 | "beginsPattern": ".", 29 | "endsPattern": "QEMU_started", 30 | } 31 | } 32 | ] 33 | }, 34 | ] 35 | } -------------------------------------------------------------------------------- /5_queue/0_base: -------------------------------------------------------------------------------- 1 | ../0_base -------------------------------------------------------------------------------- /5_queue/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(prj demo) 4 | 5 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/arm.cmake") 6 | set(freertos_root "${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/FreeRTOS") 7 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/common_demo.cmake") 8 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/freertos.cmake") 9 | 10 | # Set the project name 11 | project(${prj}) 12 | 13 | add_subdirectory(0_base) 14 | 15 | # Add all source files in the current directory 16 | file(GLOB demo_src "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 17 | 18 | set(src ${src} ${demo_src}) 19 | set(inc ${inc} ${CMAKE_CURRENT_SOURCE_DIR}) 20 | 21 | # Add the executable 22 | add_executable(${prj} ${src}) 23 | # Include directories 24 | target_include_directories(${prj} PUBLIC ${inc}) 25 | 26 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/log.cmake") 27 | -------------------------------------------------------------------------------- /5_queue/README.md: -------------------------------------------------------------------------------- 1 | # 5_queue 2 | ``` 3 | ../shell/rebuild_run_qemu.sh . 4 | ``` 5 | [Introduction to RTOS Part 5 - Queue](https://www.youtube.com/watch?v=pHJ3lxOoWeI&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=5) 6 | 7 | ## Terminal Output 8 | When send is faster than print. 9 | ``` 10 | #define PRINT_MSG_DELAY (1000) 11 | #define SEND_MSG_DELAY (100) 12 | ``` 13 | Terminal output is: 14 | ``` 15 | 0 16 | 1 17 | 2 18 | 3 19 | 4 20 | 5 21 | 6 22 | 7 23 | 8 24 | 9 25 | 10 26 | 11 27 | 20 28 | 29 29 | ``` 30 | 31 | ## Notes 32 | Use demo_init function in demo.c to implement your demo application. 33 | Run in debug console to dump the trace 34 | -exec dump binary value trace.bin *RecorderDataPtr -------------------------------------------------------------------------------- /5_queue/demo.c: -------------------------------------------------------------------------------- 1 | /* Kernel includes. */ 2 | #include "FreeRTOS.h" 3 | #include "task.h" 4 | #include "queue.h" 5 | #include "demo_hw.h" 6 | 7 | #define DEFAULT_PRIORITY (tskIDLE_PRIORITY + 1) 8 | #define DEFAULT_STACK_SIZE (1024u) 9 | 10 | #define PRINT_MSG_DELAY (1000) 11 | #define SEND_MSG_DELAY (100) 12 | 13 | static void _printMsgs(void * pvParameters); 14 | static void _sendMsg(void * pvParameters); 15 | 16 | static QueueHandle_t _xQueue1 = NULL; 17 | 18 | void demo_init(void) { 19 | xTaskCreate(_printMsgs, 20 | "print", 21 | DEFAULT_STACK_SIZE, 22 | NULL, 23 | DEFAULT_PRIORITY, 24 | NULL ); 25 | 26 | xTaskCreate(_sendMsg, 27 | "send", 28 | DEFAULT_STACK_SIZE, 29 | NULL, 30 | DEFAULT_PRIORITY, 31 | NULL ); 32 | 33 | // can hold 10 int32_t 34 | _xQueue1 = xQueueCreate( 10, sizeof( uint8_t ) ); 35 | 36 | /* Start the tasks and timer running. */ 37 | vTaskStartScheduler(); 38 | 39 | for( ; ; ) 40 | { 41 | } 42 | } 43 | 44 | static void _printMsgs( void * pvParameters ) { 45 | /* Prevent the compiler warning about the unused parameter. */ 46 | (void)pvParameters; 47 | uint8_t msg = 0; 48 | BaseType_t recvRet; // receive return value 49 | for( ;; ) { 50 | if (_xQueue1 == NULL) { 51 | // do nothing 52 | } else { 53 | recvRet = xQueueReceive(_xQueue1, (void *)&msg, (TickType_t)0); 54 | if(recvRet != pdTRUE) { 55 | demo_hw_term_writeLine("-1"); 56 | } else { 57 | printf("%d\n", (int)msg); 58 | } 59 | } 60 | vTaskDelay( pdMS_TO_TICKS( PRINT_MSG_DELAY ) ); 61 | } 62 | } 63 | 64 | static void _sendMsg( void * pvParameters ) { 65 | /* Prevent the compiler warning about the unused parameter. */ 66 | (void)pvParameters; 67 | uint8_t msg = 0; 68 | BaseType_t sendRet; // send function return value 69 | for( ;; ) { 70 | if(_xQueue1 == NULL) { 71 | // do nothing 72 | } else { 73 | // can wait for 10 ticks if necessary 74 | sendRet = xQueueSend(_xQueue1, (void *)&msg, (TickType_t)10); 75 | if(sendRet != pdTRUE) { 76 | // just here so you can put breakpoint 77 | } 78 | } 79 | msg++; 80 | vTaskDelay( pdMS_TO_TICKS( SEND_MSG_DELAY ) ); 81 | } 82 | } -------------------------------------------------------------------------------- /5_queue_challenge/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch_QEMU", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/demo", 12 | "cwd": "${workspaceFolder}", 13 | "miDebuggerPath": "${env:GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gdb-py", 14 | "miDebuggerServerAddress": "localhost:1234", 15 | "stopAtEntry": true, 16 | "preLaunchTask": "Run_QEMU", 17 | }, 18 | ] 19 | } -------------------------------------------------------------------------------- /5_queue_challenge/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Clean_Build", 8 | "type": "shell", 9 | "command": "${workspaceFolder}/../shell/rebuild.sh ${workspaceFolder}" 10 | }, 11 | { 12 | "label": "Run_QEMU", 13 | "type": "shell", 14 | "command": "${workspaceFolder}/../shell/rebuild_run_qemu.sh ${workspaceFolder} debug", 15 | "isBackground": true, 16 | "problemMatcher": [ 17 | { 18 | "pattern": [ 19 | { 20 | "regexp": ".", 21 | "file": 1, 22 | "location": 2, 23 | "message": 3 24 | } 25 | ], 26 | "background": { 27 | "activeOnStart": true, 28 | "beginsPattern": ".", 29 | "endsPattern": "QEMU_started", 30 | } 31 | } 32 | ] 33 | }, 34 | ] 35 | } -------------------------------------------------------------------------------- /5_queue_challenge/0_base: -------------------------------------------------------------------------------- 1 | ../0_base -------------------------------------------------------------------------------- /5_queue_challenge/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(prj demo) 4 | 5 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/arm.cmake") 6 | set(freertos_root "${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/FreeRTOS") 7 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/common_demo.cmake") 8 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/freertos.cmake") 9 | 10 | # Set the project name 11 | project(${prj}) 12 | 13 | add_subdirectory(0_base) 14 | 15 | # Add all source files in the current directory 16 | file(GLOB demo_src "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 17 | 18 | set(src ${src} ${demo_src}) 19 | set(inc ${inc} ${CMAKE_CURRENT_SOURCE_DIR}) 20 | 21 | # Add the executable 22 | add_executable(${prj} ${src}) 23 | # Include directories 24 | target_include_directories(${prj} PUBLIC ${inc}) 25 | 26 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/log.cmake") 27 | -------------------------------------------------------------------------------- /5_queue_challenge/README.md: -------------------------------------------------------------------------------- 1 | # 5_queue_challenge 2 | ``` 3 | ../shell/rebuild_run_qemu.sh . 4 | ``` 5 | Challenge of [Introduction to RTOS Part 5 - Queue](https://www.youtube.com/watch?v=pHJ3lxOoWeI&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=5) 6 | 7 | ![Simple UI](./doc/challenge.png "Simple UI") 8 | 9 | ## Terminal Output 10 | 11 | ## Notes 12 | Use demo_init function in demo.c to implement your demo application. 13 | Run in debug console to dump the trace 14 | -exec dump binary value trace.bin *RecorderDataPtr -------------------------------------------------------------------------------- /5_queue_challenge/doc/challenge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aslansq/freertos_intro_qemu/28e98a29457cd92d517eebcb9b67189bbf197faa/5_queue_challenge/doc/challenge.png -------------------------------------------------------------------------------- /6_mutex/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch_QEMU", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/demo", 12 | "cwd": "${workspaceFolder}", 13 | "miDebuggerPath": "${env:GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gdb-py", 14 | "miDebuggerServerAddress": "localhost:1234", 15 | "stopAtEntry": true, 16 | "preLaunchTask": "Run_QEMU", 17 | }, 18 | ] 19 | } -------------------------------------------------------------------------------- /6_mutex/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Clean_Build", 8 | "type": "shell", 9 | "command": "${workspaceFolder}/../shell/rebuild.sh ${workspaceFolder} -DDEMO_MUTEX_C:BOOL=ON" 10 | }, 11 | { 12 | "label": "Run_QEMU", 13 | "type": "shell", 14 | "command": "${workspaceFolder}/../shell/rebuild_run_qemu.sh ${workspaceFolder} debug -DDEMO_MUTEX_C:BOOL=ON", 15 | "isBackground": true, 16 | "problemMatcher": [ 17 | { 18 | "pattern": [ 19 | { 20 | "regexp": ".", 21 | "file": 1, 22 | "location": 2, 23 | "message": 3 24 | } 25 | ], 26 | "background": { 27 | "activeOnStart": true, 28 | "beginsPattern": ".", 29 | "endsPattern": "QEMU_started", 30 | } 31 | } 32 | ] 33 | }, 34 | ] 35 | } -------------------------------------------------------------------------------- /6_mutex/0_base: -------------------------------------------------------------------------------- 1 | ../0_base -------------------------------------------------------------------------------- /6_mutex/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(prj demo) 4 | 5 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/arm.cmake") 6 | set(freertos_root "${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/FreeRTOS") 7 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/common_demo.cmake") 8 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/freertos.cmake") 9 | 10 | # Set the project name 11 | project(${prj}) 12 | 13 | set(demo_src "") 14 | 15 | if(DEMO_MUTEX_C) 16 | message(STATUS "demo_mutex.c selected.") 17 | set(demo_src "demo_mutex.c") 18 | endif() 19 | 20 | if(DEMO_RACE_C) 21 | message(STATUS "demo_race.c selected.") 22 | set(demo_src "demo_race.c") 23 | endif() 24 | 25 | if(NOT demo_src) 26 | message(WARNING "No demo source file specified.") 27 | message(STATUS "demo_mutex.c selected.") 28 | set(demo_src "demo_mutex.c") 29 | endif() 30 | 31 | add_subdirectory(0_base) 32 | 33 | # Add all source files in the current directory 34 | set(demo_src "${CMAKE_CURRENT_SOURCE_DIR}/${demo_src}") 35 | 36 | set(src ${src} ${demo_src}) 37 | set(inc ${inc} ${CMAKE_CURRENT_SOURCE_DIR}) 38 | 39 | # Add the executable 40 | add_executable(${prj} ${src}) 41 | # Include directories 42 | target_include_directories(${prj} PUBLIC ${inc}) 43 | 44 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/log.cmake") 45 | -------------------------------------------------------------------------------- /6_mutex/README.md: -------------------------------------------------------------------------------- 1 | # 6_mutex 2 | 3 | Two demos available. Pass one of the arguments to CMake. 4 | 5 | demo_mutex.c 6 | ``` 7 | ../shell/rebuild_run_qemu.sh . -DDEMO_MUTEX_C:BOOL=ON 8 | ``` 9 | 10 | demo_race.c 11 | ``` 12 | ../shell/rebuild_run_qemu.sh . -DDEMO_RACE_C:BOOL=ON 13 | ``` 14 | 15 | default demo.c 16 | ``` 17 | ../shell/rebuild_run_qemu.sh . 18 | ``` 19 | 20 | [Introduction to RTOS Part 6 - Mutex](https://www.youtube.com/watch?v=I55auRpbiTs&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=6) 21 | 22 | ## Terminal Output 23 | ``` 24 | $ ../shell/rebuild.sh . -DDEMO_MUTEX:BOOL=ON 25 | $ ../shell/run_qemu.sh ./build/demo 26 | char device redirected to /dev/pts/1 (label serial1) 27 | 1 28 | 2 29 | 3 30 | 4 31 | 5 32 | 6 33 | 7 34 | 8 35 | 9 36 | 10 37 | 11 38 | 12 39 | 13 40 | 14 41 | 15 42 | ``` 43 | 44 | ``` 45 | $ ../shell/rebuild.sh . -DDEMO_RACE:BOOL=ON 46 | $ ../shell/run_qemu.sh ./build/demo 47 | char device redirected to /dev/pts/1 (label serial1) 48 | 1 49 | 1 50 | 2 51 | 2 52 | 3 53 | 3 54 | 4 55 | 5 56 | ``` 57 | 58 | ## Notes 59 | Use demo_init function in demo.c to implement your demo application. 60 | Run in debug console to dump the trace 61 | -exec dump binary value trace.bin *RecorderDataPtr -------------------------------------------------------------------------------- /6_mutex/demo_mutex.c: -------------------------------------------------------------------------------- 1 | #include "FreeRTOS.h" 2 | #include "task.h" 3 | #include "semphr.h" 4 | #include "demo_hw.h" 5 | 6 | #define DEFAULT_PRIORITY (tskIDLE_PRIORITY + 1) 7 | #define DEFAULT_STACK_SIZE (1024u) 8 | 9 | static void _incTask(void * pvParameters); 10 | static int _sharedVar = 0; 11 | 12 | static SemaphoreHandle_t _sharedVar_mutex; 13 | 14 | void demo_init(void) { 15 | _sharedVar_mutex = xSemaphoreCreateMutex(); 16 | 17 | xTaskCreate(_incTask, 18 | "A", 19 | DEFAULT_STACK_SIZE, 20 | NULL, 21 | DEFAULT_PRIORITY, 22 | NULL ); 23 | 24 | xTaskCreate(_incTask, 25 | "B", 26 | DEFAULT_STACK_SIZE, 27 | NULL, 28 | DEFAULT_PRIORITY, 29 | NULL ); 30 | 31 | /* Start the tasks and timer running. */ 32 | vTaskStartScheduler(); 33 | 34 | for( ; ; ) { 35 | } 36 | } 37 | 38 | static int _myRand(void) { 39 | static int ranDurOfOpLut[] = {973, 594, 28, 651, 73, 680, 452, 504}; // random duration of operation look up table 40 | static int ranIdx = 0; 41 | ranIdx++; 42 | ranIdx = ranIdx < 8 ? ranIdx : 0; 43 | // looks random enough, this particular environment is not happy calling rand function from stdlib 44 | return ranDurOfOpLut[ranIdx % 8]; 45 | } 46 | 47 | static void _incTask(void * pvParameters) { 48 | int localVar = 0; 49 | int ranDurOfOp = 0; 50 | for( ; ; ) { 51 | if(xSemaphoreTake(_sharedVar_mutex, 5) == pdTRUE) { 52 | ranDurOfOp = _myRand(); 53 | localVar = _sharedVar; 54 | localVar++; 55 | vTaskDelay( pdMS_TO_TICKS( ranDurOfOp ) ); 56 | _sharedVar = localVar; 57 | demo_hw_term_printf("%d\n", _sharedVar); 58 | xSemaphoreGive(_sharedVar_mutex); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /6_mutex/demo_race.c: -------------------------------------------------------------------------------- 1 | /* Kernel includes. */ 2 | #include "FreeRTOS.h" 3 | #include "task.h" 4 | #include "demo_hw.h" 5 | 6 | #define DEFAULT_PRIORITY (tskIDLE_PRIORITY + 1) 7 | #define DEFAULT_STACK_SIZE (1024u) 8 | 9 | static void _incTask(void * pvParameters); 10 | static int _sharedVar = 0; 11 | 12 | void demo_init(void) { 13 | 14 | xTaskCreate(_incTask, 15 | "A", 16 | DEFAULT_STACK_SIZE, 17 | NULL, 18 | DEFAULT_PRIORITY, 19 | NULL ); 20 | 21 | xTaskCreate(_incTask, 22 | "B", 23 | DEFAULT_STACK_SIZE, 24 | NULL, 25 | DEFAULT_PRIORITY, 26 | NULL ); 27 | 28 | /* Start the tasks and timer running. */ 29 | vTaskStartScheduler(); 30 | 31 | for( ; ; ) { 32 | } 33 | } 34 | 35 | static int _myRand(void) { 36 | static int ranDurOfOpLut[] = {973, 594, 28, 651, 73, 680, 452, 504}; // random duration of operation look up table 37 | static int ranIdx = 0; 38 | ranIdx++; 39 | ranIdx = ranIdx < 8 ? ranIdx : 0; 40 | // looks random enough, this particular environment is not happy calling rand function from stdlib 41 | return ranDurOfOpLut[ranIdx % 8]; 42 | } 43 | 44 | static void _incTask(void * pvParameters) { 45 | int localVar = 0; 46 | int ranDurOfOp = 0; 47 | for( ; ; ) { 48 | ranDurOfOp = _myRand(); 49 | localVar = _sharedVar; 50 | localVar++; 51 | vTaskDelay( pdMS_TO_TICKS( ranDurOfOp ) ); 52 | _sharedVar = localVar; 53 | demo_hw_term_printf("%d\n", _sharedVar); 54 | } 55 | } -------------------------------------------------------------------------------- /6_mutex_challenge/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch_QEMU", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/demo", 12 | "cwd": "${workspaceFolder}", 13 | "miDebuggerPath": "${env:GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gdb-py", 14 | "miDebuggerServerAddress": "localhost:1234", 15 | "stopAtEntry": true, 16 | "preLaunchTask": "Run_QEMU", 17 | }, 18 | ] 19 | } -------------------------------------------------------------------------------- /6_mutex_challenge/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Clean_Build", 8 | "type": "shell", 9 | "command": "${workspaceFolder}/../shell/rebuild.sh ${workspaceFolder}" 10 | }, 11 | { 12 | "label": "Run_QEMU", 13 | "type": "shell", 14 | "command": "${workspaceFolder}/../shell/rebuild_run_qemu.sh ${workspaceFolder} debug", 15 | "isBackground": true, 16 | "problemMatcher": [ 17 | { 18 | "pattern": [ 19 | { 20 | "regexp": ".", 21 | "file": 1, 22 | "location": 2, 23 | "message": 3 24 | } 25 | ], 26 | "background": { 27 | "activeOnStart": true, 28 | "beginsPattern": ".", 29 | "endsPattern": "QEMU_started", 30 | } 31 | } 32 | ] 33 | }, 34 | ] 35 | } -------------------------------------------------------------------------------- /6_mutex_challenge/0_base: -------------------------------------------------------------------------------- 1 | ../0_base -------------------------------------------------------------------------------- /6_mutex_challenge/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(prj demo) 4 | 5 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/arm.cmake") 6 | set(freertos_root "${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/FreeRTOS") 7 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/common_demo.cmake") 8 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/freertos.cmake") 9 | 10 | # Set the project name 11 | project(${prj}) 12 | 13 | add_subdirectory(0_base) 14 | 15 | # Add all source files in the current directory 16 | file(GLOB demo_src "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 17 | 18 | set(src ${src} ${demo_src}) 19 | set(inc ${inc} ${CMAKE_CURRENT_SOURCE_DIR}) 20 | 21 | # Add the executable 22 | add_executable(${prj} ${src}) 23 | # Include directories 24 | target_include_directories(${prj} PUBLIC ${inc}) 25 | 26 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/log.cmake") 27 | -------------------------------------------------------------------------------- /6_mutex_challenge/README.md: -------------------------------------------------------------------------------- 1 | # 6_mutex_challenge 2 | 3 | ``` 4 | ../shell/rebuild_run_qemu.sh . 5 | ``` 6 | 7 | Challenge of [Introduction to RTOS Part 6 - Mutex](https://www.youtube.com/watch?v=I55auRpbiTs&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=6) 8 | 9 | On the video he says this hack. 10 | Well new FreeRTOS version can detect the hack and assert. 11 | Below is their explanation: 12 | ``` 13 | /* A task can only have an inherited priority if it holds the mutex. 14 | * If the mutex is held by a task then it cannot be given from an 15 | * interrupt, and if a mutex is given by the holding task then it must 16 | * be the running state task. */ 17 | ``` 18 | So binary semaphore used to solve the challenge 19 | 20 | ## Terminal Output 21 | 22 | ## Notes 23 | Use demo_init function in demo.c to implement your demo application. 24 | Run in debug console to dump the trace 25 | -exec dump binary value trace.bin *RecorderDataPtr -------------------------------------------------------------------------------- /6_mutex_challenge/demo.c: -------------------------------------------------------------------------------- 1 | /* Standard includes. */ 2 | #include 3 | 4 | /* Kernel includes. */ 5 | #include "FreeRTOS.h" 6 | #include "task.h" 7 | #include "semphr.h" 8 | #include "demo_hw.h" 9 | 10 | #define BLINK_TASK_PRIORITY (tskIDLE_PRIORITY + 1) 11 | #define BLINK_TASK_STACK_SIZE 1024 12 | 13 | static SemaphoreHandle_t _binSemphr = NULL; 14 | 15 | void _setup(void * pvParameters); 16 | static void _blinkLED(void * pvParameters); 17 | 18 | void demo_init(void) { 19 | xTaskCreate(_setup, /* The function that implements the task. */ 20 | "s", /* The text name assigned to the task - for debug only as it is not used by the kernel. */ 21 | BLINK_TASK_STACK_SIZE, /* The size of the stack to allocate to the task. */ 22 | NULL, /* The parameter passed to the task */ 23 | BLINK_TASK_PRIORITY, /* The priority assigned to the task. */ 24 | NULL ); /* The task handle is not required, so NULL is passed. */ 25 | 26 | /* Start the tasks and timer running. */ 27 | vTaskStartScheduler(); 28 | 29 | for( ; ; ) 30 | { 31 | } 32 | } 33 | 34 | // simulating arduino environment 35 | void _setup(void * pvParameters) { 36 | (void)pvParameters; 37 | char buf[100]; 38 | // on the video he says this hack 39 | // well new FreeRTOS version can detect the hack and assert 40 | // below is their explanation: 41 | /* A task can only have an inherited priority if it holds the mutex. 42 | * If the mutex is held by a task then it cannot be given from an 43 | * interrupt, and if a mutex is given by the holding task then it must 44 | * be the running state task. */ 45 | // _binSemphr = xSemaphoreCreateMutex(); 46 | 47 | // so semaphore used to solve this challenge 48 | _binSemphr = xSemaphoreCreateBinary(); 49 | uint32_t delay = 1000; 50 | 51 | demo_hw_term_write("Enter delay: "); 52 | demo_hw_term_readLine(buf, sizeof(buf)); 53 | delay = atoi(buf); 54 | demo_hw_term_printf("\nDelay set to %d\n", (int)delay); 55 | 56 | xTaskCreate(_blinkLED, /* The function that implements the task. */ 57 | "blink", /* The text name assigned to the task - for debug only as it is not used by the kernel. */ 58 | BLINK_TASK_STACK_SIZE, /* The size of the stack to allocate to the task. */ 59 | &delay, /* The parameter passed to the task */ 60 | BLINK_TASK_PRIORITY, /* The priority assigned to the task. */ 61 | NULL ); /* The task handle is not required, so NULL is passed. */ 62 | 63 | // wait until you take 64 | xSemaphoreTake(_binSemphr, portMAX_DELAY); 65 | demo_hw_term_writeLine("_setup done"); 66 | vTaskDelete(NULL); 67 | } 68 | 69 | static void _blinkLED( void * pvParameters ) { 70 | configASSERT(!( _binSemphr == NULL)); 71 | configASSERT(!( pvParameters == NULL)); 72 | uint32_t delay = 100; 73 | delay = *((uint32_t *) pvParameters); 74 | xSemaphoreGive(_binSemphr); 75 | for( ;; ) { 76 | vTaskDelay( pdMS_TO_TICKS( delay ) ); 77 | demo_hw_led_toggle(); 78 | } 79 | } -------------------------------------------------------------------------------- /7_semaphore/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch_QEMU", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/demo", 12 | "cwd": "${workspaceFolder}", 13 | "miDebuggerPath": "${env:GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gdb-py", 14 | "miDebuggerServerAddress": "localhost:1234", 15 | "stopAtEntry": true, 16 | "preLaunchTask": "Run_QEMU", 17 | }, 18 | ] 19 | } -------------------------------------------------------------------------------- /7_semaphore/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Clean_Build", 8 | "type": "shell", 9 | "command": "${workspaceFolder}/../shell/rebuild.sh ${workspaceFolder}" 10 | }, 11 | { 12 | "label": "Run_QEMU", 13 | "type": "shell", 14 | "command": "${workspaceFolder}/../shell/rebuild_run_qemu.sh ${workspaceFolder} debug", 15 | "isBackground": true, 16 | "problemMatcher": [ 17 | { 18 | "pattern": [ 19 | { 20 | "regexp": ".", 21 | "file": 1, 22 | "location": 2, 23 | "message": 3 24 | } 25 | ], 26 | "background": { 27 | "activeOnStart": true, 28 | "beginsPattern": ".", 29 | "endsPattern": "QEMU_started", 30 | } 31 | } 32 | ] 33 | }, 34 | ] 35 | } -------------------------------------------------------------------------------- /7_semaphore/0_base: -------------------------------------------------------------------------------- 1 | ../0_base -------------------------------------------------------------------------------- /7_semaphore/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(prj demo) 4 | 5 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/arm.cmake") 6 | set(freertos_root "${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/FreeRTOS") 7 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/common_demo.cmake") 8 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/freertos.cmake") 9 | 10 | # Set the project name 11 | project(${prj}) 12 | 13 | add_subdirectory(0_base) 14 | 15 | # Add all source files in the current directory 16 | file(GLOB demo_src "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 17 | 18 | set(src ${src} ${demo_src}) 19 | set(inc ${inc} ${CMAKE_CURRENT_SOURCE_DIR}) 20 | 21 | # Add the executable 22 | add_executable(${prj} ${src}) 23 | # Include directories 24 | target_include_directories(${prj} PUBLIC ${inc}) 25 | 26 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/log.cmake") 27 | -------------------------------------------------------------------------------- /7_semaphore/README.md: -------------------------------------------------------------------------------- 1 | # 7_semaphore 2 | 3 | ``` 4 | ../shell/rebuild_run_qemu.sh . 5 | ``` 6 | 7 | [Introduction to RTOS Part 7 - Semaphore](https://www.youtube.com/watch?v=5JcMtbA9QEE&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=7) 8 | 9 | ## Terminal Output 10 | 11 | ## Notes 12 | Use demo_init function in demo.c to implement your demo application. 13 | Run in debug console to dump the trace 14 | -exec dump binary value trace.bin *RecorderDataPtr -------------------------------------------------------------------------------- /7_semaphore/demo.c: -------------------------------------------------------------------------------- 1 | /* Kernel includes. */ 2 | #include "FreeRTOS.h" 3 | #include "task.h" 4 | #include "semphr.h" 5 | #include "demo_hw.h" 6 | #include 7 | 8 | #define DEFAULT_TASK_PRIORITY (tskIDLE_PRIORITY + 1) 9 | #define DEFAULT_TASK_STACK_SIZE 1024 10 | 11 | #define NUM_OF_PRINT_MSG_TASK (5u) 12 | 13 | static SemaphoreHandle_t _semphr = NULL; 14 | 15 | void _setup(void * pvParameters); 16 | static void _printMsg(void * pvParameters); 17 | 18 | void demo_init(void) { 19 | xTaskCreate(_setup, /* The function that implements the task. */ 20 | "S", /* The text name assigned to the task - for debug only as it is not used by the kernel. */ 21 | DEFAULT_TASK_STACK_SIZE, /* The size of the stack to allocate to the task. */ 22 | NULL, /* The parameter passed to the task */ 23 | DEFAULT_TASK_PRIORITY, /* The priority assigned to the task. */ 24 | NULL ); /* The task handle is not required, so NULL is passed. */ 25 | 26 | /* Start the tasks and timer running. */ 27 | vTaskStartScheduler(); 28 | 29 | for( ; ; ) 30 | { 31 | } 32 | } 33 | 34 | // simulating arduino environment 35 | void _setup(void * pvParameters) { 36 | (void)pvParameters; 37 | char msg[] = "Hi from _setup\'s stack\n"; 38 | char taskNames[NUM_OF_PRINT_MSG_TASK][2] = {"A", "B", "C", "D", "E"}; 39 | uint8_t i; 40 | 41 | _semphr = xSemaphoreCreateCounting(NUM_OF_PRINT_MSG_TASK, 0); 42 | 43 | for(i = 0; i < NUM_OF_PRINT_MSG_TASK; ++i) { 44 | xTaskCreate(_printMsg, /* The function that implements the task. */ 45 | taskNames[i], /* The text name assigned to the task - for debug only as it is not used by the kernel. */ 46 | DEFAULT_TASK_STACK_SIZE, /* The size of the stack to allocate to the task. */ 47 | msg, /* The parameter passed to the task */ 48 | DEFAULT_TASK_PRIORITY, /* The priority assigned to the task. */ 49 | NULL ); /* The task handle is not required, so NULL is passed. */ 50 | } 51 | 52 | for(i = 0; i < NUM_OF_PRINT_MSG_TASK; ++i) { 53 | xSemaphoreTake(_semphr, portMAX_DELAY); 54 | } 55 | 56 | demo_hw_term_writeLine("_setup done"); 57 | vTaskDelete(NULL); 58 | } 59 | 60 | static void _printMsg( void * pvParameters ) { 61 | configASSERT(!(_semphr == NULL)); 62 | configASSERT(!(pvParameters == NULL)); 63 | char msg[100]; 64 | strcpy(msg, (char *)pvParameters); 65 | demo_hw_term_printf("%s", msg); 66 | xSemaphoreGive(_semphr); 67 | vTaskDelete(NULL); 68 | } -------------------------------------------------------------------------------- /7_semaphore_challenge/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch_QEMU", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/demo", 12 | "cwd": "${workspaceFolder}", 13 | "miDebuggerPath": "${env:GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gdb-py", 14 | "miDebuggerServerAddress": "localhost:1234", 15 | "stopAtEntry": true, 16 | "preLaunchTask": "Run_QEMU", 17 | }, 18 | ] 19 | } -------------------------------------------------------------------------------- /7_semaphore_challenge/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Clean_Build", 8 | "type": "shell", 9 | "command": "${workspaceFolder}/../shell/rebuild.sh ${workspaceFolder}" 10 | }, 11 | { 12 | "label": "Run_QEMU", 13 | "type": "shell", 14 | "command": "${workspaceFolder}/../shell/rebuild_run_qemu.sh ${workspaceFolder} debug", 15 | "isBackground": true, 16 | "problemMatcher": [ 17 | { 18 | "pattern": [ 19 | { 20 | "regexp": ".", 21 | "file": 1, 22 | "location": 2, 23 | "message": 3 24 | } 25 | ], 26 | "background": { 27 | "activeOnStart": true, 28 | "beginsPattern": ".", 29 | "endsPattern": "QEMU_started", 30 | } 31 | } 32 | ] 33 | }, 34 | ] 35 | } -------------------------------------------------------------------------------- /7_semaphore_challenge/0_base: -------------------------------------------------------------------------------- 1 | ../0_base -------------------------------------------------------------------------------- /7_semaphore_challenge/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(prj demo) 4 | 5 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/arm.cmake") 6 | set(freertos_root "${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/FreeRTOS") 7 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/common_demo.cmake") 8 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/freertos.cmake") 9 | 10 | # Set the project name 11 | project(${prj}) 12 | 13 | add_subdirectory(0_base) 14 | 15 | # Add all source files in the current directory 16 | file(GLOB demo_src "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 17 | 18 | set(src ${src} ${demo_src}) 19 | set(inc ${inc} ${CMAKE_CURRENT_SOURCE_DIR}) 20 | 21 | # Add the executable 22 | add_executable(${prj} ${src}) 23 | # Include directories 24 | target_include_directories(${prj} PUBLIC ${inc}) 25 | 26 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/log.cmake") 27 | -------------------------------------------------------------------------------- /7_semaphore_challenge/README.md: -------------------------------------------------------------------------------- 1 | # 7_semaphore_challenge 2 | 3 | ``` 4 | ../shell/rebuild_run_qemu.sh . 5 | ``` 6 | 7 | [Introduction to RTOS Part 7 - Semaphore](https://www.youtube.com/watch?v=5JcMtbA9QEE&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=7) 8 | 9 | Interesting trace to see how some producers take longer than others because they wait for semaphore or mutex. 10 | ![Trace](./doc/trace.png "Trace") 11 | 12 | ## Terminal Output 13 | ``` 14 | 1 15 | 1 16 | 1 17 | 2 18 | 2 19 | 2 20 | 3 21 | 3 22 | 3 23 | 4 24 | 4 25 | 4 26 | 0 27 | 0 28 | 0 29 | ``` 30 | ## Notes 31 | Use demo_init function in demo.c to implement your demo application. 32 | Run in debug console to dump the trace 33 | -exec dump binary value trace.bin *RecorderDataPtr -------------------------------------------------------------------------------- /7_semaphore_challenge/doc/challenge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aslansq/freertos_intro_qemu/28e98a29457cd92d517eebcb9b67189bbf197faa/7_semaphore_challenge/doc/challenge.png -------------------------------------------------------------------------------- /7_semaphore_challenge/doc/trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aslansq/freertos_intro_qemu/28e98a29457cd92d517eebcb9b67189bbf197faa/7_semaphore_challenge/doc/trace.png -------------------------------------------------------------------------------- /8_sw_timers/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch_QEMU", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/demo", 12 | "cwd": "${workspaceFolder}", 13 | "miDebuggerPath": "${env:GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gdb-py", 14 | "miDebuggerServerAddress": "localhost:1234", 15 | "stopAtEntry": true, 16 | "preLaunchTask": "Run_QEMU", 17 | }, 18 | ] 19 | } -------------------------------------------------------------------------------- /8_sw_timers/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Clean_Build", 8 | "type": "shell", 9 | "command": "${workspaceFolder}/../shell/rebuild.sh ${workspaceFolder}" 10 | }, 11 | { 12 | "label": "Run_QEMU", 13 | "type": "shell", 14 | "command": "${workspaceFolder}/../shell/rebuild_run_qemu.sh ${workspaceFolder} debug", 15 | "isBackground": true, 16 | "problemMatcher": [ 17 | { 18 | "pattern": [ 19 | { 20 | "regexp": ".", 21 | "file": 1, 22 | "location": 2, 23 | "message": 3 24 | } 25 | ], 26 | "background": { 27 | "activeOnStart": true, 28 | "beginsPattern": ".", 29 | "endsPattern": "QEMU_started", 30 | } 31 | } 32 | ] 33 | }, 34 | ] 35 | } -------------------------------------------------------------------------------- /8_sw_timers/0_base: -------------------------------------------------------------------------------- 1 | ../0_base -------------------------------------------------------------------------------- /8_sw_timers/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(prj demo) 4 | 5 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/arm.cmake") 6 | set(freertos_root "${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/FreeRTOS") 7 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/common_demo.cmake") 8 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/freertos.cmake") 9 | 10 | # Set the project name 11 | project(${prj}) 12 | 13 | add_subdirectory(0_base) 14 | 15 | # Add all source files in the current directory 16 | file(GLOB demo_src "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 17 | 18 | set(src ${src} ${demo_src}) 19 | set(inc ${inc} ${CMAKE_CURRENT_SOURCE_DIR}) 20 | 21 | # Add the executable 22 | add_executable(${prj} ${src}) 23 | # Include directories 24 | target_include_directories(${prj} PUBLIC ${inc}) 25 | 26 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/log.cmake") 27 | -------------------------------------------------------------------------------- /8_sw_timers/README.md: -------------------------------------------------------------------------------- 1 | # 8_sw_timers 2 | 3 | ``` 4 | ../shell/rebuild_run_qemu.sh . 5 | ``` 6 | 7 | [Introduction to RTOS Part 8 - Software Timer ](https://www.youtube.com/watch?v=b1f1Iex0Tso&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=8) 8 | 9 | ## Terminal Output 10 | 11 | ## Notes 12 | Use demo_init function in demo.c to implement your demo application. 13 | Run in debug console to dump the trace 14 | -exec dump binary value trace.bin *RecorderDataPtr -------------------------------------------------------------------------------- /8_sw_timers/demo.c: -------------------------------------------------------------------------------- 1 | /* Kernel includes. */ 2 | #include "FreeRTOS.h" 3 | #include "timers.h" 4 | #include "demo_hw.h" 5 | 6 | // Timer call back 7 | void _timerCallback(TimerHandle_t xTimer); 8 | 9 | static const char _oneShotTmChar = 'o'; 10 | static const char _autoReTmChar = 'a'; 11 | 12 | void demo_init(void) { 13 | // one shot timer handle 14 | TimerHandle_t oneShotTm; 15 | // auto reload timer handle 16 | TimerHandle_t autoReTm; 17 | 18 | oneShotTm = xTimerCreate("oneShotTm", // pcTimerName 19 | pdMS_TO_TICKS( 2000 ), // xTimerPeriod 20 | pdFALSE, // uxAutoReload 21 | (void *)&_oneShotTmChar, // pvTimerID 22 | _timerCallback); // pxCallbackFunction 23 | 24 | 25 | autoReTm = xTimerCreate("autoReTm", // pcTimerName 26 | pdMS_TO_TICKS( 1000 ), // xTimerPeriod 27 | pdTRUE, // uxAutoReload 28 | (void *)&_autoReTmChar, // pvTimerID 29 | _timerCallback); // pxCallbackFunction 30 | 31 | configASSERT(!(oneShotTm == NULL)); 32 | configASSERT(!(autoReTm == NULL)); 33 | 34 | xTimerStart(oneShotTm, portMAX_DELAY); 35 | xTimerStart(autoReTm, portMAX_DELAY); 36 | vTaskStartScheduler(); 37 | for( ; ; ) { 38 | } 39 | } 40 | 41 | void _timerCallback(TimerHandle_t xTimer) { 42 | char *cPtr = (char *)pvTimerGetTimerID(xTimer); 43 | if((*cPtr) == _oneShotTmChar) { 44 | demo_hw_term_writeLine("one shot tm expired."); 45 | } else if((*cPtr) == _autoReTmChar) { 46 | demo_hw_term_writeLine("auto reload tm expired."); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /8_sw_timers_challenge/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch_QEMU", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/demo", 12 | "cwd": "${workspaceFolder}", 13 | "miDebuggerPath": "${env:GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gdb-py", 14 | "miDebuggerServerAddress": "localhost:1234", 15 | "stopAtEntry": true, 16 | "preLaunchTask": "Run_QEMU", 17 | }, 18 | ] 19 | } -------------------------------------------------------------------------------- /8_sw_timers_challenge/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Clean_Build", 8 | "type": "shell", 9 | "command": "${workspaceFolder}/../shell/rebuild.sh ${workspaceFolder}" 10 | }, 11 | { 12 | "label": "Run_QEMU", 13 | "type": "shell", 14 | "command": "${workspaceFolder}/../shell/rebuild_run_qemu.sh ${workspaceFolder} debug", 15 | "isBackground": true, 16 | "problemMatcher": [ 17 | { 18 | "pattern": [ 19 | { 20 | "regexp": ".", 21 | "file": 1, 22 | "location": 2, 23 | "message": 3 24 | } 25 | ], 26 | "background": { 27 | "activeOnStart": true, 28 | "beginsPattern": ".", 29 | "endsPattern": "QEMU_started", 30 | } 31 | } 32 | ] 33 | }, 34 | ] 35 | } -------------------------------------------------------------------------------- /8_sw_timers_challenge/0_base: -------------------------------------------------------------------------------- 1 | ../0_base -------------------------------------------------------------------------------- /8_sw_timers_challenge/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(prj demo) 4 | 5 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/arm.cmake") 6 | set(freertos_root "${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/FreeRTOS") 7 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/common_demo.cmake") 8 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/freertos.cmake") 9 | 10 | # Set the project name 11 | project(${prj}) 12 | 13 | add_subdirectory(0_base) 14 | 15 | # Add all source files in the current directory 16 | file(GLOB demo_src "${CMAKE_CURRENT_SOURCE_DIR}/*.c") 17 | 18 | set(src ${src} ${demo_src}) 19 | set(inc ${inc} ${CMAKE_CURRENT_SOURCE_DIR}) 20 | 21 | # Add the executable 22 | add_executable(${prj} ${src}) 23 | # Include directories 24 | target_include_directories(${prj} PUBLIC ${inc}) 25 | 26 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/log.cmake") 27 | -------------------------------------------------------------------------------- /8_sw_timers_challenge/README.md: -------------------------------------------------------------------------------- 1 | # 8_sw_timers_challenge 2 | 3 | ``` 4 | ../shell/rebuild_run_qemu.sh . 5 | ``` 6 | 7 | Challenge of [Introduction to RTOS Part 8 - Software Timer ](https://www.youtube.com/watch?v=b1f1Iex0Tso&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=8) 8 | 9 | ## Terminal Output 10 | 11 | ## Notes 12 | Use demo_init function in demo.c to implement your demo application. 13 | Run in debug console to dump the trace 14 | -exec dump binary value trace.bin *RecorderDataPtr -------------------------------------------------------------------------------- /8_sw_timers_challenge/demo.c: -------------------------------------------------------------------------------- 1 | /* Kernel includes. */ 2 | #include "FreeRTOS.h" 3 | #include "timers.h" 4 | #include "task.h" 5 | #include "demo_hw.h" 6 | 7 | #define DEFAULT_TASK_STACK_SIZE (1024u) 8 | #define DEFAULT_TASK_PRIORITY (tskIDLE_PRIORITY + 1) 9 | 10 | // Timer call back 11 | void _backlightTmCbk(TimerHandle_t xTimer); 12 | static void _userInTask(void * pvParameters); 13 | 14 | static const char _backlightTmChar = 'b'; 15 | // one shot timer handle 16 | static TimerHandle_t _backlightTm; 17 | 18 | void demo_init(void) { 19 | BaseType_t ret; 20 | _backlightTm = xTimerCreate( 21 | "backlightTm", // pcTimerName 22 | pdMS_TO_TICKS( 5000 ), // xTimerPeriod 23 | pdFALSE, // uxAutoReload 24 | (void *)&_backlightTmChar, // pvTimerID 25 | _backlightTmCbk // pxCallbackFunction 26 | ); 27 | 28 | ret = xTaskCreate( 29 | _userInTask, // pvTaskCode 30 | "userIn", // pcName 31 | DEFAULT_TASK_STACK_SIZE, // uxStackDepth 32 | NULL, // pvParameters 33 | DEFAULT_TASK_PRIORITY, // uxPriority 34 | NULL // pxCreatedTask 35 | ); 36 | 37 | if(_backlightTm == NULL || 38 | ret != pdTRUE) { 39 | demo_hw_term_writeLine("err timer"); 40 | while(1) 41 | ; 42 | } 43 | 44 | xTimerStart(_backlightTm, portMAX_DELAY); 45 | vTaskStartScheduler(); 46 | for( ; ; ) { 47 | } 48 | } 49 | 50 | static void _userInTask(void * pvParameters) { 51 | configASSERT(!(_backlightTm == NULL)); 52 | (void)pvParameters; 53 | char c; 54 | int ret; 55 | for( ; ; ) { 56 | ret = demo_hw_term_readCharNonBlock(&c); 57 | if(ret) { 58 | demo_hw_led_set(1); 59 | demo_hw_term_writeChar(c); 60 | xTimerStart(_backlightTm, portMAX_DELAY); 61 | } 62 | } 63 | } 64 | 65 | void _backlightTmCbk(TimerHandle_t xTimer) { 66 | configASSERT(!(xTimer == NULL)); 67 | char *cPtr = (char *)pvTimerGetTimerID(xTimer); 68 | if((*cPtr) == _backlightTmChar) { 69 | demo_hw_led_set(0); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /9_hw_int/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch_QEMU", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/demo", 12 | "cwd": "${workspaceFolder}", 13 | "miDebuggerPath": "${env:GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gdb-py", 14 | "miDebuggerServerAddress": "localhost:1234", 15 | "stopAtEntry": true, 16 | "preLaunchTask": "Run_QEMU", 17 | }, 18 | ] 19 | } -------------------------------------------------------------------------------- /9_hw_int/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Clean_Build", 8 | "type": "shell", 9 | "command": "${workspaceFolder}/../shell/rebuild.sh ${workspaceFolder} -DDEMO_ADC_C:BOOL=ON" 10 | }, 11 | { 12 | "label": "Run_QEMU", 13 | "type": "shell", 14 | "command": "${workspaceFolder}/../shell/rebuild_run_qemu.sh ${workspaceFolder} debug -DDEMO_ADC_C:BOOL=ON", 15 | "isBackground": true, 16 | "problemMatcher": [ 17 | { 18 | "pattern": [ 19 | { 20 | "regexp": ".", 21 | "file": 1, 22 | "location": 2, 23 | "message": 3 24 | } 25 | ], 26 | "background": { 27 | "activeOnStart": true, 28 | "beginsPattern": ".", 29 | "endsPattern": "QEMU_started", 30 | } 31 | } 32 | ] 33 | }, 34 | ] 35 | } -------------------------------------------------------------------------------- /9_hw_int/0_base: -------------------------------------------------------------------------------- 1 | ../0_base -------------------------------------------------------------------------------- /9_hw_int/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(prj demo) 4 | 5 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/arm.cmake") 6 | set(freertos_root "${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/FreeRTOS") 7 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/common_demo.cmake") 8 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/freertos.cmake") 9 | 10 | # Set the project name 11 | project(${prj}) 12 | 13 | if(DEMO_TM_C) 14 | message(STATUS "demo_tm.c selected.") 15 | set(demo_src "demo_tm.c") 16 | endif() 17 | 18 | if(DEMO_ADC_C) 19 | message(STATUS "demo_adc.c selected.") 20 | set(demo_src "demo_adc.c") 21 | endif() 22 | 23 | if(DEMO_NOTIFY_C) 24 | message(STATUS "demo_notify.c selected.") 25 | set(demo_src "demo_notify.c") 26 | endif() 27 | 28 | if(NOT demo_src) 29 | message(WARNING "No demo source file specified.") 30 | message(STATUS "demo_adc.c selected.") 31 | set(demo_src "demo_adc.c") 32 | endif() 33 | 34 | add_subdirectory(0_base) 35 | 36 | # Add all source files in the current directory 37 | set(demo_src "${CMAKE_CURRENT_SOURCE_DIR}/${demo_src}") 38 | 39 | set(src ${src} ${demo_src}) 40 | set(inc ${inc} ${CMAKE_CURRENT_SOURCE_DIR}) 41 | 42 | # Add the executable 43 | add_executable(${prj} ${src}) 44 | # Include directories 45 | target_include_directories(${prj} PUBLIC ${inc}) 46 | 47 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/log.cmake") 48 | -------------------------------------------------------------------------------- /9_hw_int/README.md: -------------------------------------------------------------------------------- 1 | # 9_hw_int 2 | 3 | demo_tm.c 4 | ``` 5 | ../shell/rebuild_run_qemu.sh . -DDEMO_TM_C:BOOL=ON 6 | ``` 7 | demo_adc.c 8 | ``` 9 | ../shell/rebuild_run_qemu.sh . -DDEMO_ADC_C:BOOL=ON 10 | ``` 11 | demo_notify.c 12 | ``` 13 | ../shell/rebuild_run_qemu.sh . -DDEMO_NOTIFY_C:BOOL=ON 14 | ``` 15 | default demo_adc.c 16 | ``` 17 | ../shell/rebuild_run_qemu.sh . 18 | ``` 19 | 20 | [Introduction to RTOS Part 9 - Hardware Interrupts](https://www.youtube.com/watch?v=qsflCf6ahXU&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=9) 21 | 22 | As he explains while loop is running, interrupt occurs then OS switches to printValue. 23 | Purpose isr should be as short as possible. You let other task to handle information. This called deferred interrupt. 24 | ![adcTrace](./doc/adcTrace.png "adcTrace") 25 | 26 | ## Terminal Output 27 | 28 | ## Notes 29 | Use demo_init function in demo.c to implement your demo application. 30 | Run in debug console to dump the trace 31 | -exec dump binary value trace.bin *RecorderDataPtr -------------------------------------------------------------------------------- /9_hw_int/demo_adc.c: -------------------------------------------------------------------------------- 1 | /* Kernel includes. */ 2 | #include "FreeRTOS.h" 3 | #include "task.h" 4 | // demo hardware 5 | #include "demo_hw.h" 6 | #include "CMSDK_CM3.h" 7 | #include "semphr.h" 8 | 9 | #define LOOP_TASK_PRIORTY (tskIDLE_PRIORITY + 1) 10 | #define PRINT_VAL_TASK_PRIORITY (tskIDLE_PRIORITY + 2) 11 | #define DEFAULT_TASK_STACK_SIZE (1024u) 12 | 13 | #define TM0 CMSDK_TIMER0 14 | #define TIMER_INT_CLEAR() (TM0->INTCLEAR |= CMSDK_TIMER_INTCLEAR_Msk) 15 | #define TIMER_FREQUENCY ( 1UL ) 16 | 17 | #define PRIO_ISR_TIMER configMAX_SYSCALL_INTERRUPT_PRIORITY // the hardware priority of the interrupt 18 | 19 | static void _loop( void * pvParameters ); 20 | static void _printValue( void * pvParameters ); 21 | static uint8_t _adcVal = 0; 22 | static SemaphoreHandle_t _adcSemphr = NULL; 23 | 24 | TraceISRHandle_t _traceTmIsrHandle; 25 | 26 | void demo_init(void) { 27 | xTraceISRRegister("t", PRIO_ISR_TIMER, &_traceTmIsrHandle); 28 | 29 | 30 | TIMER_INT_CLEAR(); 31 | TM0->CTRL |= CMSDK_TIMER_CTRL_IRQEN_Msk; 32 | TM0->RELOAD = ( configCPU_CLOCK_HZ / TIMER_FREQUENCY ) + 1UL; 33 | TM0->CTRL |= CMSDK_TIMER_CTRL_EN_Msk; 34 | NVIC_SetPriority( TIMER0_IRQn, configMAX_SYSCALL_INTERRUPT_PRIORITY ); 35 | NVIC_EnableIRQ( TIMER0_IRQn ); 36 | 37 | _adcSemphr = xSemaphoreCreateBinary(); 38 | 39 | if(_adcSemphr == NULL) { 40 | demo_hw_term_writeLine("err _adcSemphr"); 41 | while(1) 42 | ; 43 | } 44 | 45 | xTaskCreate( 46 | _printValue, // pvTaskCode 47 | "p", // pcName 48 | DEFAULT_TASK_STACK_SIZE, // uxStackDepth 49 | NULL, // pvParameters 50 | PRINT_VAL_TASK_PRIORITY, // uxPriority 51 | NULL // pxCreatedTask 52 | ); 53 | 54 | xTaskCreate( 55 | _loop, // pvTaskCode 56 | "l", // pcName 57 | DEFAULT_TASK_STACK_SIZE, // uxStackDepth 58 | NULL, // pvParameters 59 | LOOP_TASK_PRIORTY, // uxPriority 60 | NULL // pxCreatedTask 61 | ); 62 | 63 | vTaskStartScheduler(); 64 | 65 | for( ; ; ) { 66 | } 67 | } 68 | 69 | static void _loop( void * pvParameters ) { 70 | (void)pvParameters; 71 | for( ; ; ) { 72 | // do nothing 73 | } 74 | } 75 | 76 | 77 | static void _printValue( void * pvParameters ) { 78 | (void)pvParameters; 79 | for( ; ; ) { 80 | xSemaphoreTake(_adcSemphr, portMAX_DELAY); 81 | demo_hw_term_printf("%d\n", (int)_adcVal); 82 | } 83 | } 84 | 85 | void TIMER0_Handler( void ) 86 | { 87 | xTraceISRBegin(_traceTmIsrHandle); 88 | /* Clear interrupt. */ 89 | TIMER_INT_CLEAR(); 90 | BaseType_t p; 91 | _adcVal = demo_hw_adc_read(); 92 | xSemaphoreGiveFromISR(_adcSemphr, &p); 93 | portYIELD_FROM_ISR(p); 94 | xTraceISREnd(0); 95 | } 96 | -------------------------------------------------------------------------------- /9_hw_int/demo_notify.c: -------------------------------------------------------------------------------- 1 | /* Kernel includes. */ 2 | #include "FreeRTOS.h" 3 | #include "task.h" 4 | // demo hardware 5 | #include "demo_hw.h" 6 | #include "CMSDK_CM3.h" 7 | #include "semphr.h" 8 | 9 | #define LOOP_TASK_PRIORTY (tskIDLE_PRIORITY + 1) 10 | #define PRINT_VAL_TASK_PRIORITY (tskIDLE_PRIORITY + 2) 11 | #define DEFAULT_TASK_STACK_SIZE (1024u) 12 | 13 | #define TM0 CMSDK_TIMER0 14 | #define TIMER_INT_CLEAR() (TM0->INTCLEAR |= CMSDK_TIMER_INTCLEAR_Msk) 15 | #define TIMER_FREQUENCY ( 1UL ) 16 | 17 | #define PRIO_ISR_TIMER configMAX_SYSCALL_INTERRUPT_PRIORITY // the hardware priority of the interrupt 18 | 19 | static void _loop( void * pvParameters ); 20 | static void _printValue( void * pvParameters ); 21 | static uint8_t _adcVal = 0; 22 | 23 | TraceISRHandle_t _traceTmIsrHandle; 24 | TaskHandle_t _printValueTaskHandle = NULL; 25 | 26 | void demo_init(void) { 27 | xTraceISRRegister("t", PRIO_ISR_TIMER, &_traceTmIsrHandle); 28 | 29 | 30 | TIMER_INT_CLEAR(); 31 | TM0->CTRL |= CMSDK_TIMER_CTRL_IRQEN_Msk; 32 | TM0->RELOAD = ( configCPU_CLOCK_HZ / TIMER_FREQUENCY ) + 1UL; 33 | TM0->CTRL |= CMSDK_TIMER_CTRL_EN_Msk; 34 | NVIC_SetPriority( TIMER0_IRQn, configMAX_SYSCALL_INTERRUPT_PRIORITY ); 35 | NVIC_EnableIRQ( TIMER0_IRQn ); 36 | 37 | xTaskCreate( 38 | _printValue, // pvTaskCode 39 | "p", // pcName 40 | DEFAULT_TASK_STACK_SIZE, // uxStackDepth 41 | NULL, // pvParameters 42 | PRINT_VAL_TASK_PRIORITY, // uxPriority 43 | &_printValueTaskHandle // pxCreatedTask 44 | ); 45 | 46 | configASSERT(!(_printValueTaskHandle == NULL)); 47 | 48 | xTaskCreate( 49 | _loop, // pvTaskCode 50 | "l", // pcName 51 | DEFAULT_TASK_STACK_SIZE, // uxStackDepth 52 | NULL, // pvParameters 53 | LOOP_TASK_PRIORTY, // uxPriority 54 | NULL // pxCreatedTask 55 | ); 56 | 57 | vTaskStartScheduler(); 58 | 59 | for( ; ; ) { 60 | } 61 | } 62 | 63 | static void _loop( void * pvParameters ) { 64 | (void)pvParameters; 65 | for( ; ; ) { 66 | // do nothing 67 | } 68 | } 69 | 70 | 71 | static void _printValue( void * pvParameters ) { 72 | (void)pvParameters; 73 | uint32_t ulNotificationValue; 74 | for( ; ; ) { 75 | ulNotificationValue = ulTaskNotifyTake( 76 | pdTRUE, 77 | portMAX_DELAY 78 | ); 79 | 80 | configASSERT(!(ulNotificationValue == 0)); 81 | demo_hw_term_printf("%d\n", (int)_adcVal); 82 | } 83 | } 84 | 85 | void TIMER0_Handler( void ) 86 | { 87 | xTraceISRBegin(_traceTmIsrHandle); 88 | BaseType_t xHigherPriorityTaskWoken = pdFALSE; 89 | /* Clear interrupt. */ 90 | TIMER_INT_CLEAR(); 91 | _adcVal = demo_hw_adc_read(); 92 | vTaskNotifyGiveFromISR(_printValueTaskHandle, &xHigherPriorityTaskWoken); 93 | portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); 94 | xTraceISREnd(0); 95 | } 96 | -------------------------------------------------------------------------------- /9_hw_int/demo_tm.c: -------------------------------------------------------------------------------- 1 | /* Kernel includes. */ 2 | #include "FreeRTOS.h" 3 | #include "task.h" 4 | // demo hardware 5 | #include "demo_hw.h" 6 | #include "CMSDK_CM3.h" 7 | 8 | #define DEFAULT_TASK_LOOP_PRIORITY (tskIDLE_PRIORITY + 1) 9 | #define DEFAULT_TASK_STACK_SIZE (1024u) 10 | 11 | #define TM0 CMSDK_TIMER0 12 | #define TIMER_INT_CLEAR() (TM0->INTCLEAR |= CMSDK_TIMER_INTCLEAR_Msk) 13 | #define TIMER_FREQUENCY ( 1UL ) 14 | 15 | static void _printValue( void * pvParameters ); 16 | 17 | static volatile uint32_t _isrCounter = 0; 18 | 19 | void demo_init(void) { 20 | TIMER_INT_CLEAR(); 21 | TM0->CTRL |= CMSDK_TIMER_CTRL_IRQEN_Msk; 22 | TM0->RELOAD = ( configCPU_CLOCK_HZ / TIMER_FREQUENCY ) + 1UL; 23 | TM0->CTRL |= CMSDK_TIMER_CTRL_EN_Msk; 24 | NVIC_SetPriority( TIMER0_IRQn, configMAX_SYSCALL_INTERRUPT_PRIORITY ); 25 | NVIC_EnableIRQ( TIMER0_IRQn ); 26 | 27 | xTaskCreate( 28 | _printValue, // pvTaskCode 29 | "p", // pcName 30 | DEFAULT_TASK_STACK_SIZE, // uxStackDepth 31 | NULL, // pvParameters 32 | DEFAULT_TASK_LOOP_PRIORITY, // uxPriority 33 | NULL // pxCreatedTask 34 | ); 35 | 36 | vTaskStartScheduler(); 37 | 38 | for( ; ; ) { 39 | } 40 | } 41 | 42 | static void _printValue( void * pvParameters ) { 43 | (void)pvParameters; 44 | for( ; ; ) { 45 | vTaskDelay( pdMS_TO_TICKS( 1300 ) ); 46 | demo_hw_term_printf("%d\n", (int)_isrCounter); 47 | taskENTER_CRITICAL(); 48 | _isrCounter--; 49 | taskEXIT_CRITICAL(); 50 | } 51 | } 52 | 53 | void TIMER0_Handler( void ) 54 | { 55 | /* Clear interrupt. */ 56 | TIMER_INT_CLEAR(); 57 | UBaseType_t uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR(); 58 | _isrCounter++; 59 | taskEXIT_CRITICAL_FROM_ISR(uxSavedInterruptStatus); 60 | } 61 | -------------------------------------------------------------------------------- /9_hw_int/doc/adcTrace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aslansq/freertos_intro_qemu/28e98a29457cd92d517eebcb9b67189bbf197faa/9_hw_int/doc/adcTrace.png -------------------------------------------------------------------------------- /9_hw_int_challenge/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch_QEMU", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/demo", 12 | "cwd": "${workspaceFolder}", 13 | "miDebuggerPath": "${env:GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gdb-py", 14 | "miDebuggerServerAddress": "localhost:1234", 15 | "stopAtEntry": true, 16 | "preLaunchTask": "Run_QEMU", 17 | }, 18 | ] 19 | } -------------------------------------------------------------------------------- /9_hw_int_challenge/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Clean_Build", 8 | "type": "shell", 9 | "command": "${workspaceFolder}/../shell/rebuild.sh ${workspaceFolder}" 10 | }, 11 | { 12 | "label": "Run_QEMU", 13 | "type": "shell", 14 | "command": "${workspaceFolder}/../shell/rebuild_run_qemu.sh ${workspaceFolder} debug", 15 | "isBackground": true, 16 | "problemMatcher": [ 17 | { 18 | "pattern": [ 19 | { 20 | "regexp": ".", 21 | "file": 1, 22 | "location": 2, 23 | "message": 3 24 | } 25 | ], 26 | "background": { 27 | "activeOnStart": true, 28 | "beginsPattern": ".", 29 | "endsPattern": "QEMU_started", 30 | } 31 | } 32 | ] 33 | }, 34 | ] 35 | } -------------------------------------------------------------------------------- /9_hw_int_challenge/0_base: -------------------------------------------------------------------------------- 1 | ../0_base -------------------------------------------------------------------------------- /9_hw_int_challenge/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(prj demo) 4 | 5 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/arm.cmake") 6 | set(freertos_root "${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/FreeRTOS") 7 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/common_demo.cmake") 8 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/freertos.cmake") 9 | 10 | # Set the project name 11 | project(${prj}) 12 | 13 | add_subdirectory(0_base) 14 | 15 | # Add all source files in the current directory 16 | set(demo_src "${CMAKE_CURRENT_SOURCE_DIR}/demo.c" "${CMAKE_CURRENT_SOURCE_DIR}/demo_init.c") 17 | 18 | set(src ${src} ${demo_src}) 19 | set(inc ${inc} ${CMAKE_CURRENT_SOURCE_DIR}) 20 | 21 | # Add the executable 22 | add_executable(${prj} ${src}) 23 | # Include directories 24 | target_include_directories(${prj} PUBLIC ${inc}) 25 | 26 | include("${CMAKE_CURRENT_SOURCE_DIR}/0_base/misc/cmake/log.cmake") 27 | -------------------------------------------------------------------------------- /9_hw_int_challenge/README.md: -------------------------------------------------------------------------------- 1 | # 9_hw_int_challenge 2 | 3 | ``` 4 | ../shell/rebuild_run_qemu.sh . 5 | ``` 6 | 7 | Challenge of [Introduction to RTOS Part 9 - Hardware Interrupts](https://www.youtube.com/watch?v=qsflCf6ahXU&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=9) 8 | 9 | 10 | ## Terminal Output 11 | 12 | ## Notes 13 | Use demo_init function in demo.c to implement your demo application. 14 | Run in debug console to dump the trace 15 | -exec dump binary value trace.bin *RecorderDataPtr -------------------------------------------------------------------------------- /9_hw_int_challenge/demo.h: -------------------------------------------------------------------------------- 1 | #ifndef DEMO_H 2 | #define DEMO_H 3 | 4 | void demo_taskA( void * pvParameters ); 5 | void demo_taskB( void * pvParameters ); 6 | void demo_taskLed( void * pvParameters ); 7 | #endif // DEMO_H -------------------------------------------------------------------------------- /9_hw_int_challenge/demo_init.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef DEMO_INIT_H 3 | #define DEMO_INIT_H 4 | 5 | /* Kernel includes. */ 6 | #include "FreeRTOS.h" 7 | #include "task.h" 8 | #include "semphr.h" 9 | #include "ringbuffer.h" 10 | #include "queue.h" 11 | 12 | // demo hardware 13 | #include "demo_hw.h" 14 | #include "CMSDK_CM3.h" 15 | // timer related defines 16 | #define TM0 CMSDK_TIMER0 17 | #define TIMER_INT_CLEAR() (TM0->INTCLEAR |= CMSDK_TIMER_INTCLEAR_Msk) 18 | #define TIMER_FREQUENCY ( 10UL ) 19 | #define PRIO_ISR_TIMER configMAX_SYSCALL_INTERRUPT_PRIORITY // the hardware priority of the interrupt 20 | #define SIZE_OF_ADC_QUEUE (10u) 21 | // task priorities 22 | #define DEFAULT_TASK_PRIORITY (tskIDLE_PRIORITY + 1) 23 | #define LED_TASK_PRIORITY (tskIDLE_PRIORITY + 2) 24 | #define B_TASK_PRIORITY (tskIDLE_PRIORITY + 3) 25 | #define A_TASK_PRIORITY (tskIDLE_PRIORITY + 4) 26 | // default stack size 27 | #define DEFAULT_TASK_STACK_SIZE (1024u) 28 | // number of ring buffers 29 | #define NUM_OF_RINGS (3u) 30 | // size of ring buffer 31 | #define SIZE_OF_RING_BUF (16u) 32 | // notify task to process when you this number of samples 33 | #define NOTIFY_WHEN_NUM_OF_ADC_READS (10u) 34 | #if (SIZE_OF_RING_BUF - NOTIFY_WHEN_NUM_OF_ADC_READS - 1) < 0 35 | #error number of reads would not fit into ring buffer 36 | #endif 37 | 38 | typedef struct { 39 | // handle needed for tracing 40 | TraceISRHandle_t traceIsrHandle; 41 | // ring buffers 42 | ring_buffer_t ringBuf[NUM_OF_RINGS]; 43 | // ring buffer in active use 44 | uint8_t ringBufIdx; 45 | // actual buffer for ring buffer 46 | char buf[NUM_OF_RINGS][SIZE_OF_RING_BUF]; 47 | // task that is going to be notified when NOTIFY_WHEN_NUM_OF_ADC_READS met 48 | TaskHandle_t taskToNotify; 49 | // is handle successfully init 50 | BaseType_t isInitialized; 51 | } demo_tmIsrHandle_T; 52 | 53 | typedef struct { 54 | // handle of the task 55 | TaskHandle_t taskHandle; 56 | // ring buffers filled by tm isr 57 | ring_buffer_t *isrRingBuf[NUM_OF_RINGS]; 58 | // ring buffer notification 59 | uint8_t ringBufNotifyIdx; 60 | // analog digital converted value average 61 | float adcAvg; 62 | // adc avg values provider for the queue 63 | QueueHandle_t pAdcAvgQ; 64 | // is handle successfully init 65 | BaseType_t isInitialized; 66 | } demo_taskAHandle_T; 67 | 68 | typedef struct { 69 | // adc avg values consumer for the queue 70 | QueueHandle_t cAdcAvgQ; 71 | BaseType_t isInitialized; 72 | } demo_taskBHandle_T; 73 | 74 | typedef struct { 75 | demo_tmIsrHandle_T demoTmIsrHandle; 76 | demo_taskAHandle_T demoTaskAHandle; 77 | demo_taskBHandle_T demoTaskBHandle; 78 | QueueHandle_t adcAvgQ; 79 | } demo_mainHandle_T; 80 | 81 | void demo_init_tm(demo_tmIsrHandle_T *demoHandle, 82 | TaskHandle_t taskToNotify); 83 | 84 | void demo_init_taskA(demo_taskAHandle_T *demoHandle, 85 | ring_buffer_t *isrRing, 86 | QueueHandle_t providerAdcAvgQ); 87 | 88 | void demo_init_taskB(demo_taskBHandle_T *demoHandle, 89 | QueueHandle_t consumerAdcAvgQ); 90 | 91 | // this is just implemented to see if scheduler is running 92 | void demo_init_taskLed(void); 93 | 94 | 95 | #endif //DEMO_INIT_H -------------------------------------------------------------------------------- /configure.sh: -------------------------------------------------------------------------------- 1 | thisPath=$(realpath "$0") 2 | thisDirPath=$(dirname "$thisPath") 3 | source "${thisDirPath}/shell/util.sh" 4 | 5 | if [ -z "${GCC_ARM_NONE_EABI_BIN_PATH}" ] 6 | then 7 | echoerr environment variable GCC_ARM_NONE_EABI_BIN_PATH is empty 8 | ungracefulExit 9 | else 10 | echo "- found environment var GCC_ARM_NONE_EABI_BIN_PATH" 11 | fi 12 | 13 | out=$(${GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gcc --help 2>&1 1>/dev/null) 14 | if [ $? != 0 ] 15 | then 16 | echoerr "${out}" 17 | echoerr most likely GCC_ARM_NONE_EABI_BIN_PATH is not correct 18 | ungracefulExit 19 | else 20 | echo "- found arm-none-eabi-gcc" 21 | echoWTab "$(${GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gcc --version)" 22 | fi 23 | 24 | out=$(${GCC_ARM_NONE_EABI_BIN_PATH}/arm-none-eabi-gdb --help 2>&1 1>/dev/null) 25 | if [ $? != 0 ] 26 | then 27 | echoerr "${out}" 28 | echoerr most likely GCC_ARM_NONE_EABI_BIN_PATH is not correct 29 | ungracefulExit 30 | else 31 | echo "- found arm-none-eabi-gdb" 32 | fi 33 | 34 | out=$(make --help 2>&1 1>/dev/null) 35 | if [ $? != 0 ] 36 | then 37 | echoerr "${out}" 38 | echoerr most likely make is not installed 39 | ungracefulExit 40 | else 41 | echo "- found make" 42 | echoWTab "$(make --version)" 43 | fi 44 | 45 | out=$(cmake --help 2>&1 1>/dev/null) 46 | if [ $? != 0 ] 47 | then 48 | echoerr "${out}" 49 | echoerr most likely cmake is not installed 50 | ungracefulExit 51 | else 52 | echo "- found cmake" 53 | echoWTab "$(cmake --version)" 54 | fi 55 | 56 | files=$(find ${thisDirPath}/0_base/misc/FreeRTOS -type f) 57 | if [ -z "${files}" ] 58 | then 59 | echoerr FreeRTOS files not found. update submodules 60 | ungracefulExit 61 | else 62 | echo "- found FreeRTOS files" 63 | fi 64 | 65 | files=$(find "${thisDirPath}/shell" -type f) 66 | for file in ${files} 67 | do 68 | if [ ! -x "${file}" ] 69 | then 70 | echoerr "${file} does not have execute permission" 71 | ungracefulExit 72 | else 73 | echo "- found execute permission for ${file}" 74 | fi 75 | done 76 | 77 | out=$(qemu-system-arm --help 2>&1 1>/dev/null) 78 | if [ $? != 0 ] 79 | then 80 | echoerr "${out}" 81 | echoerr you are good to compile but can not run with qemu. 82 | echoerr most likely you dont have qemu installed or it is not in path. 83 | ungracefulExit 84 | else 85 | echo "- found qemu" 86 | echoWTab "$(qemu-system-arm --version)" 87 | fi 88 | 89 | echo 90 | echo SUCCESS!! 91 | -------------------------------------------------------------------------------- /shell/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script is used to build a demo 3 | # Usage: ./build.sh 4 | demoPath=$(realpath "$1") 5 | macro="" 6 | if [ ! -z "$2" ]; then 7 | macro="$2" 8 | fi 9 | 10 | thisPath=$(realpath "$0") 11 | thisDirPath=$(dirname "$thisPath") 12 | source "${thisDirPath}/util.sh" 13 | 14 | if [ -z "${demoPath}" ] 15 | then 16 | echoerr "demo path is not provided" 17 | ungracefulExit 18 | fi 19 | 20 | if [ ! -d "${demoPath}" ] 21 | then 22 | echoerr "demo path does not exist. ${demoPath}" 23 | ungracefulExit 24 | fi 25 | 26 | cd "${demoPath}" 27 | 28 | if [ $? != 0 ] 29 | then 30 | echoerr "cd ${demoPath} failure" 31 | ungracefulExit 32 | fi 33 | 34 | mkdir -p build 35 | cd build 36 | if [ ! -f build/Makefile ] 37 | then 38 | echo cmake .. ${macro} 39 | cmake .. ${macro} 40 | fi 41 | 42 | make -j all -------------------------------------------------------------------------------- /shell/preprocess.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script is used to preprocess a demo 3 | # Usage: ./preprocess.sh 4 | demoPath="$1" 5 | 6 | thisPath=$(realpath "$0") 7 | thisDirPath=$(dirname "$thisPath") 8 | source "${thisDirPath}/util.sh" 9 | 10 | if [ -z "${demoPath}" ] 11 | then 12 | echoerr "demo path is not provided" 13 | ungracefulExit 14 | fi 15 | 16 | if [ ! -d "${demoPath}" ] 17 | then 18 | echoerr "demo path does not exist" 19 | ungracefulExit 20 | fi 21 | 22 | out=$(python3 --help 2>&1 1>/dev/null) 23 | if [ $? != 0 ] 24 | then 25 | echoerr "${out}" 26 | echoerr most likely you dont have python3 installed 27 | ungracefulExit 28 | fi 29 | 30 | cd "${demoPath}/build" 31 | if [ $? != 0 ] 32 | then 33 | echoerr "cd ${demoPath}/build" failure 34 | ungracefulExit 35 | fi 36 | 37 | if [ ! -f Makefile ] 38 | then 39 | echoerr Makefile is not found 40 | ungracefulExit 41 | fi 42 | 43 | if [ ! -f "source_files.txt" ] 44 | then 45 | echoerr source_files.txt file is not found 46 | ungracefulExit 47 | fi 48 | 49 | if [ ! -f "include_files.txt" ] 50 | then 51 | echoerr include_files.txt file is not found 52 | ungracefulExit 53 | fi 54 | 55 | out=$(python3 - < 4 | demoPath=$(realpath "$1") 5 | macro="" 6 | if [ ! -z "$2" ]; then 7 | macro="$2" 8 | fi 9 | 10 | thisPath=$(realpath "$0") 11 | thisDirPath=$(dirname "$thisPath") 12 | source "${thisDirPath}/util.sh" 13 | 14 | if [ -z "${demoPath}" ] 15 | then 16 | echoerr "demo path is not provided" 17 | ungracefulExit 18 | fi 19 | 20 | if [ ! -d "${demoPath}" ] 21 | then 22 | echoerr "demo path does not exist${demoPath}" 23 | ungracefulExit 24 | fi 25 | 26 | rm -rf "${demoPath}/build" 27 | "${thisDirPath}/build.sh" ${demoPath} ${macro} 28 | -------------------------------------------------------------------------------- /shell/rebuild_all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | thisPath=$(realpath "$0") 4 | thisDirPath=$(dirname "$thisPath") 5 | source "${thisDirPath}/util.sh" 6 | prjRootPath=$(realpath "${thisDirPath}/../") # This is the root path of the project 7 | 8 | note="" 9 | 10 | for demo in ${demos} 11 | do 12 | macros=$(getMacros "${demo}") 13 | if [ -z "$macros" ] 14 | then 15 | echo "rebuilding ${demo}" 16 | echo "========================================" 17 | ${thisDirPath}/rebuild.sh "${prjRootPath}/${demo}" 18 | if [ $? != 0 ] 19 | then 20 | echoerr "build ${demo} failure" 21 | ungracefulExit 22 | else 23 | note="$note\nbuild ${demo} success" 24 | echo "build ${demo} success" 25 | echo "========================================" 26 | fi 27 | else 28 | for macro in ${macros} 29 | do 30 | echo "rebuilding ${demo} with ${macro}" 31 | echo "========================================" 32 | ${thisDirPath}/rebuild.sh ${prjRootPath}/${demo} ${macro} 33 | if [ $? != 0 ] 34 | then 35 | echoerr "build ${demo} with ${macro} failure" 36 | ungracefulExit 37 | else 38 | note="$note\nbuild ${demo} with ${macro} success" 39 | echo "build ${demo} with ${macro} success" 40 | echo "========================================" 41 | fi 42 | done 43 | fi 44 | done 45 | echo -e "$note\n" 46 | echo "All demos rebuilt successfully!" -------------------------------------------------------------------------------- /shell/rebuild_run_qemu.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script is used to build and run a project in QEMU 3 | # Usage: ./rebuild_run_qemu.sh 4 | # Eaxmple: ./rebuild_run_qemu.sh ../3_task_scheduling 5 | # Eaxmple: ./rebuild_run_qemu.sh ../3_task_scheduling debug 6 | # Eaxmple: ./rebuild_run_qemu.sh ../4_memory debug -DDEMO_1_C:BOOL=ON 7 | thisPath=$(realpath "$0") 8 | thisDirPath=$(dirname "$thisPath") 9 | demoPath="$1" 10 | debug="" 11 | macro="" 12 | 13 | for arg in $@ 14 | do 15 | if [[ $arg == -D* ]] 16 | then 17 | macro="$arg" 18 | elif [[ $arg == debug ]] 19 | then 20 | debug=debug 21 | fi 22 | done 23 | 24 | thisPath=$(realpath "$0") 25 | thisDirPath=$(dirname "$thisPath") 26 | source "${thisDirPath}/util.sh" 27 | 28 | ${thisDirPath}/rebuild.sh ${demoPath} ${macro} 29 | 30 | if [ $? != 0 ]; then 31 | echoerr "compilation failure" 32 | ungracefulExit 33 | fi 34 | 35 | if [ ! -f "${demoPath}/build/demo" ] 36 | then 37 | echoerr "demo executable not found" 38 | ungracefulExit 39 | fi 40 | 41 | echo 'QEMU_started' 42 | ${thisDirPath}/run_qemu.sh "${demoPath}/build/demo" "${debug}" -------------------------------------------------------------------------------- /shell/run_qemu.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script is used to run a demoBin 3 | # Usage: ./run_qemu.sh 4 | demoBin="$1" 5 | debug="$2" 6 | 7 | thisPath=$(realpath "$0") 8 | thisDirPath=$(dirname "$thisPath") 9 | source "${thisDirPath}/util.sh" 10 | 11 | if [ ! -f "$demoBin" ] 12 | then 13 | echoerr "demoBin binary does not exist: $demoBin" 14 | ungracefulExit 15 | fi 16 | 17 | buildPath=$(dirname "${demoBin}") 18 | logFile=${buildPath}/log.txt 19 | errFile=${buildPath}/err.txt 20 | 21 | debugFlags="" 22 | 23 | if [ "$debug" == "debug" ] 24 | then 25 | debugFlags="-s -S" 26 | echo QEMU_DEBUG_MODE 27 | elif [ "$debug" == "" ] 28 | then 29 | debugFlags="" 30 | else 31 | echoerr "Invalid debug flag: $debug" 32 | ungracefulExit 33 | fi 34 | 35 | if [ -z ${FREERTOS_INTRO_QEMU_TERM} ] 36 | then 37 | echo CONNECT below serial port to see simulated hardware: 38 | qemu-system-arm -machine mps2-an385 -cpu cortex-m3 -kernel "$demoBin" -monitor none -nographic -serial stdio -serial pty $debugFlags | tee ${logFile} 39 | else 40 | ${FREERTOS_INTRO_QEMU_TERM} -- bash -c "${thisDirPath}/screen_hw.sh ${logFile}" > ${errFile} 2>&1 41 | # somehow auto screen failed. do manually 42 | if [ $? != 0 ] 43 | then 44 | echo see ${errFile} why auto screen failed. 45 | echo CONNECT below serial port to see simulated hardware: 46 | fi 47 | qemu-system-arm -machine mps2-an385 -cpu cortex-m3 -kernel "$demoBin" -monitor none -nographic -serial stdio -serial pty $debugFlags | tee ${logFile} 48 | fi -------------------------------------------------------------------------------- /shell/screen_hw.sh: -------------------------------------------------------------------------------- 1 | logFile=$1 2 | serialPort="" 3 | while [ 1 == 1 ] 4 | do 5 | line=$(cat $logFile | grep 'char device redirected to ') 6 | if [ ! -z "$line" ] 7 | then 8 | serialPort=$(echo $line | awk '{print $5}') 9 | echo Found $serialPort 10 | break 11 | fi 12 | done 13 | 14 | screen $serialPort 15 | -------------------------------------------------------------------------------- /shell/util.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | demos="\ 4 | 2_blinky \ 5 | 3_task_scheduling \ 6 | 3_task_scheduling_challenge \ 7 | 4_memory \ 8 | 4_memory_challenge \ 9 | 5_queue \ 10 | 5_queue_challenge \ 11 | 6_mutex \ 12 | 6_mutex_challenge \ 13 | 7_semaphore \ 14 | 7_semaphore_challenge \ 15 | 8_sw_timers \ 16 | 8_sw_timers_challenge \ 17 | 9_hw_int \ 18 | 9_hw_int_challenge \ 19 | 10_deadlock_starvation \ 20 | 10_deadlock_starvation_challenge \ 21 | 11_priority_inversion \ 22 | 11_priority_inversion_challenge" 23 | 24 | getMacros() 25 | { 26 | demo_4_memory_macros="\ 27 | -DDEMO_1_C:BOOL=ON\ 28 | -DDEMO_2_C:BOOL=ON\ 29 | -DDEMO_3_C:BOOL=ON\ 30 | -DDEMO_4_C:BOOL=ON\ 31 | -DDEMO_5_C:BOOL=ON\ 32 | -DDEMO_6_C:BOOL=ON\ 33 | " 34 | 35 | demo_6_mutex_macros="\ 36 | -DDEMO_RACE_C:BOOL=ON\ 37 | -DDEMO_MUTEX_C:BOOL=ON\ 38 | " 39 | 40 | demo_9_hw_int_macros="\ 41 | -DDEMO_TM_C:BOOL=ON\ 42 | -DDEMO_ADC_C:BOOL=ON\ 43 | -DDEMO_NOTIFY_C:BOOL=ON\ 44 | " 45 | 46 | demo_10_deadlock_starvation_macros="\ 47 | -DDEMO_CHAIR_C:BOOL=ON\ 48 | -DDEMO_DEADLOCK_C:BOOL=ON\ 49 | -DDEMO_LIVELOCK_C:BOOL=ON\ 50 | -DDEMO_STICK_PRIO_C:BOOL=ON\ 51 | " 52 | 53 | demo_11_priority_inversion_macros="\ 54 | -DDEMO_UNBOUNDED_C:BOOL=ON\ 55 | -DDEMO_INHERITANCE_C:BOOL=ON\ 56 | " 57 | 58 | demo="$1" 59 | if [ "${demo}" == "4_memory" ] 60 | then 61 | echo "${demo_4_memory_macros}" 62 | elif [ "${demo}" == "6_mutex" ] 63 | then 64 | echo "${demo_6_mutex_macros}" 65 | elif [ "${demo}" == "9_hw_int" ] 66 | then 67 | echo "${demo_9_hw_int_macros}" 68 | elif [ "${demo}" == "10_deadlock_starvation" ] 69 | then 70 | echo "${demo_10_deadlock_starvation_macros}" 71 | elif [ "${demo}" == "11_priority_inversion" ] 72 | then 73 | echo "${demo_11_priority_inversion_macros}" 74 | fi 75 | } 76 | 77 | echoerr() { echo "$@" 1>&2; } 78 | 79 | ungracefulExit() 80 | { 81 | echoerr 82 | echoerr ERROR!! $0 83 | exit 1 84 | } 85 | 86 | echoWTab() 87 | { 88 | while IFS= read -r line; do 89 | echo -e "\t$line" 90 | done <<< "$@" 91 | } --------------------------------------------------------------------------------