### Example Build and Run Command Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/CoreValidation/README.md Example of building and running tests using GCC for Cortex-M3 with 'none' optimization level. This command demonstrates the usage of the build.py script. ```bash ./CMSIS/CoreValidation/Project $ ./build.py -c GCC -d CM3 -o none build run ``` -------------------------------- ### PMU Initialization and Configuration Example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Core/src/ref_pmu8.txt This example demonstrates how to initialize, configure, and use the PMU to count specific events like instructions retired and L1 D-Cache misses. ```APIDOC ## PMU Initialization and Configuration Example ### Description This example demonstrates how to initialize, configure, and use the PMU to count specific events like instructions retired and L1 D-Cache misses. ### Usage ```c // Initialize counter variables unsigned int cycle_count = 0; unsigned int l1_dcache_miss_count = 0; unsigned int instructions_retired_count = 0; // Enable the PMU // Note: Before using the PMU, software needs to ensure // that trace is enabled via the Debug Exception Monitor Control Register, DEMCR: // CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; ARM_PMU_Enable(); // Configure Event Counter Register 0 to count instructions retired // Configure Event Counter Register 1 to count L1 D-Cache misses ARM_PMU_Set_EVTYPER(0, ARM_PMU_INST_RETIRED); ARM_PMU_Set_EVTYPER(1, ARM_PMU_L1D_CACHE_MISS_RD); // Reset Event Counters and Cycle Counter ARM_PMU_EVCNTR_ALL_Reset(); ARM_PMU_CYCCNT_Reset(); // Start incrementing Cycle Count Register and Event Counter Registers 0 & 1 ARM_PMU_CNTR_Enable(PMU_CNTENSET_CCNTR_ENABLE_Msk|PMU_CNTENSET_CNT0_ENABLE_Msk|PMU_CNTENSET_CNT1_ENABLE_Msk); // Code you want to measure here // Stop incrementing Cycle Count Register and Event Counter Registers 0 & 1 ARM_PMU_CNTR_Disable(PMU_CNTENCLR_CCNTR_ENABLE_Msk|PMU_CNTENCLR_CNT0_ENABLE_Msk|PMU_CNTENCLR_CNT1_ENABLE_Msk); // Get cycle count, number of instructions retired and number of L1 D-Cache misses (on read) cycle_count = cycle_count + ARM_PMU_Get_CCNTR(); instructions_retired_count = instructions_retired_count + ARM_PMU_Get_EVCNTR(0); l1_dcache_miss_count = l1_dcache_miss_count + ARM_PMU_Get_EVCNTR(1); // Note: D-Cache must be enabled using // SCB_EnableDCache() for meaningful result. ``` ### Functions Used - `ARM_PMU_Enable()`: Enables the Performance Monitoring Unit. - `ARM_PMU_Set_EVTYPER(counter, event)`: Configures an event counter to monitor a specific event. - `ARM_PMU_EVCNTR_ALL_Reset()`: Resets all event counters. - `ARM_PMU_CYCCNT_Reset()`: Resets the cycle counter. - `ARM_PMU_CNTR_Enable(mask)`: Enables specified counters. - `ARM_PMU_CNTR_Disable(mask)`: Disables specified counters. - `ARM_PMU_Get_CCNTR()`: Retrieves the value of the cycle counter. - `ARM_PMU_Get_EVCNTR(counter)`: Retrieves the value of a specified event counter. ### Constants Used - `ARM_PMU_INST_RETIRED`: Event ID for instructions retired. - `ARM_PMU_L1D_CACHE_MISS_RD`: Event ID for L1 D-Cache read misses. - `PMU_CNTENSET_CCNTR_ENABLE_Msk`, `PMU_CNTENSET_CNT0_ENABLE_Msk`, `PMU_CNTENSET_CNT1_ENABLE_Msk`: Masks for enabling counters. - `PMU_CNTENCLR_CCNTR_ENABLE_Msk`, `PMU_CNTENCLR_CNT0_ENABLE_Msk`, `PMU_CNTENCLR_CNT1_ENABLE_Msk`: Masks for disabling counters. ``` -------------------------------- ### Basic CMSIS Example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Core/src/using.md A typical example demonstrating the use of the CMSIS layer for device initialization and main application loop. ```c #include // File name depends on device used uint32_t volatile msTicks; // Counter for millisecond Interval void SysTick_Handler (void) { // SysTick Interrupt Handler msTicks++; // Increment Counter } void WaitForTick (void) { uint32_t curTicks; curTicks = msTicks; // Save Current SysTick Value while (msTicks == curTicks) { // Wait for next SysTick Interrupt __WFE (); // Power-Down until next Event/Interrupt } } void TIM1_UP_IRQHandler (void) { // Timer Interrupt Handler ; // Add user code here } void timer1_init(int frequency) { // Set up Timer (device specific) NVIC_SetPriority (TIM1_UP_IRQn, 1); // Set Timer priority NVIC_EnableIRQ (TIM1_UP_IRQn); // Enable Timer Interrupt } void Device_Initialization (void) { // Configure & Initialize MCU if (SysTick_Config (SystemCoreClock / 1000)) { // SysTick 1mSec : // Handle Error } timer1_init (); // setup device-specific timer } // The processor clock is initialized by CMSIS startup + system file void main (void) { // user application starts here Device_Initialization (); // Configure & Initialize MCU while (1) { // Endless Loop (the Super-Loop) __disable_irq (); // Disable all interrupts Get_InputValues (); // Read Values __enable_irq (); // Enable all interrupts Calculation_Response (); // Calculate Results Output_Response (); // Output Results WaitForTick (); // Synchronize to SysTick Timer } } ``` -------------------------------- ### Build and Run Output Example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/CoreValidation/README.md Example output from the build.py script when building and running tests for GCC on Cortex-M3. It shows the progress of csolution and cbuild steps, and the final matrix summary. ```bash [GCC][Cortex-M3][none](build:csolution) csolution convert -s Validation.csolution.yml -c Validation.GCC_low+CM3 [GCC][Cortex-M3][none](build:csolution) csolution succeeded with exit code 0 [GCC][Cortex-M3][none](build:cbuild) cbuild Validation.GCC_low+CM3/Validation.GCC_low+CM3.cprj [GCC][Cortex-M3][none](build:cbuild) cbuild succeeded with exit code 0 [GCC][Cortex-M3][none](run:model_exec) FVP_MPS2_Cortex-M3 -q --simlimit 5 -f ../Layer/Target/CM3/model_config.txt -a Validation.GCC_low+CM3/Validation.GCC_low+CM3_outdir/Validation.GCC_low+CM3.elf [GCC][Cortex-M3][none](run:model_exec) FVP_MPS2_Cortex-M3 succeeded with exit code 0 Matrix Summary ============== compiler device optimize build clean extract run ---------- --------- ---------- ------- ------- --------- ----- GCC Cortex-M3 none success (skip) (skip) 35/35 ``` -------------------------------- ### Initialize and Start vStream Driver Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Driver/src/vStream.txt Initializes the vStream driver, sets up the buffer, and starts continuous data streaming. Ensure SystemCoreClockUpdate is called before initialization. ```c #include "cmsis_vstream.h" // vStream driver extern vStreamDriver_t Driver_vStreamAccelerometer; static vStreamDriver_t *ptrDriver_vStreamAccelerometer = &Driver_vStreamAccelerometer; static uint32_t vstream_buf[256]; int main (void) { static volatile uint32_t *ptr_sensor_data_block; SystemCoreClockUpdate(); // System Initialization ptrDriver_vStreamAccelerometer->Initialize(NULL); ptrDriver_vStreamAccelerometer->SetBuf(vstream_buf, sizeof(vstream_buf), sizeof(vstream_buf)/2); ptrDriver_vStreamAccelerometer->Start(VSTREAM_MODE_CONTINUOUS); do { ptr_sensor_data_block = ptrDriver_vStreamAccelerometer->GetBlock(); } while (ptr_sensor_data_block == NULL); // ... ptrDriver_vStreamAccelerometer->Stop(); ptrDriver_vStreamAccelerometer->Uninitialize(); } ``` -------------------------------- ### Initialize and Start RTOS Kernel Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/RTOS2/src/ref_cmsis_os2_kernel.txt Initializes the RTOS kernel, creates a new thread, and starts the kernel's execution. This is a typical setup for an embedded application's main function. ```c #include "RTE_Components.h" #include CMSIS_device_header #include "cmsis_os2.h" /*---------------------------------------------------------------------------- * Application main thread *---------------------------------------------------------------------------*/ void app_main (void *argument) { // ... for (;;) {} } int main (void) { // System Initialization SystemCoreClockUpdate(); // ... osKernelInitialize(); // Initialize CMSIS-RTOS osThreadNew(app_main, NULL, NULL); // Create application main thread osKernelStart(); // Start thread execution for (;;) {} } ``` -------------------------------- ### OS_Tick_Setup Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/RTOS2/src/ref_os_tick.txt Setup OS Tick timer to generate periodic RTOS Kernel Ticks. Configures the timer to generate interrupts at a specified frequency and sets the interrupt handler. The timer is initialized but not started; the RTOS kernel starts interrupts using OS_Tick_Enable. ```APIDOC ## OS_Tick_Setup ### Description Setup OS Tick timer to generate periodic RTOS Kernel Ticks. The timer should be configured to generate periodic interrupts at frequency specified by `freq`. The parameter `handler` defines the interrupt handler function that is called. The timer should only be initialized and configured but must not be started to create interrupts. The RTOS kernel calls the function `OS_Tick_Enable` to start the timer interrupts. ### Parameters #### Path Parameters - **freq** (uint32_t) - Required - The frequency of the OS Tick timer in Hz. - **handler** (IRQHandler_t) - Required - The interrupt handler function. ### Return Value - **0** on success - **-1** if `freq` is 0 or if the calculated load value is invalid. ``` -------------------------------- ### MPU Configuration Example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Core/src/ref_mpu8.txt Demonstrates how to set memory attributes and region definitions for the MPU, and then enable/disable the MPU. ```APIDOC ## MPU Configuration Example ### Description This example shows how to configure memory attributes and define memory regions using the MPU functions. It also demonstrates enabling and disabling the MPU. ### Usage ```c int main() { // Set Region 0 using Attr 0 ARM_MPU_SetMemAttr(0UL, ARM_MPU_ATTR( /* Normal memory */ MPU_ATTR_NORMAL_OUTER_WT_TR_RA_WA, /* Outer Write-Back transient with read and write allocate */ MPU_ATTR_NORMAL_INNER_WT_TR_RA_WA /* Inner Write-Through transient with read and write allocate */ )); ARM_MPU_SetRegion(0UL, ARM_MPU_RBAR(0x08000000UL, ARM_MPU_SH_NON, ARM_MPU_AP_RW, ARM_MPU_AP_NP, ARM_MPU_XN), /* Non-shareable, read/write, non-privileged, execute-never */ ARM_MPU_RLAR(0x080FFFFFUL, MAIR_ATTR(0)) /* 1MB memory block using Attr 0 */ ); ARM_MPU_Enable(0); // Execute application code that is access protected by the MPU ARM_MPU_Disable(); } ``` ``` -------------------------------- ### Example LIT Test Execution Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Core/Test/README.md An example demonstrating how to run LIT tests using GCC for Cortex-M3 with no optimization. This command triggers the build and test execution process. ```bash ./CMSIS/Core/Test $ ./build.py -c GCC -d CM3 -o none lit ``` -------------------------------- ### Install Python Requirements Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/CoreValidation/README.md Installs the necessary Python packages required by the build script. Ensure you are in the Project directory. ```bash ./CMSIS/CoreValidation/Project $ pip install -r requirements.txt ``` -------------------------------- ### Timer Interrupt Example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Core/src/ref_nvic.txt This example demonstrates the configuration and enabling of a timer interrupt, including setting up the timer, enabling its interrupt in the NVIC, and enabling the timer itself. It also shows how to acknowledge the interrupt. ```c LPC_TIM0->IR |= (1 << 0); /* Acknowledge interrupt for match channel 0 occurred*/ } active = NVIC_GetActive(TIMER0_IRQn); /* Get interrupt active state of timer 0*/ } int main (void) { /* Set match channel register MR0 to 1 millisecond*/ LPC_TIM0->MR0 = (((SystemCoreClock / 1000) / 4) - 1); /* 1 ms?*/ LPC_TIM0->MCR = (3 << 0); /* Enable interrupt and reset for match channel MR0*/ NVIC_EnableIRQ(TIMER0_IRQn); /* Enable NVIC interrupt for timer 0*/ LPC_TIM0->TCR = (1 << 0); /* Enable timer 0*/ while(1); } ``` -------------------------------- ### Joinable threads example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/RTOS2/src/ref_cmsis_os2_thread.txt Demonstrates the creation of joinable threads and synchronization using osThreadJoin. ```APIDOC ## Joinable Threads with osThreadJoin ### Description This example illustrates creating multiple joinable threads, performing work, and then synchronizing their termination using `osThreadJoin`. The master thread waits for all worker threads to complete before exiting. ### Method osThreadNew, osThreadJoin, osThreadExit ### Parameters - **worker function**: The function executed by the worker threads. - **argument**: Argument passed to the worker thread function. - **worker_attr**: Thread attributes for worker threads, including `osThreadJoinable`. - **worker_ids**: Array to store the thread IDs of the created worker threads. - **data**: Data array used by the worker threads. ### Request Example ```c __NO_RETURN void worker (void *argument) { // ... work a lot on data[] osDelay(1000U); osThreadExit(); } __NO_RETURN void thread1 (void *argument) { osThreadAttr_t worker_attr; osThreadId_t worker_ids[4]; uint8_t data[4][10]; memset(&worker_attr, 0, sizeof(worker_attr)); worker_attr.attr_bits = osThreadJoinable; worker_ids[0] = osThreadNew(worker, &data[0][0], &worker_attr); worker_ids[1] = osThreadNew(worker, &data[1][0], &worker_attr); worker_ids[2] = osThreadNew(worker, &data[2][0], &worker_attr); worker_ids[3] = osThreadNew(worker, &data[3][0], &worker_attr); osThreadJoin(worker_ids[0]); osThreadJoin(worker_ids[1]); osThreadJoin(worker_ids[2]); osThreadJoin(worker_ids[3]); osThreadExit(); } ``` ### Response - **void**: The `thread1` function orchestrates the creation and joining of worker threads. Worker threads exit upon completion of their task. The master thread exits after all workers have joined. ``` -------------------------------- ### Install Python Dependencies Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Core/Test/README.md Installs the necessary Python packages listed in requirements.txt for the build.py script to function correctly. ```bash ./CMSIS/Core/Test $ pip install -r requirements.txt ``` -------------------------------- ### Cortex-A9 Basic CMSIS Example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Core_A/src/using.md This example demonstrates initializing a private timer for millisecond ticks and implementing a delay function using CMSIS for a Cortex-A9 processor. Ensure the correct device header file is included. ```c #include // File name depends on device used static const uint32_t TICK_RATE_HZ = 1000U; uint32_t volatile msTicks; static void SysTick_Handler( void ) { msTicks++; // Increment Counter } // We use the Private Tiemer (PTIM) of the Cortex-A9 FVP Model here. // In general the available Timers are highly vendor specific for Cortex-A processors. void private_timer_init(void) { PTIM_SetLoadValue ((SystemCoreClock/TICK_RATE_HZ) - 1U); PTIM_SetControl (PTIM_GetControl() | 7U); /* Install SysTick_Handler as the interrupt function for PTIM */ IRQ_SetHandler((IRQn_ID_t)PrivTimer_IRQn, SysTick_Handler); /* Determine number of implemented priority bits */ IRQ_SetPriority ((IRQn_ID_t)PrivTimer_IRQn, IRQ_PRIORITY_Msk); /* Set lowest priority -1 */ IRQ_SetPriority ((IRQn_ID_t)PrivTimer_IRQn, GIC_GetPriority((IRQn_ID_t)PrivTimer_IRQn)-1); /* Enable IRQ */ IRQ_Enable ((IRQn_ID_t)PrivTimer_IRQn); } /* Delay execution for given amount of ticks */ void Delay(uint32_t ticks) { uint32_t tgtTicks = msTicks + ticks; // target tick count to delay execution to while (msTicks == tgtTicks) { __WFE (); // Power-Down until next Event/Interrupt } } /* main function */ int main(void) { /* Initialize device HAL here */ private_timer_init(); static uint8_t ledState = 0; /* Infinite loop */ while (1) { /* Add application code here */ ledState = !ledState; Delay(500); } } ``` -------------------------------- ### Get VIO Signal Example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Driver/src/VIO.txt Retrieves a signal from an input identified by a mask. Use this function to read data from any provided input. ```c #include "cmsis_vio.h" ``` -------------------------------- ### SPI Interface Usage Example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Driver/src/operation.md Demonstrates the usage of the SPI interface. Ensure the SPI driver is correctly configured before use. ```c #include "Driver_SPI.h" extern ARM_DRIVER_SPI Driver_SPI0; // SPI0 Device Configuration #define SPI0_DEVICE Driver_SPI0 // SPI0 Transfer int32_t spi_transfer (void) { int32_t ret = -1; uint8_t send_buffer[10] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A}; uint8_t receive_buffer[10]; // Initialize SPI0 (optional, if not done elsewhere) // ret = SPI0_DEVICE.Initialize(NULL); // Power control for SPI0 (optional, if not done elsewhere) // ret = SPI0_DEVICE.PowerControl(ARM_POWER_FULL); // Configure SPI0 // ret = SPI0_DEVICE.Configure(ARM_SPI_MODE_MASTER, ARM_SPI_DATA_BITS(8), ARM_SPI_FLOWCONTROL_NONE); // Send and receive data // ret = SPI0_DEVICE.Send(send_buffer, 10); // ret = SPI0_DEVICE.Receive(receive_buffer, 10); // Wait for transfer to complete (implementation specific) // ... // Unconfigure SPI0 (optional, if not done elsewhere) // ret = SPI0_DEVICE.Unconfigure(); // Release power for SPI0 (optional, if not done elsewhere) // ret = SPI0_DEVICE.PowerControl(ARM_POWER_OFF); // Uninitialize SPI0 (optional, if not done elsewhere) // ret = SPI0_DEVICE.Uninitialize(); return ret; } ``` -------------------------------- ### Create Simple Thread Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/RTOS2/src/ref_cmsis_os2_thread.txt Creates a thread using default settings. Ensure the kernel is initialized and started. ```c __NO_RETURN void thread1 (void *argument) { // ... for (;;) {} } int main (void) { osKernelInitialize(); ; osThreadNew(thread1, NULL, NULL); // Create thread with default settings ; osKernelStart(); } ``` -------------------------------- ### MPU Configuration Example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/RTOS2/src/ref_cmsis_os2_thread.txt This snippet demonstrates MPU configuration for zones. Refer to MPU Functions in CMSIS-Core documentation for ARM_MPU_ functions. ```c ARM_MPU_Disable(); ARM_MPU_Load(mpu_table[zone], MPU_REGIONS); ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk); } ``` -------------------------------- ### Start Sequence for Peripheral Operation Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Driver/src/operation.md Call Initialize and PowerControl in this order to start working with a peripheral. Initialize allocates I/O pins, and PowerControl powers up the peripheral and sets up IRQ/DMA. ```c drv->Initialize (...); // Allocate I/O pins drv->PowerControl (ARM_POWER_FULL); // Power up peripheral, setup IRQ/DMA ``` -------------------------------- ### Thread Exit Example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/RTOS2/src/ref_cmsis_os2_thread.txt This example demonstrates how to terminate the calling thread using osThreadExit. It includes a delay before exiting. ```c __NO_RETURN void worker (void *argument) { // do something osDelay(1000U); osThreadExit(); } ``` -------------------------------- ### Doxygen Comment Example for Function Documentation Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/General/src/mainpage.md This example demonstrates the Doxygen comment style used for documenting functions within CMSIS. It includes a brief overview, detailed description, parameter explanation, and return value information. ```c /** * @brief Enable Interrupt in NVIC Interrupt Controller * @param IRQn interrupt number that specifies the interrupt * @return none. * Enable the specified interrupt in the NVIC Interrupt Controller. * Other settings of the interrupt such as priority are not affected. */ ``` -------------------------------- ### osKernelStart Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/RTOS2/src/ref_cmsis_os2_kernel.txt Starts the RTOS kernel and begins thread switching. This function will not return if successful. It cannot be called from Interrupt Service Routines. ```APIDOC ## osKernelStart ### Description Starts the RTOS kernel and begins thread switching. This function will not return if successful. It cannot be called from Interrupt Service Routines. ### Returns - `osError`: Unspecific error. - `osErrorISR`: If called from an Interrupt Service Routine. ### Note This function cannot be called from Interrupt Service Routines. ``` -------------------------------- ### Enable GIC Interface Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Core_A/src/ref_core_ca.txt Example of enabling the GIC Interface by setting a bit in the control register. ```c GICInterface->C_CTLR |= 1; // Enable Interface ``` -------------------------------- ### Query GIC Priority Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Core_A/src/ref_gic.txt Example code demonstrating how to query the actual interrupt priorities available in the GIC implementation. ```c uint32_t priority_max = GIC_GetPriority(IRQn_MAX); uint32_t priority_val = GIC_GetPriority(IRQn_MyInterrupt); ``` -------------------------------- ### Create thread with a different priority Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/RTOS2/src/ref_cmsis_os2_thread.txt This example shows how to set an initial priority for a newly created thread, overriding the default priority. ```APIDOC ## osThreadNew with custom priority ### Description Creates a new thread and assigns it an initial priority, allowing for custom scheduling behavior. ### Method osThreadNew ### Parameters - **thread**: Pointer to the thread function that does not return. - **argument**: Argument that is passed to the thread function. - **attr**: Pointer to the thread attribute structure. The `priority` field is used to set the initial thread priority. ### Request Example ```c __NO_RETURN void thread1 (void *argument) { // ... for (;;) } const osThreadAttr_t thread1_attr = { .priority = osPriorityHigh // Set initial thread priority to high }; osThreadNew(thread1, NULL, &thread1_attr); ``` ### Response - **osThreadId_t**: Success: thread ID of created thread. Failure: NULL object. ``` -------------------------------- ### VIO Initialization Example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Driver/src/VIO.txt Initializes VIO signals and associated hardware. Use this to set up user variables and connect VIOs to actual hardware components like LEDs and buttons. ```c #if !defined CMSIS_VIN // Add user variables here: #endif #if !defined CMSIS_VOUT // Add user variables here: #endif vioSignalIn = 0U; vioSignalOut = 0U; memset(vioValue, 0, sizeof(vioValue)); #if !defined CMSIS_VOUT // Add user code here: // BSP_LED_Init(LED_BLUE); BSP_LED_Init(LED_RED); BSP_LED_Init(LED_GREEN); // #endif #if !defined CMSIS_VIN // Add user code here: // BSP_PB_Init(BUTTON_USER, BUTTON_MODE_GPIO); // #endif return; ``` -------------------------------- ### Setup OS Tick Timer (Cortex-M SysTick) Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/RTOS2/src/ref_os_tick.txt Configures the OS Tick timer to generate periodic interrupts at a specified frequency. The timer is initialized but not started; the RTOS kernel starts it later. ```c #ifndef SYSTICK_IRQ_PRIORITY #define SYSTICK_IRQ_PRIORITY 0xFFU #endif static uint8_t PendST; int32_t OS_Tick_Setup (uint32_t freq, IRQHandler_t handler) { (void)handler; uint32_t load; if (freq == 0U) { return (-1); } load = (SystemCoreClock / freq) - 1U; if (load > 0x00FFFFFFU) { return (-1); } NVIC_SetPriority(SysTick_IRQn, SYSTICK_IRQ_PRIORITY); SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk; SysTick->LOAD = load; SysTick->VAL = 0U; PendST = 0U; return (0); } ``` -------------------------------- ### Get DACR Register Value Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Core_A/src/ref_core_reg.txt Use this function to retrieve the current value of the DACR register. No specific setup is required. ```c __STATIC_INLINE uint32_t __get_DACR() { return 0; } ``` -------------------------------- ### Get Current Thread ID Example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/RTOS2/src/ref_cmsis_os2_thread.txt Retrieves the unique identifier of the currently executing thread. Returns NULL if the ID cannot be obtained. ```c void ThreadGetId_example (void) { osThreadId_t id; id = osThreadGetId(); if (id == NULL) { // Failed to get the id } } ``` -------------------------------- ### SystemCoreClock Usage Example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Core/src/ref_system_init.txt Demonstrates how to use SystemCoreClock, SystemInit, and SystemCoreClockUpdate. It's recommended to call SystemCoreClockUpdate at the beginning of main to ensure SystemCoreClock reflects the current system clock speed. ```c #include "LPC17xx.h" uint32_t coreClock_1 = 0; /* Variables to store core clock values */ uint32_t coreClock_2 = 0; int main (void) { coreClock_1 = SystemCoreClock; /* Store value of predefined SystemCoreClock */ SystemCoreClockUpdate(); /* Update SystemCoreClock according to register settings */ coreClock_2 = SystemCoreClock; /* Store value of calculated SystemCoreClock */ if (coreClock_2 != coreClock_1) { /* Without changing the clock setting both core clock values should be the same */ // Error Handling } while(1); } ``` -------------------------------- ### Get Kernel State Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/RTOS2/src/ref_cmsis_os2_kernel.txt Returns the current state of the kernel. This function can be safely called before the RTOS is initialized or started, and also from Interrupt Service Routines. ```c int main (void) { // System Initialization SystemCoreClockUpdate(); // ... if(osKernelGetState() == osKernelInactive) { // Is the kernel initialized? osKernelInitialize(); // Initialize CMSIS-RTOS kernel } ; } ``` -------------------------------- ### IRQ Controller Initialization and Configuration Example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Core_A/src/ref_irq_ctrl.txt Demonstrates initializing the interrupt controller, registering a handler, setting priority and mode, enabling, triggering, and disabling an interrupt. Use this for setting up and managing interrupts in your application. ```c void SGI0_Handler() { /* * Handle Interrupt */ IRQ_ClearPending((IRQn_ID_t)SGI0_IRQn); } void main() { /* Initialize the Interrupt Controller */ IRQ_Initialize(); /* Register the user defined handler function */ IRQ_SetHandler((IRQn_ID_t)SGI0_IRQn, SGI0_Handler); /* Set the priority considering the priority grouping */ const uint32_t subprio = IRQ_GetPriorityGroupBits(); IRQ_SetPriority((IRQn_ID_t)SGI0_IRQn, 1u << subprio); /* Set interrupt mode to falling edge */ IRQ_SetMode((IRQn_ID_t)SGI0_IRQn, IRQ_MODE_TYPE_IRQ | IRQ_MODE_CPU_0 | IRQ_MODE_TRIG_EDGE | IRQ_MODE_TRIG_EDGE_FALLING); IRQ_Enable((IRQn_ID_t)SGI0_IRQn); /* Trigger interrupt */ IRQ_SetPending((IRQn_ID_t)SGI0_IRQn); IRQ_Disable((IRQn_ID_t)SGI0_IRQn); } ``` -------------------------------- ### Get Thread Name Example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/RTOS2/src/ref_cmsis_os2_thread.txt Retrieves the name of the currently running thread. Returns NULL if the thread ID is invalid or if called outside of a thread context. ```c void ThreadGetName_example (void) { osThreadId_t thread_id = osThreadGetId(); const char* name = osThreadGetName(thread_id); if (name == NULL) { // Failed to get the thread name; not in a thread } } ``` -------------------------------- ### Start or Restart Timer - CMSIS-RTOS2 Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/RTOS2/src/ref_cmsis_os2_timer.txt Starts or restarts a timer with a specified delay in time ticks. This function cannot be called from interrupt service routines. Ensure the timer is created before starting. ```c #include "cmsis_os2.h" void Timer_Callback (void *arg) { // timer callback function // arg contains &exec // called every second after osTimerStart } uint32_t exec; // argument for the timer call back function void TimerStart_example (void) { osTimerId_t id; // timer id uint32_t timerDelay; // timer value osStatus_t status; // function return status // Create periodic timer exec = 1U; id = osTimerNew(Timer_Callback, osTimerPeriodic, &exec, NULL); if (id != NULL) { timerDelay = 1000U; status = osTimerStart(id, timerDelay); // start timer if (status != osOK) { // Timer could not be started } } ; } ``` -------------------------------- ### osTimerStart Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/RTOS2/src/ref_cmsis_os2_timer.txt Starts or restarts a timer. If the timer is already running, it will be restarted with the specified interval. If the timer is not running, it will be started. ```APIDOC ## osTimerStart ### Description Starts or restarts a timer with a specified interval. ### Signature ```c osStatus_t osTimerStart (osTimerId_t timer_id, uint32_t interval) ``` ### Parameters #### Parameters - **timer_id** (`osTimerId_t`): The ID of the timer to start or restart. - **interval** (`uint32_t`): The interval in system ticks for the timer. For periodic timers, this is the time between successive calls to the callback function. For one-shot timers, this is the time until the callback function is called. ### Return Value - `osOK`: The timer was started or restarted successfully. - `osErrorResource`: The timer could not be started or restarted. ``` -------------------------------- ### Zone Setup Callback Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/RTOS2/src/ref_cmsis_os2_thread.txt Implement osZoneSetup_Callback to handle MPU Protected Zone changes. This callback is invoked by the kernel when a zone's status changes. ```c /* Update MPU settings for newly activating Zone */ void osZoneSetup_Callback (uint32_t zone) { if (zone >= ZONES_NUM) { ``` -------------------------------- ### Middleware Initialization with Driver Instance Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Driver/src/operation.md Demonstrates how to pass a specific driver instance (e.g., SPI1) to middleware for communication. Inside middleware, driver functions are called via function pointers. ```c void init_middleware (ARM_DRIVER_SPI *Drv_spi) ... \ inside the middleware the SPI driver functions are called with: \ Drv_spi->function (...); ``` ```c \ setup middleware init_middleware (&Driver_SPI1); // connect middleware to SPI1 interface : init_middleware (&Driver_SPI2); // connect middleware to SPI2 interface ``` -------------------------------- ### Startup File Template (Arm Compiler) Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Core_A/src/template.md This is a template for the startup file used with Arm Compiler for Armv7-A processors. Files for other compilers may have slight syntax variations but maintain the same structure. ```c #include "Device.h" /*---------------------------------------------------------------------------- * Exception / Interrupt Vector Table *---------------------------------------------------------------------------- */ #define SCB_VTOR_TBLOFF_Msk (0x0007FFFFUL) /*---------------------------------------------------------------------------- * Global Variables *---------------------------------------------------------------------------- */ /*---------------------------------------------------------------------------- * Local Functions *---------------------------------------------------------------------------- */ /*---------------------------------------------------------------------------- * Exported Functions *---------------------------------------------------------------------------- */ /*---------------------------------------------------------------------------- * Exception / Interrupt Handler *---------------------------------------------------------------------------- */ /*---------------------------------------------------------------------------- * Reset Handler *---------------------------------------------------------------------------- */ __asm void Reset_Handler ( void ) { extern SystemInit extern __main cpsid i ; Disable interrupts ldr r0, =_stack ; Load address of the stack mov sp, r0 ldr r0, =SystemInit blx r0 ; Call SystemInit ldr r0, =__main blx r0 ; Call __main b . ; Infinite loop } /*---------------------------------------------------------------------------- * Default Handler *---------------------------------------------------------------------------- */ __weak void Default_Handler ( void ) { while (1); } /*---------------------------------------------------------------------------- * Dummy Handlers for exceptions and interrupts *---------------------------------------------------------------------------- */ __weak void UndefinedInstruction_Handler ( void ) { Default_Handler(); } __weak void SVC_Handler ( void ) { Default_Handler(); } __weak void PrefetchAbort_Handler( void ) { Default_Handler(); } __weak void DataAbort_Handler ( void ) { Default_Handler(); } __weak void IRQ_Handler ( void ) { Default_Handler(); } __weak void FIQ_Handler ( void ) { Default_Handler(); } /*---------------------------------------------------------------------------- * Vector Table *---------------------------------------------------------------------------- */ __attribute__((section(".vectors"))) const void *VectorTable[] = { (void *) (&_estack), // 8 Int Stack Pointers Reset_Handler, // Reset Handler UndefinedInstruction_Handler, // Undefined Instruction SVC_Handler, // Supervisor Call PrefetchAbort_Handler, // Prefetch Abort DataAbort_Handler, // Data Abort 0, // Reserved IRQ_Handler, // IRQ FIQ_Handler // FIQ }; ``` -------------------------------- ### Set VIO Signal Example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Driver/src/VIO.txt Sets a signal to an output specified by a mask. Use this to map VIOs to actual hardware for displaying signals on a target board. ```c #include "cmsis_vio.h" int main (void) { vioInit(); vioSetSignal(vioLED0, vioLEDon); // ... vioSetSignal(vioLED0, vioLEDoff); } ``` -------------------------------- ### Program Entry Point Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Core/src/ref_compiler_ctrl.txt Specifies the entry function for user application or library startup after low-level initialization. ```c void Reset_Handler(void) { ``` -------------------------------- ### Configure and Enable MPU Region Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Core/src/ref_mpu8.txt Example demonstrating how to configure memory attributes and a specific memory region using the MPU. It sets up region 0 with specific attributes and enables the MPU. ```c int main() { // Set Region 0 using Attr 0 ARM_MPU_SetMemAttr(0UL, ARM_MPU_ATTR( /* Normal memory */ MPU_ATTR_NORMAL_OUTER_WT_TR_RA_WA, /* Outer Write-Back transient with read and write allocate */ MPU_ATTR_NORMAL_INNER_WT_TR_RA_WA /* Inner Write-Through transient with read and write allocate */ )); ARM_MPU_SetRegion(0UL, ARM_MPU_RBAR(0x08000000UL, ARM_MPU_SH_NON, ARM_MPU_AP_RW, ARM_MPU_AP_NP, ARM_MPU_XN), /* Non-shareable, read/write, non-privileged, execute-never */ ARM_MPU_RLAR(0x080FFFFFUL, MAIR_ATTR(0)) /* 1MB memory block using Attr 0 */ ); ARM_MPU_Enable(0); // Execute application code that is access protected by the MPU ARM_MPU_Disable(); } ``` -------------------------------- ### DACR Domain Access Permission Example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Core_A/src/ref_core_reg.txt This example demonstrates how to retrieve and manipulate domain access permissions using DACR register functions and macros. It shows clearing access permission for domain 7. ```c // clear access permission for domain 7 __set_DACR(__get_DACR() & ~DACR_D_Msk_(7)); ``` -------------------------------- ### Start RTOS Kernel Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/RTOS2/src/ref_cmsis_os2_kernel.txt Starts the RTOS kernel and begins thread switching. This function cannot be called from Interrupt Service Routines. Prior to calling, only specific kernel information and object creation functions may be called. ```c int main (void) { // System Initialization SystemCoreClockUpdate(); // ... if(osKernelGetState() == osKernelInactive) { osKernelInitialize(); } ; // ... Start Threads if (osKernelGetState() == osKernelReady) { // If kernel is ready to run... osKernelStart(); // ... start thread execution } while(1); // only reached in case of error } ``` -------------------------------- ### Joinable Threads Example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/RTOS2/src/ref_cmsis_os2_thread.txt Demonstrates the creation of joinable threads using the osThreadJoinable attribute. These threads can be synchronized using osThreadJoin upon termination. ```c __NO_RETURN void worker (void *argument) { ; // work a lot on data[] osDelay(1000U); osThreadExit(); } __NO_RETURN void thread1 (void *argument) { osThreadAttr_t worker_attr; osThreadId_t worker_ids[4]; uint8_t data[4][10]; memset(&worker_attr, 0, sizeof(worker_attr)); worker_attr.attr_bits = osThreadJoinable; worker_ids[0] = osThreadNew(worker, &data[0][0], &worker_attr); worker_ids[1] = osThreadNew(worker, &data[1][0], &worker_attr); worker_ids[2] = osThreadNew(worker, &data[2][0], &worker_attr); worker_ids[3] = osThreadNew(worker, &data[3][0], &worker_attr); osThreadJoin(worker_ids[0]); osThreadJoin(worker_ids[1]); osThreadJoin(worker_ids[2]); osThreadJoin(worker_ids[3]); osThreadExit(); } ``` -------------------------------- ### CMSIS-RTOS2 Main Function Template Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/RTOS2/src/using.md This template demonstrates the recommended order for system initialization, RTOS kernel initialization, thread creation, and starting the scheduler in the main function. ```c /*---------------------------------------------------------------------------- * CMSIS-RTOS 'main' function template *---------------------------------------------------------------------------*/ #include "RTE_Components.h" #include CMSIS_device_header #include "cmsis_os2.h" /*---------------------------------------------------------------------------- * Application main thread *---------------------------------------------------------------------------*/ void app_main (void *argument) { // ... for (;;) {} } int main (void) { // System Initialization SystemCoreClockUpdate(); // ... osKernelInitialize(); // Initialize CMSIS-RTOS osThreadNew(app_main, NULL, NULL); // Create application main thread osKernelStart(); // Start thread execution for (;;) {} } ``` -------------------------------- ### RTOS Kernel ITM Channel 31 Example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Core/src/ref_debug.txt Example demonstrating the usage of ITM Channel 31 for RTOS kernel debugging. It checks for debugger connection and ITM channel enablement before transmitting task ID and status information. ```c if ((CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA) && (ITM->TCR & ITM_TCR_ITMENA) && (ITM->TER & (1UL >> 31))) { // transmit trace data while (ITM->PORT31_U32 == 0); ITM->PORT[31].u8 = task_id; // id of next task while (ITM->PORT[31].u32 == 0); ITM->PORT[31].u32 = task_status; // status information } ``` -------------------------------- ### VIO Initialization in main Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Driver/src/VIO.txt Initializes the VIO interface. This function should be called after system core clock update. ```c #include "cmsis_vio.h" int main (void) { // System Initialization SystemCoreClockUpdate(); vioInit(); // ... } ``` -------------------------------- ### SystemInit Function Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Core_A/src/ref_system_init.txt Initializes the microcontroller system, typically configuring the oscillator (PLL) and updating the SystemCoreClock variable. This function is called from the startup file. ```APIDOC void SystemInit (void); ``` -------------------------------- ### __get_ISR Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Core_A/src/ref_core_reg.txt Function to get the Interrupt Status Register (ISR). ```APIDOC ## __get_ISR ### Description This function returns the current value of the CMSIS_ISR. ### Method __STATIC_INLINE uint32_t __get_ISR(void) ``` -------------------------------- ### Thread Flags Usage Example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/RTOS2/src/ref_cmsis_os2_thread_flags.txt This example demonstrates the basic principles of thread flags. It shows how one thread can set flags for another and how the target thread waits for specific flags. Note that thread flag management functions cannot be called from Interrupt Service Routines, except for osThreadFlagsSet. ```c #include "cmsis_os2.h" osThreadId_t tid; uint32_t flagsX; uint32_t flags; void threadX (void *argument) { osDelay(1U); for (;;) { flagsX = osThreadFlagsWait(0x0001U, osFlagsWaitAny, osWaitForever); /* B */ } } void app_main (void *argument) { tid = osThreadNew(threadX, NULL, NULL); flags = osThreadFlagsSet(tid, 0x0002U); /* A */ osDelay(2U); flags = osThreadFlagsSet(tid, 0x0005U); /* C */ osDelay(2U); for(;;); } ``` -------------------------------- ### vStreamInitialize Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Driver/src/vStream.txt Prepares the Virtual Streaming interface for operation by initializing resources and registering an event callback function. ```APIDOC ## vStreamInitialize ### Description Initializes the Virtual Streaming interface and registers an event callback function. ### Method `int32_t vStreamInitialize (vStreamEvent_t event_cb)` ### Parameters * `event_cb` (vStreamEvent_t) - Callback function to signal events. Can be NULL if not required. ### Return Value Returns `VSTREAM_OK` on success, or a negative error code on failure. ### Remarks This function must be called before any other vStream operations. The event callback function must conform to the `vStreamEvent_t` type. ``` -------------------------------- ### Priority Inheritance Mutex Example Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/RTOS2/src/ref_cmsis_os2_mutex.txt Illustrates the use of mutexes with priority inheritance. This protocol helps prevent priority inversion by temporarily boosting the priority of a lower-priority thread holding a mutex when a higher-priority thread attempts to acquire it. The example highlights how removing priority inheritance can lead to a blocked high-priority thread. ```c #include "cmsis_os2.h" osMutexId_t mutex_id; const osMutexAttr_t Thread_Mutex_attr = { "myThreadMutex", // human readable mutex name osMutexPrioInherit, // attr_bits NULL, // memory for control block 0U // size for control block }; void HighPrioThread(void *argument) { osDelay(1000U); // wait 1s until start actual work while(1) { osMutexAcquire(mutex_id, osWaitForever); // try to acquire mutex // do stuff osMutexRelease(mutex_id); } } void MidPrioThread(void *argument) { osDelay(1000U); // wait 1s until start actual work while(1) { // do non blocking stuff } } void LowPrioThread(void *argument) { while(1) { osMutexAcquire(mutex_id, osWaitForever); osDelay(5000U); // block mutex for 5s osMutexRelease(mutex_id); osDelay(5000U); // sleep for 5s } } ``` -------------------------------- ### __get_IFSR and __set_IFSR Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Core_A/src/ref_core_reg.txt Functions to get and set the Instruction Fault Status Register (IFSR). ```APIDOC ## __get_IFSR ### Description This function returns the current value of the CMSIS_IFSR. ### Method __STATIC_INLINE uint32_t __get_IFSR(void) ## __set_IFSR ### Description This function assigns the given value to the CMSIS_IFSR. ### Method __STATIC_INLINE void __set_IFSR(uint32_t ifsr) ``` -------------------------------- ### SystemInit Function Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Core/src/ref_system_init.txt Initializes the microcontroller system, typically configuring the oscillator (PLL) and updating the SystemCoreClock variable if the clock speed is variable. This function is called from the startup file. ```APIDOC ## SystemInit Function ### Description Function to initialize the system. Initializes the microcontroller system. Typically, this function configures the oscillator (PLL) that is part of the microcontroller device. For systems with a variable clock speed, it updates the variable `SystemCoreClock`. ### Signature `void SystemInit(void);` ### Called By Startup file (`startup_device`) ``` -------------------------------- ### System Configuration Template (Header File) Source: https://github.com/arm-software/cmsis_6/blob/main/CMSIS/Documentation/Doxygen/Core_A/src/template.md This header file provides prototypes for public functions defined in the system configuration C file. It allows access to device-specific functions and configuration settings. ```c /** * @brief Get system core clock frequency * * @param None * @retval System Core Clock frequency in Hz */ extern uint32_t SystemCoreClock; // System Core Clock /** * @brief Update SystemCoreClock variable * * @param None * @retval None */ extern void SystemCoreClockUpdate ( void ); /*---------------------------------------------------------------------------- * System Functions (optional) *---------------------------------------------------------------------------- */ /** * @brief Initialize the system * * @param None * @retval None */ extern void SystemInit ( void ); /*---------------------------------------------------------------------------- * End of system_Device.h *---------------------------------------------------------------------------- */ ```