From ca3236ef2f8eed158e9ebec414d26bd8f7a32e12 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 24 Oct 2017 11:28:22 +0100 Subject: [PATCH] Merge remote-tracking branch 'origin/feature/timer_triggered' into development # Conflicts: # test/codeblocks/ETL.cbp --- .../ArmTimerCallbacks.uvoptx | 0 .../ArmTimerCallbacks.uvprojx | 10 +- .../STM32F401RETx/startup_stm32f401xe.s | 0 .../Device/STM32F401RETx/system_stm32f4xx.c | 0 .../etl_profile.h | 0 .../main.cpp | 0 .../ArmTimerCallbacks.uvoptx | 322 ++++++++ .../ArmTimerCallbacks.uvprojx | 489 +++++++++++ .../STM32F401RETx/startup_stm32f401xe.s | 392 +++++++++ .../Device/STM32F401RETx/system_stm32f4xx.c | 763 ++++++++++++++++++ examples/ArmTimerCallbacks - C/ecl_user.h | 38 + examples/ArmTimerCallbacks - C/main.c | 142 ++++ src/c/ecl_timer.c | 398 +++++++++ src/c/ecl_timer.h | 118 +++ src/c/ecl_timer_list.c | 201 +++++ src/c/ecl_timer_list.h | 44 + test/codeblocks/ETL.cbp | 11 + test/ecl_user.h | 50 ++ test/test_c_timer_framework.cpp | 681 ++++++++++++++++ test/vs2017/etl.vcxproj | 10 +- test/vs2017/etl.vcxproj.filters | 24 + 21 files changed, 3686 insertions(+), 7 deletions(-) rename examples/{ArmTimerCallbacks => ArmTimerCallbacks - C++}/ArmTimerCallbacks.uvoptx (100%) rename examples/{ArmTimerCallbacks => ArmTimerCallbacks - C++}/ArmTimerCallbacks.uvprojx (98%) rename examples/{ArmTimerCallbacks => ArmTimerCallbacks - C++}/RTE/Device/STM32F401RETx/startup_stm32f401xe.s (100%) rename examples/{ArmTimerCallbacks => ArmTimerCallbacks - C++}/RTE/Device/STM32F401RETx/system_stm32f4xx.c (100%) rename examples/{ArmTimerCallbacks => ArmTimerCallbacks - C++}/etl_profile.h (100%) rename examples/{ArmTimerCallbacks => ArmTimerCallbacks - C++}/main.cpp (100%) create mode 100644 examples/ArmTimerCallbacks - C/ArmTimerCallbacks.uvoptx create mode 100644 examples/ArmTimerCallbacks - C/ArmTimerCallbacks.uvprojx create mode 100644 examples/ArmTimerCallbacks - C/RTE/Device/STM32F401RETx/startup_stm32f401xe.s create mode 100644 examples/ArmTimerCallbacks - C/RTE/Device/STM32F401RETx/system_stm32f4xx.c create mode 100644 examples/ArmTimerCallbacks - C/ecl_user.h create mode 100644 examples/ArmTimerCallbacks - C/main.c create mode 100644 src/c/ecl_timer.c create mode 100644 src/c/ecl_timer.h create mode 100644 src/c/ecl_timer_list.c create mode 100644 src/c/ecl_timer_list.h create mode 100644 test/ecl_user.h create mode 100644 test/test_c_timer_framework.cpp diff --git a/examples/ArmTimerCallbacks/ArmTimerCallbacks.uvoptx b/examples/ArmTimerCallbacks - C++/ArmTimerCallbacks.uvoptx similarity index 100% rename from examples/ArmTimerCallbacks/ArmTimerCallbacks.uvoptx rename to examples/ArmTimerCallbacks - C++/ArmTimerCallbacks.uvoptx diff --git a/examples/ArmTimerCallbacks/ArmTimerCallbacks.uvprojx b/examples/ArmTimerCallbacks - C++/ArmTimerCallbacks.uvprojx similarity index 98% rename from examples/ArmTimerCallbacks/ArmTimerCallbacks.uvprojx rename to examples/ArmTimerCallbacks - C++/ArmTimerCallbacks.uvprojx index 1d18e62d..ed494f20 100644 --- a/examples/ArmTimerCallbacks/ArmTimerCallbacks.uvprojx +++ b/examples/ArmTimerCallbacks - C++/ArmTimerCallbacks.uvprojx @@ -10,8 +10,8 @@ Target 1 0x4 ARM-ADS - 5060528::V5.06 update 5 (build 528)::ARMCC - 0 + 6070000::V6.7::.\ARMCLANG + 1 STM32F401RETx @@ -311,7 +311,7 @@ 1 - 4 + 7 0 0 1 @@ -320,7 +320,7 @@ 1 0 0 - 2 + 3 0 0 1 @@ -336,7 +336,7 @@ - ..\..\src;..\ArmTimerCallbacks + ..\..\src;..\ArmTimerCallbacks - C++ diff --git a/examples/ArmTimerCallbacks/RTE/Device/STM32F401RETx/startup_stm32f401xe.s b/examples/ArmTimerCallbacks - C++/RTE/Device/STM32F401RETx/startup_stm32f401xe.s similarity index 100% rename from examples/ArmTimerCallbacks/RTE/Device/STM32F401RETx/startup_stm32f401xe.s rename to examples/ArmTimerCallbacks - C++/RTE/Device/STM32F401RETx/startup_stm32f401xe.s diff --git a/examples/ArmTimerCallbacks/RTE/Device/STM32F401RETx/system_stm32f4xx.c b/examples/ArmTimerCallbacks - C++/RTE/Device/STM32F401RETx/system_stm32f4xx.c similarity index 100% rename from examples/ArmTimerCallbacks/RTE/Device/STM32F401RETx/system_stm32f4xx.c rename to examples/ArmTimerCallbacks - C++/RTE/Device/STM32F401RETx/system_stm32f4xx.c diff --git a/examples/ArmTimerCallbacks/etl_profile.h b/examples/ArmTimerCallbacks - C++/etl_profile.h similarity index 100% rename from examples/ArmTimerCallbacks/etl_profile.h rename to examples/ArmTimerCallbacks - C++/etl_profile.h diff --git a/examples/ArmTimerCallbacks/main.cpp b/examples/ArmTimerCallbacks - C++/main.cpp similarity index 100% rename from examples/ArmTimerCallbacks/main.cpp rename to examples/ArmTimerCallbacks - C++/main.cpp diff --git a/examples/ArmTimerCallbacks - C/ArmTimerCallbacks.uvoptx b/examples/ArmTimerCallbacks - C/ArmTimerCallbacks.uvoptx new file mode 100644 index 00000000..a96071c6 --- /dev/null +++ b/examples/ArmTimerCallbacks - C/ArmTimerCallbacks.uvoptx @@ -0,0 +1,322 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + Target 1 + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\Listings\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 18 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 5 + + + + + + + + + + + STLink\ST-LINKIII-KEIL_SWO.dll + + + + 0 + ARMRTXEVENTFLAGS + -L70 -Z18 -C0 -M0 -T1 + + + 0 + DLGTARM + (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0) + + + 0 + ARMDBGFLAGS + + + + 0 + DLGUARM + (105=-1,-1,-1,-1,0) + + + 0 + ST-LINKIII-KEIL_SWO + -U066CFF485550707267024134 -O207 -SF4000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P2 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_512.FLM -FS08000000 -FL080000 -FP0($$Device:STM32F401RETx$CMSIS\Flash\STM32F4xx_512.FLM) + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_512 -FS08000000 -FL080000 -FP0($$Device:STM32F401RETx$CMSIS\Flash\STM32F4xx_512.FLM)) + + + + + + 0 + 1 + returnCode + + + 1 + 1 + short_toggle + + + 2 + 1 + timer + + + + 0 + + + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + 1 + 0 + 2 + 10000000 + + + + + + Source Group 1 + 1 + 0 + 0 + 0 + + 1 + 1 + 1 + 0 + 0 + 0 + .\main.c + main.c + 0 + 0 + + + 1 + 2 + 1 + 0 + 0 + 0 + ..\..\src\c\ecl_timer.c + ecl_timer.c + 0 + 0 + + + 1 + 3 + 1 + 0 + 0 + 0 + ..\..\src\c\ecl_timer_list.c + ecl_timer_list.c + 0 + 0 + + + 1 + 4 + 5 + 0 + 0 + 0 + ..\..\src\c\ecl_timer.h + ecl_timer.h + 0 + 0 + + + 1 + 5 + 5 + 0 + 0 + 0 + ..\..\src\c\ecl_timer_list.h + ecl_timer_list.h + 0 + 0 + + + 1 + 6 + 5 + 0 + 0 + 0 + .\ecl_user.h + ecl_user.h + 0 + 0 + + + + + ::Board Support + 1 + 0 + 0 + 1 + + + + ::CMSIS + 0 + 0 + 0 + 1 + + + + ::Device + 1 + 0 + 0 + 1 + + +
diff --git a/examples/ArmTimerCallbacks - C/ArmTimerCallbacks.uvprojx b/examples/ArmTimerCallbacks - C/ArmTimerCallbacks.uvprojx new file mode 100644 index 00000000..28b06f23 --- /dev/null +++ b/examples/ArmTimerCallbacks - C/ArmTimerCallbacks.uvprojx @@ -0,0 +1,489 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + Target 1 + 0x4 + ARM-ADS + 5060528::V5.06 update 5 (build 528)::ARMCC + 0 + + + STM32F401RETx + STMicroelectronics + Keil.STM32F4xx_DFP.2.11.0 + http://www.keil.com/pack + IRAM(0x20000000,0x18000) IROM(0x08000000,0x80000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F4xx_512 -FS08000000 -FL080000 -FP0($$Device:STM32F401RETx$CMSIS\Flash\STM32F4xx_512.FLM)) + 0 + $$Device:STM32F401RETx$Drivers\CMSIS\Device\ST\STM32F4xx\Include\stm32f4xx.h + + + + + + + + + + $$Device:STM32F401RETx$CMSIS\SVD\STM32F401xE.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\Objects\ + ArmTimerCallbacks + 1 + 0 + 0 + 1 + 1 + .\Listings\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP -MPU + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 1 + 0x8000000 + 0x80000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x80000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 1 + 0 + 0 + 1 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 3 + 3 + 1 + 1 + 0 + 0 + 0 + + + + + ..\..\src;../../src/c;..\ArmTimerCallbacks - C + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Source Group 1 + + + main.c + 1 + .\main.c + + + ecl_timer.c + 1 + ..\..\src\c\ecl_timer.c + + + ecl_timer_list.c + 1 + ..\..\src\c\ecl_timer_list.c + + + ecl_timer.h + 5 + ..\..\src\c\ecl_timer.h + + + ecl_timer_list.h + 5 + ..\..\src\c\ecl_timer_list.h + + + ecl_user.h + 5 + .\ecl_user.h + + + + + ::Board Support + + + ::CMSIS + + + ::Device + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + RTE\Device\STM32F401RETx\startup_stm32f401xe.s + + + + + + + + RTE\Device\STM32F401RETx\system_stm32f4xx.c + + + + + + + + + +
diff --git a/examples/ArmTimerCallbacks - C/RTE/Device/STM32F401RETx/startup_stm32f401xe.s b/examples/ArmTimerCallbacks - C/RTE/Device/STM32F401RETx/startup_stm32f401xe.s new file mode 100644 index 00000000..dc82c615 --- /dev/null +++ b/examples/ArmTimerCallbacks - C/RTE/Device/STM32F401RETx/startup_stm32f401xe.s @@ -0,0 +1,392 @@ +;******************** (C) COPYRIGHT 2016 STMicroelectronics ******************** +;* File Name : startup_stm32f401xe.s +;* Author : MCD Application Team +;* Version : V2.6.0 +;* Date : 04-November-2016 +;* Description : STM32F401xe devices vector table for MDK-ARM toolchain. +;* This module performs: +;* - Set the initial SP +;* - Set the initial PC == Reset_Handler +;* - Set the vector table entries with the exceptions ISR address +;* - Branches to __main in the C library (which eventually +;* calls main()). +;* After Reset the CortexM4 processor is in Thread mode, +;* priority is Privileged, and the Stack is set to Main. +;* <<< Use Configuration Wizard in Context Menu >>> +;******************************************************************************* +; +;* Redistribution and use in source and binary forms, with or without modification, +;* are permitted provided that the following conditions are met: +;* 1. Redistributions of source code must retain the above copyright notice, +;* this list of conditions and the following disclaimer. +;* 2. Redistributions in binary form must reproduce the above copyright notice, +;* this list of conditions and the following disclaimer in the documentation +;* and/or other materials provided with the distribution. +;* 3. Neither the name of STMicroelectronics nor the names of its contributors +;* may be used to endorse or promote products derived from this software +;* without specific prior written permission. +;* +;* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +;* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +;* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +;* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +;* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +;* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +;* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +; +;******************************************************************************* + +; Amount of memory (in bytes) allocated for Stack +; Tailor this value to your application needs +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + AREA STACK, NOINIT, READWRITE, ALIGN=3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00000200 + + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + PRESERVE8 + THUMB + + +; Vector Table Mapped to Address 0 at Reset + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDG_IRQHandler ; Window WatchDog + DCD PVD_IRQHandler ; PVD through EXTI Line detection + DCD TAMP_STAMP_IRQHandler ; Tamper and TimeStamps through the EXTI line + DCD RTC_WKUP_IRQHandler ; RTC Wakeup through the EXTI line + DCD FLASH_IRQHandler ; FLASH + DCD RCC_IRQHandler ; RCC + DCD EXTI0_IRQHandler ; EXTI Line0 + DCD EXTI1_IRQHandler ; EXTI Line1 + DCD EXTI2_IRQHandler ; EXTI Line2 + DCD EXTI3_IRQHandler ; EXTI Line3 + DCD EXTI4_IRQHandler ; EXTI Line4 + DCD DMA1_Stream0_IRQHandler ; DMA1 Stream 0 + DCD DMA1_Stream1_IRQHandler ; DMA1 Stream 1 + DCD DMA1_Stream2_IRQHandler ; DMA1 Stream 2 + DCD DMA1_Stream3_IRQHandler ; DMA1 Stream 3 + DCD DMA1_Stream4_IRQHandler ; DMA1 Stream 4 + DCD DMA1_Stream5_IRQHandler ; DMA1 Stream 5 + DCD DMA1_Stream6_IRQHandler ; DMA1 Stream 6 + DCD ADC_IRQHandler ; ADC1, ADC2 and ADC3s + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD EXTI9_5_IRQHandler ; External Line[9:5]s + DCD TIM1_BRK_TIM9_IRQHandler ; TIM1 Break and TIM9 + DCD TIM1_UP_TIM10_IRQHandler ; TIM1 Update and TIM10 + DCD TIM1_TRG_COM_TIM11_IRQHandler ; TIM1 Trigger and Commutation and TIM11 + DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare + DCD TIM2_IRQHandler ; TIM2 + DCD TIM3_IRQHandler ; TIM3 + DCD TIM4_IRQHandler ; TIM4 + DCD I2C1_EV_IRQHandler ; I2C1 Event + DCD I2C1_ER_IRQHandler ; I2C1 Error + DCD I2C2_EV_IRQHandler ; I2C2 Event + DCD I2C2_ER_IRQHandler ; I2C2 Error + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD 0 ; Reserved + DCD EXTI15_10_IRQHandler ; External Line[15:10]s + DCD RTC_Alarm_IRQHandler ; RTC Alarm (A and B) through EXTI Line + DCD OTG_FS_WKUP_IRQHandler ; USB OTG FS Wakeup through EXTI line + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD DMA1_Stream7_IRQHandler ; DMA1 Stream7 + DCD 0 ; Reserved + DCD SDIO_IRQHandler ; SDIO + DCD TIM5_IRQHandler ; TIM5 + DCD SPI3_IRQHandler ; SPI3 + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD DMA2_Stream0_IRQHandler ; DMA2 Stream 0 + DCD DMA2_Stream1_IRQHandler ; DMA2 Stream 1 + DCD DMA2_Stream2_IRQHandler ; DMA2 Stream 2 + DCD DMA2_Stream3_IRQHandler ; DMA2 Stream 3 + DCD DMA2_Stream4_IRQHandler ; DMA2 Stream 4 + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD OTG_FS_IRQHandler ; USB OTG FS + DCD DMA2_Stream5_IRQHandler ; DMA2 Stream 5 + DCD DMA2_Stream6_IRQHandler ; DMA2 Stream 6 + DCD DMA2_Stream7_IRQHandler ; DMA2 Stream 7 + DCD USART6_IRQHandler ; USART6 + DCD I2C3_EV_IRQHandler ; I2C3 event + DCD I2C3_ER_IRQHandler ; I2C3 error + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD FPU_IRQHandler ; FPU + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SPI4_IRQHandler ; SPI4 + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +; Reset handler +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT SystemInit + IMPORT __main + + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +; Dummy Exception Handlers (infinite loops which can be modified) + +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP +HardFault_Handler\ + PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP +MemManage_Handler\ + PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP +BusFault_Handler\ + PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP +UsageFault_Handler\ + PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP +DebugMon_Handler\ + PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC + + EXPORT WWDG_IRQHandler [WEAK] + EXPORT PVD_IRQHandler [WEAK] + EXPORT TAMP_STAMP_IRQHandler [WEAK] + EXPORT RTC_WKUP_IRQHandler [WEAK] + EXPORT FLASH_IRQHandler [WEAK] + EXPORT RCC_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA1_Stream0_IRQHandler [WEAK] + EXPORT DMA1_Stream1_IRQHandler [WEAK] + EXPORT DMA1_Stream2_IRQHandler [WEAK] + EXPORT DMA1_Stream3_IRQHandler [WEAK] + EXPORT DMA1_Stream4_IRQHandler [WEAK] + EXPORT DMA1_Stream5_IRQHandler [WEAK] + EXPORT DMA1_Stream6_IRQHandler [WEAK] + EXPORT ADC_IRQHandler [WEAK] + EXPORT EXTI9_5_IRQHandler [WEAK] + EXPORT TIM1_BRK_TIM9_IRQHandler [WEAK] + EXPORT TIM1_UP_TIM10_IRQHandler [WEAK] + EXPORT TIM1_TRG_COM_TIM11_IRQHandler [WEAK] + EXPORT TIM1_CC_IRQHandler [WEAK] + EXPORT TIM2_IRQHandler [WEAK] + EXPORT TIM3_IRQHandler [WEAK] + EXPORT TIM4_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT I2C2_EV_IRQHandler [WEAK] + EXPORT I2C2_ER_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT EXTI15_10_IRQHandler [WEAK] + EXPORT RTC_Alarm_IRQHandler [WEAK] + EXPORT OTG_FS_WKUP_IRQHandler [WEAK] + EXPORT DMA1_Stream7_IRQHandler [WEAK] + EXPORT SDIO_IRQHandler [WEAK] + EXPORT TIM5_IRQHandler [WEAK] + EXPORT SPI3_IRQHandler [WEAK] + EXPORT DMA2_Stream0_IRQHandler [WEAK] + EXPORT DMA2_Stream1_IRQHandler [WEAK] + EXPORT DMA2_Stream2_IRQHandler [WEAK] + EXPORT DMA2_Stream3_IRQHandler [WEAK] + EXPORT DMA2_Stream4_IRQHandler [WEAK] + EXPORT OTG_FS_IRQHandler [WEAK] + EXPORT DMA2_Stream5_IRQHandler [WEAK] + EXPORT DMA2_Stream6_IRQHandler [WEAK] + EXPORT DMA2_Stream7_IRQHandler [WEAK] + EXPORT USART6_IRQHandler [WEAK] + EXPORT I2C3_EV_IRQHandler [WEAK] + EXPORT I2C3_ER_IRQHandler [WEAK] + EXPORT FPU_IRQHandler [WEAK] + EXPORT SPI4_IRQHandler [WEAK] + +WWDG_IRQHandler +PVD_IRQHandler +TAMP_STAMP_IRQHandler +RTC_WKUP_IRQHandler +FLASH_IRQHandler +RCC_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA1_Stream0_IRQHandler +DMA1_Stream1_IRQHandler +DMA1_Stream2_IRQHandler +DMA1_Stream3_IRQHandler +DMA1_Stream4_IRQHandler +DMA1_Stream5_IRQHandler +DMA1_Stream6_IRQHandler +ADC_IRQHandler +EXTI9_5_IRQHandler +TIM1_BRK_TIM9_IRQHandler +TIM1_UP_TIM10_IRQHandler +TIM1_TRG_COM_TIM11_IRQHandler +TIM1_CC_IRQHandler +TIM2_IRQHandler +TIM3_IRQHandler +TIM4_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +I2C2_EV_IRQHandler +I2C2_ER_IRQHandler +SPI1_IRQHandler +SPI2_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +EXTI15_10_IRQHandler +RTC_Alarm_IRQHandler +OTG_FS_WKUP_IRQHandler +DMA1_Stream7_IRQHandler +SDIO_IRQHandler +TIM5_IRQHandler +SPI3_IRQHandler +DMA2_Stream0_IRQHandler +DMA2_Stream1_IRQHandler +DMA2_Stream2_IRQHandler +DMA2_Stream3_IRQHandler +DMA2_Stream4_IRQHandler +OTG_FS_IRQHandler +DMA2_Stream5_IRQHandler +DMA2_Stream6_IRQHandler +DMA2_Stream7_IRQHandler +USART6_IRQHandler +I2C3_EV_IRQHandler +I2C3_ER_IRQHandler +FPU_IRQHandler +SPI4_IRQHandler + + B . + + ENDP + + ALIGN + +;******************************************************************************* +; User Stack and Heap initialization +;******************************************************************************* + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap + + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + + ALIGN + + ENDIF + + END + +;************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE***** diff --git a/examples/ArmTimerCallbacks - C/RTE/Device/STM32F401RETx/system_stm32f4xx.c b/examples/ArmTimerCallbacks - C/RTE/Device/STM32F401RETx/system_stm32f4xx.c new file mode 100644 index 00000000..bca0633d --- /dev/null +++ b/examples/ArmTimerCallbacks - C/RTE/Device/STM32F401RETx/system_stm32f4xx.c @@ -0,0 +1,763 @@ +/** + ****************************************************************************** + * @file system_stm32f4xx.c + * @author MCD Application Team + * @version V2.6.0 + * @date 04-November-2016 + * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File. + * + * This file provides two functions and one global variable to be called from + * user application: + * - SystemInit(): This function is called at startup just after reset and + * before branch to main program. This call is made inside + * the "startup_stm32f4xx.s" file. + * + * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used + * by the user application to setup the SysTick + * timer or configure other parameters. + * + * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must + * be called whenever the core clock is changed + * during program execution. + * + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f4xx_system + * @{ + */ + +/** @addtogroup STM32F4xx_System_Private_Includes + * @{ + */ + + +#include "stm32f4xx.h" + +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Defines + * @{ + */ + +/************************* Miscellaneous Configuration ************************/ +/*!< Uncomment the following line if you need to use external SRAM or SDRAM as data memory */ +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\ + || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ + || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) +/* #define DATA_IN_ExtSRAM */ +#endif /* STM32F40xxx || STM32F41xxx || STM32F42xxx || STM32F43xxx || STM32F469xx || STM32F479xx ||\ + STM32F412Zx || STM32F412Vx */ + +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ + || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) +/* #define DATA_IN_ExtSDRAM */ +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx ||\ + STM32F479xx */ + +/*!< Uncomment the following line if you need to relocate your vector Table in + Internal SRAM. */ +/* #define VECT_TAB_SRAM */ +#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. + This value must be a multiple of 0x200. */ +/******************************************************************************/ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Variables + * @{ + */ + /* This variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetHCLKFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency + Note: If you use this function to configure the system clock; then there + is no need to call the 2 first functions listed above, since SystemCoreClock + variable is updated automatically. + */ +uint32_t SystemCoreClock = 16000000; +const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; +const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_FunctionPrototypes + * @{ + */ + +#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) + static void SystemInit_ExtMemCtl(void); +#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Functions + * @{ + */ + +/** + * @brief Setup the microcontroller system + * Initialize the FPU setting, vector table location and External memory + * configuration. + * @param None + * @retval None + */ +void SystemInit(void) +{ + /* FPU settings ------------------------------------------------------------*/ + #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ + #endif + /* Reset the RCC clock configuration to the default reset state ------------*/ + /* Set HSION bit */ + RCC->CR |= (uint32_t)0x00000001; + + /* Reset CFGR register */ + RCC->CFGR = 0x00000000; + + /* Reset HSEON, CSSON and PLLON bits */ + RCC->CR &= (uint32_t)0xFEF6FFFF; + + /* Reset PLLCFGR register */ + RCC->PLLCFGR = 0x24003010; + + /* Reset HSEBYP bit */ + RCC->CR &= (uint32_t)0xFFFBFFFF; + + /* Disable all interrupts */ + RCC->CIR = 0x00000000; + +#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) + SystemInit_ExtMemCtl(); +#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */ + + /* Configure the Vector Table location add offset address ------------------*/ +#ifdef VECT_TAB_SRAM + SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ +#else + SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ +#endif +} + +/** + * @brief Update SystemCoreClock variable according to Clock Register Values. + * The SystemCoreClock variable contains the core clock (HCLK), it can + * be used by the user application to setup the SysTick timer or configure + * other parameters. + * + * @note Each time the core clock (HCLK) changes, this function must be called + * to update SystemCoreClock variable value. Otherwise, any configuration + * based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * + * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) + * or HSI_VALUE(*) multiplied/divided by the PLL factors. + * + * (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value + * 16 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file (its value + * depends on the application requirements), user has to ensure that HSE_VALUE + * is same as the real frequency of the crystal used. Otherwise, this function + * may have wrong result. + * + * - The result of this function could be not correct when using fractional + * value for HSE crystal. + * + * @param None + * @retval None + */ +void SystemCoreClockUpdate(void) +{ + uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2; + + /* Get SYSCLK source -------------------------------------------------------*/ + tmp = RCC->CFGR & RCC_CFGR_SWS; + + switch (tmp) + { + case 0x00: /* HSI used as system clock source */ + SystemCoreClock = HSI_VALUE; + break; + case 0x04: /* HSE used as system clock source */ + SystemCoreClock = HSE_VALUE; + break; + case 0x08: /* PLL used as system clock source */ + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N + SYSCLK = PLL_VCO / PLL_P + */ + pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22; + pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; + + if (pllsource != 0) + { + /* HSE used as PLL clock source */ + pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); + } + else + { + /* HSI used as PLL clock source */ + pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); + } + + pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2; + SystemCoreClock = pllvco/pllp; + break; + default: + SystemCoreClock = HSI_VALUE; + break; + } + /* Compute HCLK frequency --------------------------------------------------*/ + /* Get HCLK prescaler */ + tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; + /* HCLK frequency */ + SystemCoreClock >>= tmp; +} + +#if defined (DATA_IN_ExtSRAM) && defined (DATA_IN_ExtSDRAM) +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ + || defined(STM32F469xx) || defined(STM32F479xx) +/** + * @brief Setup the external memory controller. + * Called in startup_stm32f4xx.s before jump to main. + * This function configures the external memories (SRAM/SDRAM) + * This SRAM/SDRAM will be used as program data memory (including heap and stack). + * @param None + * @retval None + */ +void SystemInit_ExtMemCtl(void) +{ + __IO uint32_t tmp = 0x00; + + register uint32_t tmpreg = 0, timeout = 0xFFFF; + register __IO uint32_t index; + + /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface clock */ + RCC->AHB1ENR |= 0x000001F8; + + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN); + + /* Connect PDx pins to FMC Alternate function */ + GPIOD->AFR[0] = 0x00CCC0CC; + GPIOD->AFR[1] = 0xCCCCCCCC; + /* Configure PDx pins in Alternate function mode */ + GPIOD->MODER = 0xAAAA0A8A; + /* Configure PDx pins speed to 100 MHz */ + GPIOD->OSPEEDR = 0xFFFF0FCF; + /* Configure PDx pins Output type to push-pull */ + GPIOD->OTYPER = 0x00000000; + /* No pull-up, pull-down for PDx pins */ + GPIOD->PUPDR = 0x00000000; + + /* Connect PEx pins to FMC Alternate function */ + GPIOE->AFR[0] = 0xC00CC0CC; + GPIOE->AFR[1] = 0xCCCCCCCC; + /* Configure PEx pins in Alternate function mode */ + GPIOE->MODER = 0xAAAA828A; + /* Configure PEx pins speed to 100 MHz */ + GPIOE->OSPEEDR = 0xFFFFC3CF; + /* Configure PEx pins Output type to push-pull */ + GPIOE->OTYPER = 0x00000000; + /* No pull-up, pull-down for PEx pins */ + GPIOE->PUPDR = 0x00000000; + + /* Connect PFx pins to FMC Alternate function */ + GPIOF->AFR[0] = 0xCCCCCCCC; + GPIOF->AFR[1] = 0xCCCCCCCC; + /* Configure PFx pins in Alternate function mode */ + GPIOF->MODER = 0xAA800AAA; + /* Configure PFx pins speed to 50 MHz */ + GPIOF->OSPEEDR = 0xAA800AAA; + /* Configure PFx pins Output type to push-pull */ + GPIOF->OTYPER = 0x00000000; + /* No pull-up, pull-down for PFx pins */ + GPIOF->PUPDR = 0x00000000; + + /* Connect PGx pins to FMC Alternate function */ + GPIOG->AFR[0] = 0xCCCCCCCC; + GPIOG->AFR[1] = 0xCCCCCCCC; + /* Configure PGx pins in Alternate function mode */ + GPIOG->MODER = 0xAAAAAAAA; + /* Configure PGx pins speed to 50 MHz */ + GPIOG->OSPEEDR = 0xAAAAAAAA; + /* Configure PGx pins Output type to push-pull */ + GPIOG->OTYPER = 0x00000000; + /* No pull-up, pull-down for PGx pins */ + GPIOG->PUPDR = 0x00000000; + + /* Connect PHx pins to FMC Alternate function */ + GPIOH->AFR[0] = 0x00C0CC00; + GPIOH->AFR[1] = 0xCCCCCCCC; + /* Configure PHx pins in Alternate function mode */ + GPIOH->MODER = 0xAAAA08A0; + /* Configure PHx pins speed to 50 MHz */ + GPIOH->OSPEEDR = 0xAAAA08A0; + /* Configure PHx pins Output type to push-pull */ + GPIOH->OTYPER = 0x00000000; + /* No pull-up, pull-down for PHx pins */ + GPIOH->PUPDR = 0x00000000; + + /* Connect PIx pins to FMC Alternate function */ + GPIOI->AFR[0] = 0xCCCCCCCC; + GPIOI->AFR[1] = 0x00000CC0; + /* Configure PIx pins in Alternate function mode */ + GPIOI->MODER = 0x0028AAAA; + /* Configure PIx pins speed to 50 MHz */ + GPIOI->OSPEEDR = 0x0028AAAA; + /* Configure PIx pins Output type to push-pull */ + GPIOI->OTYPER = 0x00000000; + /* No pull-up, pull-down for PIx pins */ + GPIOI->PUPDR = 0x00000000; + +/*-- FMC Configuration -------------------------------------------------------*/ + /* Enable the FMC interface clock */ + RCC->AHB3ENR |= 0x00000001; + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); + + FMC_Bank5_6->SDCR[0] = 0x000019E4; + FMC_Bank5_6->SDTR[0] = 0x01115351; + + /* SDRAM initialization sequence */ + /* Clock enable command */ + FMC_Bank5_6->SDCMR = 0x00000011; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* Delay */ + for (index = 0; index<1000; index++); + + /* PALL command */ + FMC_Bank5_6->SDCMR = 0x00000012; + timeout = 0xFFFF; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* Auto refresh command */ + FMC_Bank5_6->SDCMR = 0x00000073; + timeout = 0xFFFF; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* MRD register program */ + FMC_Bank5_6->SDCMR = 0x00046014; + timeout = 0xFFFF; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* Set refresh count */ + tmpreg = FMC_Bank5_6->SDRTR; + FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1)); + + /* Disable write protection */ + tmpreg = FMC_Bank5_6->SDCR[0]; + FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF); + +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) + /* Configure and enable Bank1_SRAM2 */ + FMC_Bank1->BTCR[2] = 0x00001011; + FMC_Bank1->BTCR[3] = 0x00000201; + FMC_Bank1E->BWTR[2] = 0x0fffffff; +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ +#if defined(STM32F469xx) || defined(STM32F479xx) + /* Configure and enable Bank1_SRAM2 */ + FMC_Bank1->BTCR[2] = 0x00001091; + FMC_Bank1->BTCR[3] = 0x00110212; + FMC_Bank1E->BWTR[2] = 0x0fffffff; +#endif /* STM32F469xx || STM32F479xx */ + + (void)(tmp); +} +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */ +#elif defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) +/** + * @brief Setup the external memory controller. + * Called in startup_stm32f4xx.s before jump to main. + * This function configures the external memories (SRAM/SDRAM) + * This SRAM/SDRAM will be used as program data memory (including heap and stack). + * @param None + * @retval None + */ +void SystemInit_ExtMemCtl(void) +{ + __IO uint32_t tmp = 0x00; +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ + || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) +#if defined (DATA_IN_ExtSDRAM) + register uint32_t tmpreg = 0, timeout = 0xFFFF; + register __IO uint32_t index; + +#if defined(STM32F446xx) + /* Enable GPIOA, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG interface + clock */ + RCC->AHB1ENR |= 0x0000007D; +#else + /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface + clock */ + RCC->AHB1ENR |= 0x000001F8; +#endif /* STM32F446xx */ + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN); + +#if defined(STM32F446xx) + /* Connect PAx pins to FMC Alternate function */ + GPIOA->AFR[0] |= 0xC0000000; + GPIOA->AFR[1] |= 0x00000000; + /* Configure PDx pins in Alternate function mode */ + GPIOA->MODER |= 0x00008000; + /* Configure PDx pins speed to 50 MHz */ + GPIOA->OSPEEDR |= 0x00008000; + /* Configure PDx pins Output type to push-pull */ + GPIOA->OTYPER |= 0x00000000; + /* No pull-up, pull-down for PDx pins */ + GPIOA->PUPDR |= 0x00000000; + + /* Connect PCx pins to FMC Alternate function */ + GPIOC->AFR[0] |= 0x00CC0000; + GPIOC->AFR[1] |= 0x00000000; + /* Configure PDx pins in Alternate function mode */ + GPIOC->MODER |= 0x00000A00; + /* Configure PDx pins speed to 50 MHz */ + GPIOC->OSPEEDR |= 0x00000A00; + /* Configure PDx pins Output type to push-pull */ + GPIOC->OTYPER |= 0x00000000; + /* No pull-up, pull-down for PDx pins */ + GPIOC->PUPDR |= 0x00000000; +#endif /* STM32F446xx */ + + /* Connect PDx pins to FMC Alternate function */ + GPIOD->AFR[0] = 0x000000CC; + GPIOD->AFR[1] = 0xCC000CCC; + /* Configure PDx pins in Alternate function mode */ + GPIOD->MODER = 0xA02A000A; + /* Configure PDx pins speed to 50 MHz */ + GPIOD->OSPEEDR = 0xA02A000A; + /* Configure PDx pins Output type to push-pull */ + GPIOD->OTYPER = 0x00000000; + /* No pull-up, pull-down for PDx pins */ + GPIOD->PUPDR = 0x00000000; + + /* Connect PEx pins to FMC Alternate function */ + GPIOE->AFR[0] = 0xC00000CC; + GPIOE->AFR[1] = 0xCCCCCCCC; + /* Configure PEx pins in Alternate function mode */ + GPIOE->MODER = 0xAAAA800A; + /* Configure PEx pins speed to 50 MHz */ + GPIOE->OSPEEDR = 0xAAAA800A; + /* Configure PEx pins Output type to push-pull */ + GPIOE->OTYPER = 0x00000000; + /* No pull-up, pull-down for PEx pins */ + GPIOE->PUPDR = 0x00000000; + + /* Connect PFx pins to FMC Alternate function */ + GPIOF->AFR[0] = 0xCCCCCCCC; + GPIOF->AFR[1] = 0xCCCCCCCC; + /* Configure PFx pins in Alternate function mode */ + GPIOF->MODER = 0xAA800AAA; + /* Configure PFx pins speed to 50 MHz */ + GPIOF->OSPEEDR = 0xAA800AAA; + /* Configure PFx pins Output type to push-pull */ + GPIOF->OTYPER = 0x00000000; + /* No pull-up, pull-down for PFx pins */ + GPIOF->PUPDR = 0x00000000; + + /* Connect PGx pins to FMC Alternate function */ + GPIOG->AFR[0] = 0xCCCCCCCC; + GPIOG->AFR[1] = 0xCCCCCCCC; + /* Configure PGx pins in Alternate function mode */ + GPIOG->MODER = 0xAAAAAAAA; + /* Configure PGx pins speed to 50 MHz */ + GPIOG->OSPEEDR = 0xAAAAAAAA; + /* Configure PGx pins Output type to push-pull */ + GPIOG->OTYPER = 0x00000000; + /* No pull-up, pull-down for PGx pins */ + GPIOG->PUPDR = 0x00000000; + +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ + || defined(STM32F469xx) || defined(STM32F479xx) + /* Connect PHx pins to FMC Alternate function */ + GPIOH->AFR[0] = 0x00C0CC00; + GPIOH->AFR[1] = 0xCCCCCCCC; + /* Configure PHx pins in Alternate function mode */ + GPIOH->MODER = 0xAAAA08A0; + /* Configure PHx pins speed to 50 MHz */ + GPIOH->OSPEEDR = 0xAAAA08A0; + /* Configure PHx pins Output type to push-pull */ + GPIOH->OTYPER = 0x00000000; + /* No pull-up, pull-down for PHx pins */ + GPIOH->PUPDR = 0x00000000; + + /* Connect PIx pins to FMC Alternate function */ + GPIOI->AFR[0] = 0xCCCCCCCC; + GPIOI->AFR[1] = 0x00000CC0; + /* Configure PIx pins in Alternate function mode */ + GPIOI->MODER = 0x0028AAAA; + /* Configure PIx pins speed to 50 MHz */ + GPIOI->OSPEEDR = 0x0028AAAA; + /* Configure PIx pins Output type to push-pull */ + GPIOI->OTYPER = 0x00000000; + /* No pull-up, pull-down for PIx pins */ + GPIOI->PUPDR = 0x00000000; +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */ + +/*-- FMC Configuration -------------------------------------------------------*/ + /* Enable the FMC interface clock */ + RCC->AHB3ENR |= 0x00000001; + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); + + /* Configure and enable SDRAM bank1 */ +#if defined(STM32F446xx) + FMC_Bank5_6->SDCR[0] = 0x00001954; +#else + FMC_Bank5_6->SDCR[0] = 0x000019E4; +#endif /* STM32F446xx */ + FMC_Bank5_6->SDTR[0] = 0x01115351; + + /* SDRAM initialization sequence */ + /* Clock enable command */ + FMC_Bank5_6->SDCMR = 0x00000011; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* Delay */ + for (index = 0; index<1000; index++); + + /* PALL command */ + FMC_Bank5_6->SDCMR = 0x00000012; + timeout = 0xFFFF; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* Auto refresh command */ +#if defined(STM32F446xx) + FMC_Bank5_6->SDCMR = 0x000000F3; +#else + FMC_Bank5_6->SDCMR = 0x00000073; +#endif /* STM32F446xx */ + timeout = 0xFFFF; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* MRD register program */ +#if defined(STM32F446xx) + FMC_Bank5_6->SDCMR = 0x00044014; +#else + FMC_Bank5_6->SDCMR = 0x00046014; +#endif /* STM32F446xx */ + timeout = 0xFFFF; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* Set refresh count */ + tmpreg = FMC_Bank5_6->SDRTR; +#if defined(STM32F446xx) + FMC_Bank5_6->SDRTR = (tmpreg | (0x0000050C<<1)); +#else + FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1)); +#endif /* STM32F446xx */ + + /* Disable write protection */ + tmpreg = FMC_Bank5_6->SDCR[0]; + FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF); +#endif /* DATA_IN_ExtSDRAM */ +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */ + +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\ + || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ + || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) + +#if defined(DATA_IN_ExtSRAM) +/*-- GPIOs Configuration -----------------------------------------------------*/ + /* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */ + RCC->AHB1ENR |= 0x00000078; + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN); + + /* Connect PDx pins to FMC Alternate function */ + GPIOD->AFR[0] = 0x00CCC0CC; + GPIOD->AFR[1] = 0xCCCCCCCC; + /* Configure PDx pins in Alternate function mode */ + GPIOD->MODER = 0xAAAA0A8A; + /* Configure PDx pins speed to 100 MHz */ + GPIOD->OSPEEDR = 0xFFFF0FCF; + /* Configure PDx pins Output type to push-pull */ + GPIOD->OTYPER = 0x00000000; + /* No pull-up, pull-down for PDx pins */ + GPIOD->PUPDR = 0x00000000; + + /* Connect PEx pins to FMC Alternate function */ + GPIOE->AFR[0] = 0xC00CC0CC; + GPIOE->AFR[1] = 0xCCCCCCCC; + /* Configure PEx pins in Alternate function mode */ + GPIOE->MODER = 0xAAAA828A; + /* Configure PEx pins speed to 100 MHz */ + GPIOE->OSPEEDR = 0xFFFFC3CF; + /* Configure PEx pins Output type to push-pull */ + GPIOE->OTYPER = 0x00000000; + /* No pull-up, pull-down for PEx pins */ + GPIOE->PUPDR = 0x00000000; + + /* Connect PFx pins to FMC Alternate function */ + GPIOF->AFR[0] = 0x00CCCCCC; + GPIOF->AFR[1] = 0xCCCC0000; + /* Configure PFx pins in Alternate function mode */ + GPIOF->MODER = 0xAA000AAA; + /* Configure PFx pins speed to 100 MHz */ + GPIOF->OSPEEDR = 0xFF000FFF; + /* Configure PFx pins Output type to push-pull */ + GPIOF->OTYPER = 0x00000000; + /* No pull-up, pull-down for PFx pins */ + GPIOF->PUPDR = 0x00000000; + + /* Connect PGx pins to FMC Alternate function */ + GPIOG->AFR[0] = 0x00CCCCCC; + GPIOG->AFR[1] = 0x000000C0; + /* Configure PGx pins in Alternate function mode */ + GPIOG->MODER = 0x00085AAA; + /* Configure PGx pins speed to 100 MHz */ + GPIOG->OSPEEDR = 0x000CAFFF; + /* Configure PGx pins Output type to push-pull */ + GPIOG->OTYPER = 0x00000000; + /* No pull-up, pull-down for PGx pins */ + GPIOG->PUPDR = 0x00000000; + +/*-- FMC/FSMC Configuration --------------------------------------------------*/ + /* Enable the FMC/FSMC interface clock */ + RCC->AHB3ENR |= 0x00000001; + +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); + /* Configure and enable Bank1_SRAM2 */ + FMC_Bank1->BTCR[2] = 0x00001011; + FMC_Bank1->BTCR[3] = 0x00000201; + FMC_Bank1E->BWTR[2] = 0x0fffffff; +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ +#if defined(STM32F469xx) || defined(STM32F479xx) + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); + /* Configure and enable Bank1_SRAM2 */ + FMC_Bank1->BTCR[2] = 0x00001091; + FMC_Bank1->BTCR[3] = 0x00110212; + FMC_Bank1E->BWTR[2] = 0x0fffffff; +#endif /* STM32F469xx || STM32F479xx */ +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx)\ + || defined(STM32F412Zx) || defined(STM32F412Vx) + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FSMCEN); + /* Configure and enable Bank1_SRAM2 */ + FSMC_Bank1->BTCR[2] = 0x00001011; + FSMC_Bank1->BTCR[3] = 0x00000201; + FSMC_Bank1E->BWTR[2] = 0x0FFFFFFF; +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F412Zx || STM32F412Vx */ + +#endif /* DATA_IN_ExtSRAM */ +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx ||\ + STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx */ + (void)(tmp); +} +#endif /* DATA_IN_ExtSRAM && DATA_IN_ExtSDRAM */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/examples/ArmTimerCallbacks - C/ecl_user.h b/examples/ArmTimerCallbacks - C/ecl_user.h new file mode 100644 index 00000000..6fbb9d8e --- /dev/null +++ b/examples/ArmTimerCallbacks - C/ecl_user.h @@ -0,0 +1,38 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2017 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef __ECL_USER__ +#define __ECL_USER__ + +#include + +#define ECL_TIMER_TIMER_SEMAPHORE uint32_t +#define ECL_TIMER_DISABLE_PROCESSING(x) __sync_fetch_and_add(&x, 1) +#define ECL_TIMER_ENABLE_PROCESSING(x) __sync_fetch_and_sub(&x, 1) +#define ECL_TIMER_PROCESSING_ENABLED(x) (__sync_fetch_and_add(&x, 0) == 0) +#endif diff --git a/examples/ArmTimerCallbacks - C/main.c b/examples/ArmTimerCallbacks - C/main.c new file mode 100644 index 00000000..8b80a68c --- /dev/null +++ b/examples/ArmTimerCallbacks - C/main.c @@ -0,0 +1,142 @@ + +#include + +#include "Board_LED.h" // ::Board Support:LED +#include "Board_Buttons.h" // ::Board Support:Buttons + +#include "stm32f4xx.h" // Device header + +#include "ecl_timer.h" + +#define N_TIMERS 4 +struct ecl_timer_config timers[N_TIMERS]; + +ecl_timer_id_t short_toggle; +ecl_timer_id_t long_toggle; +ecl_timer_id_t start_timers; +ecl_timer_id_t swap_timers; + +/*---------------------------------------------------------------------------- + * SystemCoreClockConfigure: configure SystemCoreClock using HSI + (HSE is not populated on Nucleo board) + *----------------------------------------------------------------------------*/ +void SystemCoreClockConfigure(void) { + + RCC->CR |= ((uint32_t)RCC_CR_HSION); // Enable HSI + while ((RCC->CR & RCC_CR_HSIRDY) == 0); // Wait for HSI Ready + + RCC->CFGR = RCC_CFGR_SW_HSI; // HSI is system clock + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI); // Wait for HSI used as system clock + + FLASH->ACR = FLASH_ACR_PRFTEN; // Enable Prefetch Buffer + FLASH->ACR |= FLASH_ACR_ICEN; // Instruction cache enable + FLASH->ACR |= FLASH_ACR_DCEN; // Data cache enable + FLASH->ACR |= FLASH_ACR_LATENCY_5WS; // Flash 5 wait state + + RCC->CFGR |= RCC_CFGR_HPRE_DIV1; // HCLK = SYSCLK + RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; // APB1 = HCLK/4 + RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; // APB2 = HCLK/2 + + RCC->CR &= ~RCC_CR_PLLON; // Disable PLL + + // PLL configuration: VCO = HSI/M * N, Sysclk = VCO/P + RCC->PLLCFGR = ( 16ul | // PLL_M = 16 + (384ul << 6) | // PLL_N = 384 + ( 3ul << 16) | // PLL_P = 8 + (RCC_PLLCFGR_PLLSRC_HSI) | // PLL_SRC = HSI + ( 8ul << 24) ); // PLL_Q = 8 + + RCC->CR |= RCC_CR_PLLON; // Enable PLL + while((RCC->CR & RCC_CR_PLLRDY) == 0) __NOP(); // Wait till PLL is ready + + RCC->CFGR &= ~RCC_CFGR_SW; // Select PLL as system clock source + RCC->CFGR |= RCC_CFGR_SW_PLL; + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // Wait till PLL is system clock src +} + +void StartTimers() +{ + ecl_timer_start(short_toggle, ECL_TIMER_START_DELAYED); + ecl_timer_start(swap_timers, ECL_TIMER_START_DELAYED); +} + +void SwapTimers() +{ + static int state = 0; + + if (!state) + { + ecl_timer_stop(short_toggle); + ecl_timer_start(long_toggle, ECL_TIMER_START_DELAYED); + } + else + { + ecl_timer_start(short_toggle, ECL_TIMER_START_DELAYED); + ecl_timer_stop(long_toggle); + } + + state = !state; + + ecl_timer_start(swap_timers, ECL_TIMER_START_DELAYED); +} + +void LedToggle() +{ + static int state = 0; + + if (state) + { + LED_On(0); + } + else + { + LED_Off(0); + } + + state = !state; +} + +int main() +{ + SystemCoreClockConfigure(); // configure HSI as System Clock + SystemCoreClockUpdate(); + + LED_Initialize(); + Buttons_Initialize(); + + ecl_timer_init(timers, N_TIMERS); + + // The LEDs will start flashing fast after 2 seconds. + // After another 5 seconds they will start flashing slower. + short_toggle = ecl_timer_register(LedToggle, 50, ECL_TIMER_REPEATING); + long_toggle = ecl_timer_register(LedToggle, 100, ECL_TIMER_REPEATING); + start_timers = ecl_timer_register(StartTimers, 2000, ECL_TIMER_SINGLE_SHOT); + swap_timers = ecl_timer_register(SwapTimers, 1500, ECL_TIMER_SINGLE_SHOT); + + SysTick_Config(SystemCoreClock / 1000); + + ecl_timer_enable(ECL_TIMER_ENABLED); + + ecl_timer_start(start_timers, ECL_TIMER_START_DELAYED); + + while (1) + { + __NOP(); + } +} + +void SysTick_Handler() +{ + const uint32_t TICK = 1; + static uint32_t nticks = TICK; + + if (ecl_timer_tick(nticks)) + { + nticks = TICK; + } + else + { + nticks += TICK; + } +} + diff --git a/src/c/ecl_timer.c b/src/c/ecl_timer.c new file mode 100644 index 00000000..29b5b17b --- /dev/null +++ b/src/c/ecl_timer.c @@ -0,0 +1,398 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2017 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include +#include + +#include "ecl_timer.h" +#include "ecl_timer_list.h" + +//******************************************* +/// Default initialisation. +//******************************************* +void ecl_timer_data_init_default(struct ecl_timer_config* ptimer_data_) +{ + assert(ptimer_data_ != 0); + + ptimer_data_->pcallback = 0; + ptimer_data_->period = 0; + ptimer_data_->delta = ECL_TIMER_INACTIVE; + ptimer_data_->id = ECL_TIMER_NO_TIMER; + ptimer_data_->previous = ECL_TIMER_NO_TIMER; + ptimer_data_->next = ECL_TIMER_NO_TIMER; + ptimer_data_->repeating = ECL_TIMER_REPEATING; +} + +//******************************************* +/// Parameterised initialisation. +//******************************************* +void ecl_timer_data_init(struct ecl_timer_config* ptimer_data_, + ecl_timer_id_t id_, + void (*pcallback_)(), + ecl_timer_time_t period_, + ecl_timer_mode_t repeating_) +{ + assert(ptimer_data_ != 0); + assert(pcallback_ != 0); + + ptimer_data_->pcallback = pcallback_; + ptimer_data_->period = period_; + ptimer_data_->delta = ECL_TIMER_INACTIVE; + ptimer_data_->id = id_; + ptimer_data_->previous = ECL_TIMER_NO_TIMER; + ptimer_data_->next = ECL_TIMER_NO_TIMER; + ptimer_data_->repeating = repeating_; +} + +//******************************************* +/// Returns true if the timer is active. +//******************************************* +ecl_timer_result_t ecl_timer_is_active(struct ecl_timer_config* ptimer_data_) +{ + assert(ptimer_data_ != 0); + + return (ptimer_data_->delta != ECL_TIMER_INACTIVE) ? ECL_TIMER_PASS : ECL_TIMER_FAIL; +} + +//******************************************* +/// Sets the timer to the inactive state. +//******************************************* +void ecl_set_timer_inactive(struct ecl_timer_config* ptimer_data_) +{ + assert(ptimer_data_ != 0); + + ptimer_data_->delta = ECL_TIMER_INACTIVE; +} + +struct ecl_time_config +{ + struct ecl_timer_config* ptimers; + uint_least8_t max_timers; + volatile ecl_timer_enable_t enabled; + ECL_TIMER_TIMER_SEMAPHORE process_semaphore; + volatile uint_least8_t registered_timers; +}; + +static struct ecl_time_config ecl; + +void ecl_timer_init(struct ecl_timer_config* ptimers_, uint_least8_t max_timers_) +{ + assert(ptimers_ != 0); + + ecl.ptimers = ptimers_; + ecl.max_timers = max_timers_; + ecl.enabled = 0; + ecl.process_semaphore = 0; + ecl.registered_timers = 0; + + int i; + for (i = 0; i < max_timers_; ++i) + { + ecl_timer_data_init_default(&ecl.ptimers[i]); + } + + ecl_timer_list_init(ecl.ptimers); +} + +//******************************************* +/// Register a ptimer-> +//******************************************* +ecl_timer_id_t ecl_timer_register(void (*pcallback_)(), + ecl_timer_time_t period_, + ecl_timer_mode_t repeating_) +{ + assert(pcallback_ != 0); + assert(ecl.ptimers != 0); + + ecl_timer_id_t id = ECL_TIMER_NO_TIMER; + + ECL_TIMER_DISABLE_PROCESSING(ecl.process_semaphore); + + int is_space = (ecl.registered_timers < ecl.max_timers); + + if (is_space) + { + // Search for the free space. + uint_least8_t i; + for (i = 0; i < ecl.max_timers; ++i) + { + struct ecl_timer_config* ptimer = &ecl.ptimers[i]; + + if (ptimer->id == ECL_TIMER_NO_TIMER) + { + // Create in-place. + ecl_timer_data_init(ptimer, i, pcallback_, period_, repeating_); + ++ecl.registered_timers; + id = i; + break; + } + } + } + + ECL_TIMER_ENABLE_PROCESSING(ecl.process_semaphore); + + return id; +} + +//******************************************* +/// Unregister a ptimer-> +//******************************************* +ecl_timer_result_t ecl_timer_unregister(ecl_timer_id_t id_) +{ + assert(ecl.ptimers != 0); + + ecl_timer_result_t result = ECL_TIMER_FAIL; + + if (id_ != ECL_TIMER_NO_TIMER) + { + ECL_TIMER_DISABLE_PROCESSING(ecl.process_semaphore); + + struct ecl_timer_config* ptimer = &ecl.ptimers[id_]; + + if (ptimer->id != ECL_TIMER_NO_TIMER) + { + if (ecl_timer_is_active(ptimer)) + { + ecl_timer_list_remove(ptimer->id, 0); + + // Reset in-place. + ecl_timer_data_init_default(ptimer); + --ecl.registered_timers; + + result = ECL_TIMER_PASS; + } + } + + ECL_TIMER_ENABLE_PROCESSING(ecl.process_semaphore); + } + + return result; +} + +//******************************************* +/// Enable/disable the ptimer-> +//******************************************* +void ecl_timer_enable(ecl_timer_enable_t state_) +{ + assert(ecl.ptimers != 0); + assert((state_ == ECL_TIMER_ENABLED) || (state_ == ECL_TIMER_DISABLED)); + + ecl.enabled = state_; +} + +//******************************************* +/// Get the enable/disable state. +//******************************************* +ecl_timer_result_t ecl_timer_is_running() +{ + return ecl.enabled; +} + +//******************************************* +/// Clears the timer of data. +//******************************************* +void ecl_timer_clear() +{ + ECL_TIMER_DISABLE_PROCESSING(ecl.process_semaphore); + + ecl_timer_list_clear(); + + int i; + for (i = 0; i < ecl.max_timers; ++i) + { + ecl_timer_data_init_default(&ecl.ptimers[i]); + } + + ecl.registered_timers = 0; + + ECL_TIMER_ENABLE_PROCESSING(ecl.process_semaphore); +} + +//******************************************* +// Called by the timer service to indicate the +// amount of time that has elapsed since the last successful call to 'tick'. +// Returns true if the tick was processed, false if not. +//******************************************* +ecl_timer_result_t ecl_timer_tick(uint32_t count) +{ + assert(ecl.ptimers != 0); + + if (ecl.enabled) + { + if (ECL_TIMER_PROCESSING_ENABLED(ecl.process_semaphore)) + { + // We have something to do? + int has_active = !ecl_timer_list_empty(); + + if (has_active) + { + while (has_active && (count >= ecl_timer_list_front()->delta)) + { + struct ecl_timer_config* ptimer = ecl_timer_list_front(); + + count -= ptimer->delta; + + ecl_timer_list_remove(ptimer->id, 1); + + if (ptimer->repeating) + { + // Reinsert the ptimer-> + ptimer->delta = ptimer->period; + ecl_timer_list_insert(ptimer->id); + } + + if (ptimer->pcallback != 0) + { + // Call the C callback. + (ptimer->pcallback)(); + } + + has_active = !ecl_timer_list_empty(); + } + + if (has_active) + { + // Subtract any remainder from the next due timeout. + ecl_timer_list_front()->delta -= count; + } + } + + return ECL_TIMER_PASS; + } + } + + return ECL_TIMER_FAIL; +} + +//******************************************* +/// Starts a timer +//******************************************* +ecl_timer_result_t ecl_timer_start(ecl_timer_id_t id_, ecl_timer_start_t immediate_) +{ + assert(ecl.ptimers != 0); + + ECL_TIMER_DISABLE_PROCESSING(ecl.process_semaphore); + + ecl_timer_result_t result = ECL_TIMER_FAIL; + + // Valid timer id? + if (id_ != ECL_TIMER_NO_TIMER) + { + struct ecl_timer_config* ptimer = &ecl.ptimers[id_]; + + // Registered timer? + if (ptimer->id != ECL_TIMER_NO_TIMER) + { + // Has a valid period. + if (ptimer->period != ECL_TIMER_INACTIVE) + { + if (ecl_timer_is_active(ptimer)) + { + ecl_timer_list_remove(ptimer->id, 0); + } + + ptimer->delta = immediate_ ? 0 : ptimer->period; + ecl_timer_list_insert(ptimer->id); + + result = ECL_TIMER_PASS; + } + } + } + + ECL_TIMER_ENABLE_PROCESSING(ecl.process_semaphore); + + return result; +} + +//******************************************* +/// Stops a timer +//******************************************* +ecl_timer_result_t ecl_timer_stop(ecl_timer_id_t id_) +{ + assert(ecl.ptimers != 0); + + ECL_TIMER_DISABLE_PROCESSING(ecl.process_semaphore); + + ecl_timer_result_t result = ECL_TIMER_FAIL; + + // Valid timer id? + if (id_ != ECL_TIMER_NO_TIMER) + { + struct ecl_timer_config* ptimer = &ecl.ptimers[id_]; + + // Registered timer? + if (ptimer->id != ECL_TIMER_NO_TIMER) + { + if (ecl_timer_is_active(ptimer)) + { + ecl_timer_list_remove(ptimer->id, 0); + result = ECL_TIMER_PASS; + } + } + } + + ECL_TIMER_ENABLE_PROCESSING(ecl.process_semaphore); + + return result; +} + +//******************************************* +/// Sets a timer's period. +//******************************************* +ecl_timer_result_t ecl_timer_set_period(ecl_timer_id_t id_, ecl_timer_time_t period_) +{ + assert(ecl.ptimers != 0); + + if (ecl_timer_stop(id_)) + { + ecl.ptimers[id_].period = period_; + return ecl_timer_start(id_, 0); + } + + return ECL_TIMER_FAIL; +} + +//******************************************* +/// Sets a timer's mode. +//******************************************* +ecl_timer_result_t ecl_timer_set_mode(ecl_timer_id_t id_, ecl_timer_mode_t repeating_) +{ + assert(ecl.ptimers != 0); + + if (ecl_timer_stop(id_)) + { + ecl.ptimers[id_].repeating = repeating_; + return ecl_timer_start(id_, 0); + } + + return ECL_TIMER_FAIL; +} + + + + diff --git a/src/c/ecl_timer.h b/src/c/ecl_timer.h new file mode 100644 index 00000000..0d5e33e9 --- /dev/null +++ b/src/c/ecl_timer.h @@ -0,0 +1,118 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2017 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef __ETL_C_TIMER_FRAMEWORK__ +#define __ETL_C_TIMER_FRAMEWORK__ + +#include + +#include "ecl_user.h" + +// Pass/fail results. +enum +{ + ECL_TIMER_FAIL = 0, + ECL_TIMER_PASS = 1, +}; + +typedef int ecl_timer_result_t; + +// Enable states. +enum +{ + ECL_TIMER_DISABLED = ECL_TIMER_FAIL, + ECL_TIMER_ENABLED = ECL_TIMER_PASS +}; + +typedef int ecl_timer_enable_t; + +// Timer modes. +enum +{ + ECL_TIMER_SINGLE_SHOT = 0, + ECL_TIMER_REPEATING = 1 +}; + +typedef char ecl_timer_mode_t; + +// Timer start action. +enum +{ + ECL_TIMER_START_DELAYED = 0, + ECL_TIMER_START_IMMEDIATE = 1 +}; + +typedef char ecl_timer_start_t; + +// Timer identifiers. +enum +{ + ECL_TIMER_NO_TIMER = 255 +}; + +typedef uint_least8_t ecl_timer_id_t; + +// Timer times. +#define ECL_TIMER_INACTIVE 0xFFFFFFFF + +typedef uint32_t ecl_timer_time_t; + +//************************************************************************* +/// The configuration of a timer. +//************************************************************************* +struct ecl_timer_config +{ + void (*pcallback)(); + ecl_timer_time_t period; + ecl_timer_time_t delta; + ecl_timer_id_t id; + uint_least8_t previous; + uint_least8_t next; + char repeating; +}; + +//************************************************************************* +/// The API. +//************************************************************************* +void ecl_timer_data_init_default(struct ecl_timer_config* ptimer_data_); +void ecl_timer_data_init(struct ecl_timer_config* ptimer_data_, ecl_timer_id_t id_, void(*pcallback_)(), ecl_timer_time_t period_, ecl_timer_mode_t repeating_); +ecl_timer_result_t ecl_timer_is_active(struct ecl_timer_config* ptimer_data_); +void ecl_set_timer_inactive(struct ecl_timer_config* ptimer_data_); +void ecl_timer_init(struct ecl_timer_config* ptimers_, uint_least8_t max_timers_); +ecl_timer_id_t ecl_timer_register(void(*pcallback_)(), ecl_timer_time_t period_, ecl_timer_mode_t repeating_); +ecl_timer_result_t ecl_timer_unregister(ecl_timer_id_t id_); +void ecl_timer_enable(ecl_timer_enable_t state_); +ecl_timer_result_t ecl_timer_is_running(void); +void ecl_timer_clear(void); +ecl_timer_result_t ecl_timer_tick(uint32_t count); +ecl_timer_result_t ecl_timer_start(ecl_timer_id_t id_, ecl_timer_start_t immediate_); +ecl_timer_result_t ecl_timer_stop(ecl_timer_id_t id_); +ecl_timer_result_t ecl_timer_set_period(ecl_timer_id_t id_, ecl_timer_time_t period_); +ecl_timer_result_t ecl_timer_set_mode(ecl_timer_id_t id_, ecl_timer_mode_t repeating_); + +#endif diff --git a/src/c/ecl_timer_list.c b/src/c/ecl_timer_list.c new file mode 100644 index 00000000..1e728ff0 --- /dev/null +++ b/src/c/ecl_timer_list.c @@ -0,0 +1,201 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2017 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "ecl_timer.h" +#include "ecl_timer_list.h" + +//************************************************************************* +/// A specialised intrusive linked list for timer data. +//************************************************************************* + +static ecl_timer_id_t head; +static ecl_timer_id_t tail; +static ecl_timer_id_t current; + +struct ecl_timer_config* ptimers; + +void ecl_timer_list_init(struct ecl_timer_config* const ptimers_) +{ + ptimers = ptimers_; + head = ECL_TIMER_NO_TIMER; + tail = ECL_TIMER_NO_TIMER; + current = ECL_TIMER_NO_TIMER; +} + +//******************************* +struct ecl_timer_config* ecl_timer_list_front() +{ + return &ptimers[head]; +} + +//******************************* +ecl_timer_id_t ecl_timer_list_begin() +{ + current = head; + return current; +} + +//******************************* +ecl_timer_id_t ecl_timer_list_previous(ecl_timer_id_t last) +{ + current = ptimers[last].previous; + return current; +} + +//******************************* +ecl_timer_id_t ecl_timer_list_next(ecl_timer_id_t last) +{ + current = ptimers[last].next; + return current; +} + +//******************************* +int ecl_timer_list_empty() +{ + return head == ECL_TIMER_NO_TIMER; +} + +//******************************* +// Inserts the timer at the correct delta position +//******************************* +void ecl_timer_list_insert(ecl_timer_id_t id_) +{ + struct ecl_timer_config* ptimer = &ptimers[id_]; + + if (head == ECL_TIMER_NO_TIMER) + { + // No entries yet. + head = id_; + tail = id_; + ptimer->previous = ECL_TIMER_NO_TIMER; + ptimer->next = ECL_TIMER_NO_TIMER; + } + else + { + // We already have entries. + ecl_timer_id_t test_id = ecl_timer_list_begin(); + + while (test_id != ECL_TIMER_NO_TIMER) + { + struct ecl_timer_config* ptest = &ptimers[test_id]; + + // Find the correct place to insert. + if (ptimer->delta <= ptest->delta) + { + if (ptest->id == head) + { + head = ptimer->id; + } + + // Insert before ptest-> + ptimer->previous = ptest->previous; + ptest->previous = ptimer->id; + ptimer->next = ptest->id; + + // Adjust the next delta to compensate. + ptest->delta -= ptimer->delta; + + if (ptimer->previous != ECL_TIMER_NO_TIMER) + { + ptimers[ptimer->previous].next = ptimer->id; + } + break; + } + else + { + ptimer->delta -= ptest->delta; + } + + test_id = ecl_timer_list_next(test_id); + } + + // Reached the end? + if (test_id == ECL_TIMER_NO_TIMER) + { + // Tag on to the tail. + ptimers[tail].next = ptimer->id; + ptimer->previous = tail; + ptimer->next = ECL_TIMER_NO_TIMER; + tail = ptimer->id; + } + } +} + +//******************************* +void ecl_timer_list_remove(ecl_timer_id_t id_, int has_expired) +{ + struct ecl_timer_config* ptimer = &ptimers[id_]; + + if (head == id_) + { + head = ptimer->next; + } + else + { + ptimers[ptimer->previous].next = ptimer->next; + } + + if (tail == id_) + { + tail = ptimer->previous; + } + else + { + ptimers[ptimer->next].previous = ptimer->previous; + } + + if (!has_expired) + { + // Adjust the next delta. + if (ptimer->next != ECL_TIMER_NO_TIMER) + { + ptimers[ptimer->next].delta += ptimer->delta; + } + } + + ptimer->previous = ECL_TIMER_NO_TIMER; + ptimer->next = ECL_TIMER_NO_TIMER; + ptimer->delta = ECL_TIMER_INACTIVE; +} + +//******************************* +void ecl_timer_list_clear() +{ + ecl_timer_id_t id = ecl_timer_list_begin(); + + while (id != ECL_TIMER_NO_TIMER) + { + struct ecl_timer_config* ptimer = &ptimers[id]; + id = ecl_timer_list_next(id); + ptimer->next = ECL_TIMER_NO_TIMER; + } + + head = ECL_TIMER_NO_TIMER; + tail = ECL_TIMER_NO_TIMER; + current = ECL_TIMER_NO_TIMER; +} diff --git a/src/c/ecl_timer_list.h b/src/c/ecl_timer_list.h new file mode 100644 index 00000000..7662b48e --- /dev/null +++ b/src/c/ecl_timer_list.h @@ -0,0 +1,44 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2017 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef __ETL_C_TIMER_FRAMEWORK_LIST__ +#define __ETL_C_TIMER_FRAMEWORK_LIST__ + +#include "ecl_timer.h" + +void ecl_timer_list_init(struct ecl_timer_config* const ptimers_); +struct ecl_timer_config* ecl_timer_list_front(void); +ecl_timer_id_t ecl_timer_list_begin(void); +ecl_timer_id_t ecl_timer_list_previous(ecl_timer_id_t last); +ecl_timer_id_t ecl_timer_list_next(ecl_timer_id_t last); +int ecl_timer_list_empty(void); +void ecl_timer_list_insert(ecl_timer_id_t id_); +void ecl_timer_list_remove(ecl_timer_id_t id_, int has_expired); +void ecl_timer_list_clear(void); + +#endif diff --git a/test/codeblocks/ETL.cbp b/test/codeblocks/ETL.cbp index d25c0e6f..b3b13bf4 100644 --- a/test/codeblocks/ETL.cbp +++ b/test/codeblocks/ETL.cbp @@ -50,6 +50,7 @@ + @@ -58,6 +59,14 @@ + + + + + + @@ -258,6 +267,7 @@ + @@ -269,6 +279,7 @@ + diff --git a/test/ecl_user.h b/test/ecl_user.h new file mode 100644 index 00000000..637089e4 --- /dev/null +++ b/test/ecl_user.h @@ -0,0 +1,50 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2017 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef __ECL_USER__ +#define __ECL_USER__ + +#include "platform.h" + +#include + +#if defined(ETL_COMPILER_GCC) + #define ECL_TIMER_TIMER_SEMAPHORE uint32_t + #define ECL_TIMER_DISABLE_PROCESSING(x) __sync_fetch_and_add(&x, 1) + #define ECL_TIMER_ENABLE_PROCESSING(x) __sync_fetch_and_sub(&x, 1) + #define ECL_TIMER_PROCESSING_ENABLED(x) (__sync_fetch_and_add(&x, 0) == 0) +#else + #include + + #define ECL_TIMER_TIMER_SEMAPHORE uint32_t + #define ECL_TIMER_DISABLE_PROCESSING(x) InterlockedIncrement((volatile long*)&x) + #define ECL_TIMER_ENABLE_PROCESSING(x) InterlockedDecrement((volatile long*)&x) + #define ECL_TIMER_PROCESSING_ENABLED(x) (InterlockedAdd((volatile long*)&x, 0) == 0) +#endif + +#endif diff --git a/test/test_c_timer_framework.cpp b/test/test_c_timer_framework.cpp new file mode 100644 index 00000000..c96a712b --- /dev/null +++ b/test/test_c_timer_framework.cpp @@ -0,0 +1,681 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2017 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "UnitTest++.h" +#include "ExtraCheckMacros.h" + +#include "platform.h" + +extern "C" +{ + #include "ecl_timer.h" +} + +#include +#include +#include +#include + +#if defined(ETL_COMPILER_MICROSOFT) +#include +#endif + +#define REALTIME_TEST 0 + +namespace +{ + uint64_t ticks = 0; + + std::vector callback_list1; + std::vector callback_list2; + std::vector callback_list3; + + void callback1() + { + callback_list1.push_back(ticks); + } + + void callback2() + { + callback_list2.push_back(ticks); + } + + void callback3() + { + callback_list3.push_back(ticks); + } + + void callback3b() + { + callback_list3.push_back(ticks); + + ecl_timer_start(2, ECL_TIMER_START_DELAYED); + ecl_timer_start(1, ECL_TIMER_START_DELAYED); + } + + const int NTIMERS = 3; + struct ecl_timer_config timers[NTIMERS]; + + SUITE(test_ecl_timer) + { + //========================================================================= + TEST(ecl_timer_too_many_timers) + { + ecl_timer_init(timers, NTIMERS); + + ecl_timer_id_t id1 = ecl_timer_register(callback1, 37, ECL_TIMER_SINGLE_SHOT); + ecl_timer_id_t id2 = ecl_timer_register(callback2, 23, ECL_TIMER_SINGLE_SHOT); + ecl_timer_id_t id3 = ecl_timer_register(callback3, 11, ECL_TIMER_SINGLE_SHOT); + ecl_timer_id_t id4 = ecl_timer_register(callback3, 11, ECL_TIMER_SINGLE_SHOT); + + CHECK(id1 != ECL_TIMER_NO_TIMER); + CHECK(id2 != ECL_TIMER_NO_TIMER); + CHECK(id3 != ECL_TIMER_NO_TIMER); + CHECK(id4 == ECL_TIMER_NO_TIMER); + + ecl_timer_clear(); + id3 = ecl_timer_register(callback3, 11, ECL_TIMER_SINGLE_SHOT); + CHECK(id3 != ECL_TIMER_NO_TIMER); + } + + //========================================================================= + TEST(ecl_timer_one_shot) + { + ecl_timer_init(timers, NTIMERS); + + ecl_timer_id_t id1 = ecl_timer_register(callback1, 37, ECL_TIMER_SINGLE_SHOT); + ecl_timer_id_t id2 = ecl_timer_register(callback2, 23, ECL_TIMER_SINGLE_SHOT); + ecl_timer_id_t id3 = ecl_timer_register(callback3, 11, ECL_TIMER_SINGLE_SHOT); + + callback_list1.clear(); + callback_list2.clear(); + callback_list3.clear(); + + ecl_timer_enable(ECL_TIMER_ENABLED); + + ecl_timer_start(id1, ECL_TIMER_START_DELAYED); + ecl_timer_start(id2, ECL_TIMER_START_DELAYED); + ecl_timer_start(id3, ECL_TIMER_START_DELAYED); + + ecl_timer_enable(ECL_TIMER_ENABLED); + + ticks = 0; + + const uint32_t step = 1; + + while (ticks <= 100U) + { + ticks += step; + ecl_timer_tick(step); + } + + std::vector compare1 = { 37 }; + std::vector compare2 = { 23 }; + std::vector compare3 = { 11 }; + + CHECK(callback_list1.size() != 0); + CHECK(callback_list2.size() != 0); + CHECK(callback_list3.size() != 0); + + CHECK_ARRAY_EQUAL(compare1.data(), callback_list1.data(), compare1.size()); + CHECK_ARRAY_EQUAL(compare2.data(), callback_list2.data(), compare2.size()); + CHECK_ARRAY_EQUAL(compare3.data(), callback_list3.data(), compare3.size()); + } + + //========================================================================= + TEST(ecl_timer_repeating) + { + ecl_timer_init(timers, NTIMERS); + + ecl_timer_id_t id1 = ecl_timer_register(callback1, 37, ECL_TIMER_REPEATING); + ecl_timer_id_t id2 = ecl_timer_register(callback2, 23, ECL_TIMER_REPEATING); + ecl_timer_id_t id3 = ecl_timer_register(callback3, 11, ECL_TIMER_REPEATING); + + callback_list1.clear(); + callback_list2.clear(); + callback_list3.clear(); + + ecl_timer_enable(ECL_TIMER_ENABLED); + + ecl_timer_start(id1, ECL_TIMER_START_DELAYED); + ecl_timer_start(id2, ECL_TIMER_START_DELAYED); + ecl_timer_start(id3, ECL_TIMER_START_DELAYED); + + ecl_timer_enable(ECL_TIMER_ENABLED); + + ticks = 0; + + const uint32_t step = 1; + + while (ticks <= 100U) + { + ticks += step; + ecl_timer_tick(step); + } + + std::vector compare1 = { 37, 74 }; + std::vector compare2 = { 23, 46, 69, 92 }; + std::vector compare3 = { 11, 22, 33, 44, 55, 66, 77, 88, 99 }; + + CHECK(callback_list1.size() != 0); + CHECK(callback_list2.size() != 0); + CHECK(callback_list3.size() != 0); + + CHECK_ARRAY_EQUAL(compare1.data(), callback_list1.data(), compare1.size()); + CHECK_ARRAY_EQUAL(compare2.data(), callback_list2.data(), compare2.size()); + CHECK_ARRAY_EQUAL(compare3.data(), callback_list3.data(), compare3.size()); + } + + //========================================================================= + TEST(ecl_timer_repeating_bigger_step) + { + ecl_timer_init(timers, NTIMERS); + + ecl_timer_id_t id1 = ecl_timer_register(callback1, 37, ECL_TIMER_REPEATING); + ecl_timer_id_t id2 = ecl_timer_register(callback2, 23, ECL_TIMER_REPEATING); + ecl_timer_id_t id3 = ecl_timer_register(callback3, 11, ECL_TIMER_REPEATING); + + callback_list1.clear(); + callback_list2.clear(); + callback_list3.clear(); + + ecl_timer_enable(ECL_TIMER_ENABLED); + + ecl_timer_start(id1, ECL_TIMER_START_DELAYED); + ecl_timer_start(id2, ECL_TIMER_START_DELAYED); + ecl_timer_start(id3, ECL_TIMER_START_DELAYED); + + ecl_timer_enable(ECL_TIMER_ENABLED); + + ticks = 0; + + const uint32_t step = 5; + + while (ticks <= 100U) + { + ticks += step; + ecl_timer_tick(step); + } + + std::vector compare1 = { 40, 75 }; + std::vector compare2 = { 25, 50, 70, 95 }; + std::vector compare3 = { 15, 25, 35, 45, 55, 70, 80, 90, 100 }; + + CHECK(callback_list1.size() != 0); + CHECK(callback_list2.size() != 0); + CHECK(callback_list3.size() != 0); + + CHECK_ARRAY_EQUAL(compare1.data(), callback_list1.data(), compare1.size()); + CHECK_ARRAY_EQUAL(compare2.data(), callback_list2.data(), compare2.size()); + CHECK_ARRAY_EQUAL(compare3.data(), callback_list3.data(), compare3.size()); + } + + //========================================================================= + TEST(ecl_timer_repeating_stop_start) + { + ecl_timer_init(timers, NTIMERS); + + ecl_timer_id_t id1 = ecl_timer_register(callback1, 37, ECL_TIMER_REPEATING); + ecl_timer_id_t id2 = ecl_timer_register(callback2, 23, ECL_TIMER_REPEATING); + ecl_timer_id_t id3 = ecl_timer_register(callback3, 11, ECL_TIMER_REPEATING); + + callback_list1.clear(); + callback_list2.clear(); + callback_list3.clear(); + + ecl_timer_enable(ECL_TIMER_ENABLED); + + ecl_timer_start(id2, ECL_TIMER_START_DELAYED); + ecl_timer_start(id3, ECL_TIMER_START_DELAYED); + + ecl_timer_enable(ECL_TIMER_ENABLED); + + ticks = 0; + + const uint32_t step = 1; + + while (ticks <= 100U) + { + if (ticks == 40) + { + ecl_timer_start(id1, ECL_TIMER_START_DELAYED); + ecl_timer_stop(id2); + } + + if (ticks == 80) + { + ecl_timer_stop(id1); + ecl_timer_start(id2, ECL_TIMER_START_DELAYED); + } + + ticks += step; + ecl_timer_tick(step); + } + + std::vector compare1 = { 77 }; + std::vector compare2 = { 23 }; + std::vector compare3 = { 11, 22, 33, 44, 55, 66, 77, 88, 99 }; + + CHECK(callback_list1.size() != 0); + CHECK(callback_list2.size() != 0); + CHECK(callback_list3.size() != 0); + + CHECK_ARRAY_EQUAL(compare1.data(), callback_list1.data(), compare1.size()); + CHECK_ARRAY_EQUAL(compare2.data(), callback_list2.data(), compare2.size()); + CHECK_ARRAY_EQUAL(compare3.data(), callback_list3.data(), compare3.size()); + } + + //========================================================================= + TEST(ecl_timer_timer_starts_timer_small_step) + { + ecl_timer_init(timers, NTIMERS); + + ecl_timer_id_t id1 = ecl_timer_register(callback3b, 100, ECL_TIMER_SINGLE_SHOT); + ecl_timer_id_t id2 = ecl_timer_register(callback3, 10, ECL_TIMER_SINGLE_SHOT); + ecl_timer_id_t id3 = ecl_timer_register(callback3, 22, ECL_TIMER_SINGLE_SHOT); + + (void)id2; + (void)id3; + + callback_list3.clear(); + + ecl_timer_start(id1, ECL_TIMER_START_DELAYED); + + ecl_timer_enable(ECL_TIMER_ENABLED); + + ticks = 0; + + const uint32_t step = 1; + + while (ticks <= 200U) + { + ticks += step; + ecl_timer_tick(step); + } + + std::vector compare3 = { 100, 110, 122 }; + + CHECK(callback_list3.size() != 0); + + CHECK_ARRAY_EQUAL(compare3.data(), callback_list3.data(), compare3.size()); + } + + //========================================================================= + TEST(ecl_timer_timer_starts_timer_big_step) + { + ecl_timer_init(timers, NTIMERS); + + ecl_timer_id_t id1 = ecl_timer_register(callback3b, 100, ECL_TIMER_SINGLE_SHOT); + ecl_timer_id_t id2 = ecl_timer_register(callback3, 10, ECL_TIMER_SINGLE_SHOT); + ecl_timer_id_t id3 = ecl_timer_register(callback3, 22, ECL_TIMER_SINGLE_SHOT); + + (void)id2; + (void)id3; + + callback_list3.clear(); + + ecl_timer_start(id1, ECL_TIMER_START_DELAYED); + + ecl_timer_enable(ECL_TIMER_ENABLED); + + ticks = 0; + + const uint32_t step = 3; + + while (ticks <= 200U) + { + ticks += step; + ecl_timer_tick(step); + } + + std::vector compare3 = { 102, 111, 123 }; + + CHECK(callback_list3.size() != 0); + + CHECK_ARRAY_EQUAL(compare3.data(), callback_list3.data(), compare3.size()); + } + + + //========================================================================= + TEST(ecl_timer_repeating_register_unregister) + { + ecl_timer_init(timers, NTIMERS); + + ecl_timer_id_t id1; + ecl_timer_id_t id2 = ecl_timer_register(callback2, 23, ECL_TIMER_REPEATING); + ecl_timer_id_t id3 = ecl_timer_register(callback3, 11, ECL_TIMER_REPEATING); + + callback_list1.clear(); + callback_list2.clear(); + callback_list3.clear(); + + ecl_timer_start(id3, ECL_TIMER_START_DELAYED); + ecl_timer_start(id2, ECL_TIMER_START_DELAYED); + + ecl_timer_enable(ECL_TIMER_ENABLED); + + ticks = 0; + + const uint32_t step = 1; + + while (ticks <= 100U) + { + if (ticks == 40) + { + ecl_timer_unregister(id2); + + id1 = ecl_timer_register(callback1, 37, ECL_TIMER_REPEATING); + ecl_timer_start(id1, ECL_TIMER_START_DELAYED); + } + + ticks += step; + ecl_timer_tick(step); + } + + std::vector compare1 = { 77 }; + std::vector compare2 = { 23 }; + std::vector compare3 = { 11, 22, 33, 44, 55, 66, 77, 88, 99 }; + + CHECK(callback_list1.size() != 0); + CHECK(callback_list2.size() != 0); + CHECK(callback_list3.size() != 0); + + CHECK_ARRAY_EQUAL(compare1.data(), callback_list1.data(), compare1.size()); + CHECK_ARRAY_EQUAL(compare2.data(), callback_list2.data(), compare2.size()); + CHECK_ARRAY_EQUAL(compare3.data(), callback_list3.data(), compare3.size()); + } + + //========================================================================= + TEST(ecl_timer_repeating_clear) + { + ecl_timer_init(timers, NTIMERS); + + ecl_timer_id_t id1 = ecl_timer_register(callback1, 37, ECL_TIMER_REPEATING); + ecl_timer_id_t id2 = ecl_timer_register(callback2, 23, ECL_TIMER_REPEATING); + ecl_timer_id_t id3 = ecl_timer_register(callback3, 11, ECL_TIMER_REPEATING); + + callback_list1.clear(); + callback_list2.clear(); + callback_list3.clear(); + + ecl_timer_enable(ECL_TIMER_ENABLED); + + ecl_timer_start(id1, ECL_TIMER_START_DELAYED); + ecl_timer_start(id2, ECL_TIMER_START_DELAYED); + ecl_timer_start(id3, ECL_TIMER_START_DELAYED); + + ecl_timer_enable(ECL_TIMER_ENABLED); + + ticks = 0; + + const uint32_t step = 1; + + while (ticks <= 100U) + { + ticks += step; + + if (ticks == 40) + { + ecl_timer_clear(); + } + + ecl_timer_tick(step); + } + + std::vector compare1 = { 37 }; + std::vector compare2 = { 23 }; + std::vector compare3 = { 11, 22, 33, 44, 55, 66, 77, 88, 99 }; + + CHECK(callback_list1.size() != 0); + CHECK(callback_list2.size() != 0); + CHECK(callback_list3.size() != 0); + + CHECK_ARRAY_EQUAL(compare1.data(), callback_list1.data(), compare1.size()); + CHECK_ARRAY_EQUAL(compare2.data(), callback_list2.data(), compare2.size()); + CHECK_ARRAY_EQUAL(compare3.data(), callback_list3.data(), compare3.size()); + } + + //========================================================================= + TEST(ecl_timer_delayed_immediate) + { + ecl_timer_init(timers, NTIMERS); + + ecl_timer_id_t id1 = ecl_timer_register(callback1, 37, ECL_TIMER_REPEATING); + ecl_timer_id_t id2 = ecl_timer_register(callback2, 23, ECL_TIMER_REPEATING); + ecl_timer_id_t id3 = ecl_timer_register(callback3, 11, ECL_TIMER_REPEATING); + + callback_list1.clear(); + callback_list2.clear(); + callback_list3.clear(); + + ecl_timer_enable(ECL_TIMER_ENABLED); + + ticks = 5; + ecl_timer_tick(uint32_t(ticks)); + + ecl_timer_start(id1, ECL_TIMER_START_IMMEDIATE); + ecl_timer_start(id2, ECL_TIMER_START_IMMEDIATE); + ecl_timer_start(id3, ECL_TIMER_START_DELAYED); + + const uint32_t step = 1; + + while (ticks <= 100U) + { + ticks += step; + ecl_timer_tick(step); + } + + std::vector compare1 = { 6, 42, 79 }; + std::vector compare2 = { 6, 28, 51, 74, 97 }; + std::vector compare3 = { 16, 27, 38, 49, 60, 71, 82, 93 }; + + CHECK(callback_list1.size() != 0); + CHECK(callback_list2.size() != 0); + CHECK(callback_list3.size() != 0); + + CHECK_ARRAY_EQUAL(compare1.data(), callback_list1.data(), compare1.size()); + CHECK_ARRAY_EQUAL(compare2.data(), callback_list2.data(), compare2.size()); + CHECK_ARRAY_EQUAL(compare3.data(), callback_list3.data(), compare3.size()); + } + + //========================================================================= + TEST(ecl_timer_one_shot_big_step_short_delay_insert) + { + ecl_timer_init(timers, NTIMERS); + + ecl_timer_id_t id1 = ecl_timer_register(callback1, 15, ECL_TIMER_SINGLE_SHOT); + ecl_timer_id_t id2 = ecl_timer_register(callback2, 5, ECL_TIMER_REPEATING); + + callback_list1.clear(); + callback_list2.clear(); + + ecl_timer_start(id1, ECL_TIMER_START_DELAYED); + ecl_timer_start(id2, ECL_TIMER_START_DELAYED); + + ecl_timer_enable(ECL_TIMER_ENABLED); + + ticks = 0; + + const uint32_t step = 11; + + ticks += step; + ecl_timer_tick(step); + + ticks += step; + ecl_timer_tick(step); + + std::vector compare1 = { 22 }; + std::vector compare2 = { 11, 11, 22, 22 }; + + CHECK(callback_list1.size() != 0); + CHECK(callback_list2.size() != 0); + + CHECK_ARRAY_EQUAL(compare1.data(), callback_list1.data(), compare1.size()); + CHECK_ARRAY_EQUAL(compare2.data(), callback_list2.data(), compare2.size()); + } + + //========================================================================= + TEST(ecl_timer_one_shot_empty_list_huge_tick_before_insert) + { + ecl_timer_init(timers, NTIMERS); + + ecl_timer_id_t id1 = ecl_timer_register(callback1, 5, ECL_TIMER_SINGLE_SHOT); + + callback_list1.clear(); + + ecl_timer_start(id1, ECL_TIMER_START_DELAYED); + + ecl_timer_enable(ECL_TIMER_ENABLED); + + ticks = 0; + + const uint32_t step = 5; + + for (uint32_t i = 0; i < step; ++i) + { + ++ticks; + ecl_timer_tick(1); + } + + // Huge tick count. + ecl_timer_tick(UINT32_MAX - step + 1); + + ecl_timer_start(id1, ECL_TIMER_START_DELAYED); + + for (uint32_t i = 0; i < step; ++i) + { + ++ticks; + ecl_timer_tick(1); + } + std::vector compare1 = { 5, 10 }; + + CHECK(callback_list1.size() != 0); + + CHECK_ARRAY_EQUAL(compare1.data(), callback_list1.data(), compare1.size()); + } + + //========================================================================= +#if REALTIME_TEST + + #if defined(ETL_TARGET_OS_WINDOWS) // Only Windows priority is currently supported + #define RAISE_THREAD_PRIORITY SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST) + #define FIX_PROCESSOR_AFFINITY SetThreadAffinityMask(GetCurrentThread(), 1); + #else + #error No thread priority modifier defined + #endif + + void timer_event() + { + const uint32_t TICK = 1; + uint32_t tick = TICK; + ticks = 1; + + RAISE_THREAD_PRIORITY; + FIX_PROCESSOR_AFFINITY; + + while (ticks <= 1000) + { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + + if (ecl_timer_tick(tick)) + { + tick = TICK; + } + else + { + tick += TICK; + } + + ++ticks; + } + } + + TEST(ecl_timer_threads) + { + FIX_PROCESSOR_AFFINITY; + + ecl_timer_init(timers, NTIMERS); + + ecl_timer_id_t id1 = ecl_timer_register(callback1, 400, ECL_TIMER_SINGLE_SHOT); + ecl_timer_id_t id2 = ecl_timer_register(callback2, 100, ECL_TIMER_REPEATING); + ecl_timer_id_t id3 = ecl_timer_register(callback3, 10, ECL_TIMER_REPEATING); + + callback_list1.clear(); + callback_list2.clear(); + callback_list3.clear(); + + ecl_timer_start(id1, ECL_TIMER_START_DELAYED); + ecl_timer_start(id2, ECL_TIMER_START_DELAYED); + + ecl_timer_enable(ECL_TIMER_ENABLED); + + std::thread t1(timer_event); + + bool restart_1 = true; + + while (ticks <= 1000U) + { + if ((ticks > 200U) && (ticks < 500U)) + { + ecl_timer_stop(id3); + } + + if ((ticks > 600U) && (ticks < 800U)) + { + ecl_timer_start(id3, ECL_TIMER_START_DELAYED); + } + + if ((ticks > 500U) && restart_1) + { + ecl_timer_start(id1, ECL_TIMER_START_DELAYED); + restart_1 = false; + } + + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + + //Join the thread with the main thread + t1.join(); + + CHECK_EQUAL(2U, callback_list1.size()); + CHECK_EQUAL(10U, callback_list2.size()); + CHECK(callback_list3.size() < 65U); + + std::vector compare1 = { 400, 900 }; + std::vector compare2 = { 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000 }; + + CHECK(callback_list1.size() != 0); + CHECK(callback_list2.size() != 0); + CHECK(callback_list3.size() != 0); + + //CHECK_ARRAY_EQUAL(compare1.data(), callback_list1.data(), min(compare1.size(), callback_list1.size())); + //CHECK_ARRAY_EQUAL(compare2.data(), callback_list2.data(), min(compare2.size(), callback_list2.size())); + } +#endif + }; +} diff --git a/test/vs2017/etl.vcxproj b/test/vs2017/etl.vcxproj index 40bba69d..adb06e25 100644 --- a/test/vs2017/etl.vcxproj +++ b/test/vs2017/etl.vcxproj @@ -74,7 +74,7 @@ Level3 Disabled WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../src;../../test + ../../unittest-cpp/UnitTest++/;../../src;../../src/c;../../test @@ -93,7 +93,7 @@ Level3 Disabled WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../src;../../test + ../../unittest-cpp/UnitTest++/;../../src;../../src/c;../../test @@ -136,6 +136,8 @@ + + @@ -291,12 +293,15 @@ + + + @@ -344,6 +349,7 @@ + false diff --git a/test/vs2017/etl.vcxproj.filters b/test/vs2017/etl.vcxproj.filters index 294cdfd0..da20846f 100644 --- a/test/vs2017/etl.vcxproj.filters +++ b/test/vs2017/etl.vcxproj.filters @@ -52,6 +52,12 @@ {0a77d88b-f9f0-456a-be4b-c0a0ce6b437b} + + {1fdf39d9-079e-4404-a24a-6d5cb30def6a} + + + {4ac80fd1-3eca-4775-8695-eb1ea39c93f1} + @@ -552,6 +558,15 @@ ETL\Utilities\Atomic + + ECL + + + ECL + + + Source Files\ECL + @@ -917,6 +932,15 @@ Source Files + + ECL + + + ECL + + + Source Files\ECL +