#include "delay.h" #include "sys.h" ////////////////////////////////////////////////////////////////////////////////// //If you are using ucos, include the following header file. #if SYSTEM_SUPPORT_OS #include "includes.h" //ucos use #endif ////////////////////////////////////////////////////////////////////////////////// //This program is for educational purposes only, without the author's permission, may not be used for any other purpose //ALIENTEK STM32F407 Development Board //SysTick managed to delay the normal counting mode (supports ucosii) //Include delay_us,delay_ms //Hot Atom@ALIENTEK //Technical Forum:www.openedv.com //Date created: 2014/5/2 //Version: V1.3 //All rights reserved pirated reserved. //Copyright(C) Guangzhou wing electronic technology limited company 2014-2024 //All rights reserved //******************************************************************************** //Modify the description //V1.1 20140803 // 1,delay_us, add parameter equal to 0 to determine, if the parameter is equal to 0, then exit. // 2, under the modified ucosii, delay_ms function, join the OSLockNesting judgment, entered after a break, also can be used to delay. //V1.2 20150411 // Modify the way OS support to support any OS (not limited to UCOSII and UCOSIII, in theory any OS can support) // Add: delay_osrunning/delay_ostickspersec/delay_osintnesting three macro definitions // Add: delay_osschedlock/delay_osschedunlock/delay_ostimedly three-function //V1.3 20150521 // 2 bug when amend UCOSIII support: // Delay_tickspersec read: delay_ostickspersec // Delay_intnesting read: delay_osintnesting ////////////////////////////////////////////////////////////////////////////////// static u8 fac_us=0; //us delay times multiplier static u16 fac_ms=0; //ms delay times multiplier under the OS, ms representing each beat #if SYSTEM_SUPPORT_OS //If SYSTEM_SUPPORT_OS is defined, and instructions to support OS (not limited to UCOS). //When delay_us/delay_ms needs to support OS requires three macro definitions and functions associated with the OS to support //First 3 macro definition: // delay_osrunning: used to indicate whether the OS is currently running to determine if you can use the correlation function // delay_ostickspersec: used to represent the OS set the clock ticks, delay_init will be based on the parameters to initial systick // delay_osintnesting: used to represent OS interrupt nesting level, since interrupts cannot be scheduled, delay_ms uses this parameter to determine how to run //Then the 3 functions: // delay_osschedlock:Used to lock a OS task scheduling, prohibit scheduling //delay_osschedunlock:Used to unlock the OS task scheduling, reopening schedule // delay_ostimedly:For the OS delay, can cause the task scheduling. //This routine only UCOSII and UCOSIII support, other OS, please make reference to transplantation //Support UCOSII #ifdef OS_CRITICAL_METHOD //OS_CRITICAL_METHOD definitions, instructions to support UCOSII #define delay_osrunning OSRunning //OS runs mark, 0, does not run 1, run #define delay_ostickspersec OS_TICKS_PER_SEC //OS clock ticks, or scheduled per second times #define delay_osintnesting OSIntNesting //Interrupt nesting level, which interrupt nesting times #endif //Support UCOSIII #ifdef CPU_CFG_CRITICAL_METHOD //CPU_CFG_CRITICAL_METHOD definitions, instructions to support UCOSIII #define delay_osrunning OSRunning //OS runs mark, 0, does not run 1, run #define delay_ostickspersec OSCfg_TickRate_Hz //OS clock ticks, or scheduled per second times #define delay_osintnesting OSIntNestingCtr //Interrupt nesting level, which interrupt nesting times #endif //us-level delay time, close the task schedule (to prevent interrupted us delay) void delay_osschedlock(void) { #ifdef CPU_CFG_CRITICAL_METHOD //Use UCOSIII OS_ERR err; OSSchedLock(&err); //UCOSIII way, prohibit scheduling to prevent interrupted us delayed #else //Otherwise UCOSII OSSchedLock(); //UCOSII way prohibit scheduling to prevent interrupted us delayed #endif } //us-level delay time, restore task scheduling void delay_osschedunlock(void) { #ifdef CPU_CFG_CRITICAL_METHOD //Use UCOSIII OS_ERR err; OSSchedUnlock(&err); //UCOSIII way, prohibit scheduling to prevent interrupted us delayed #else //Otherwise UCOSII OSSchedUnlock(); //UCOSII way prohibit scheduling to prevent interrupted us delayed #endif } //OS is called the delay function delay //ticks:Delay number of beats void delay_ostimedly(u32 ticks) { #ifdef CPU_CFG_CRITICAL_METHOD OS_ERR err; OSTimeDly(ticks,OS_OPT_TIME_PERIODIC,&err);//UCOSIII delay adoption cycle mode #else OSTimeDly(ticks); //UCOSII delay #endif } void delay_os_ms(u32 ms) { OS_ERR err; OSTimeDlyHMSM(0, 0, 0, ms, OS_OPT_TIME_HMSM_STRICT, &err); } //systick interrupt function, used to use the OS void SysTick_Handler(void) { if(delay_osrunning==1) //OS begins to run and perform normal scheduling process { OSIntEnter(); //To enter a break OSTimeTick(); //Call the ucos clock service program OSIntExit(); //Task switching is triggered a soft interrupt } } #endif //Initialization delay function //When using ucos when this function initializes the ucos ticks //SYSTICK clock fixed to the AHB clock 1/8 //SYSCLK:System clock frequency void delay_init(u8 SYSCLK) { #if SYSTEM_SUPPORT_OS //If you need to support OS. u32 reload; #endif SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//SYSTICK using an external clock source fac_us=SYSCLK/8; //Regardless of whether or not to use OS,fac_us you need to use #if SYSTEM_SUPPORT_OS //If you need to support OS. reload=SYSCLK/8; //Count number of times per second unit k reload*=1000000/delay_ostickspersec; //According to the delay_ostickspersec set overrun time //Reload is a 24-bit registers, and the maximum value: 16777216, 72M, about 1.86s fac_ms=1000/delay_ostickspersec; //Representing OS can delay the minimum unit SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;//Enable interrupted SYSTICK SysTick->LOAD=reload; //Interrupted once every 1/OS_TICKS_PER_SEC seconds SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //Enable the SYSTICK #else fac_ms=(u16)fac_us*1000; //Under non-OS, representing each of the MS needs systick clock #endif } #if SYSTEM_SUPPORT_OS //If you need to support OS. //Delay nus //nus:Number of us to delay. //nus:0~204522252(Maximum 2^32/fac_us@fac_us=21) void delay_us(u32 nus) { u32 ticks; u32 told,tnow,tcnt=0; u32 reload=SysTick->LOAD; //LOAD value ticks=nus*fac_us; //Number of beats you want delay_osschedlock(); //Stop OS scheduling to prevent interrupted us delayed told=SysTick->VAL; //When entering the counter value while(1) { tnow=SysTick->VAL; if(tnow!=told) { if(tnow=ticks)break; //Time greater than or equal to the delay time, then exit. } }; delay_osschedunlock(); //Restore OS scheduling } //Delay nms //nms:Number of ms to delay //nms:0~65535 void delay_ms(u16 nms) { if (delay_osrunning && (delay_osintnesting == 0)) //If the OS is already running, and is not interrupted (broken not scheduling) { if (nms >= fac_ms) //Delay time is greater than the minimum OS time cycle { delay_ostimedly(nms/fac_ms); //OS extended } nms %= fac_ms; //OS has been unable to provide such a small time delay, using ordinary delay } delay_us((u32)(nms * 1000)); //Average delay } #else //When no ucos //Delay nus //nus as a number of us to delay. //Note: the value of the nus, not greater than 798915us (max 2^24/fac_us@fac_us=21) void delay_us(u32 nus) { u32 temp; SysTick->LOAD=nus*fac_us; //Time to load SysTick->VAL=0x00; //Clear counters SysTick->CTRL=0x01 ; //Start the countdown do { temp=SysTick->CTRL; } while ((temp & 0x01) && !(temp & (1 << 16))); //Waiting for the time to arrive SysTick->CTRL=0x00; //Closed counters SysTick->VAL =0X00; //Clear counters } //Delay nms //Note range of nms //SysTick->LOAD is a 24-bit registers, so the delay as follows: //nms < 0xffffff * 8 * 1000/SYSCLK = //SYSCLK units are Hz,nms for ms //Under the 168M, nms<=798ms void delay_xms(u16 nms) { u32 temp; SysTick->LOAD=(u32)nms*fac_ms; //Load time (SysTick->LOAD 24bit) SysTick->VAL =0x00; //Clear counters SysTick->CTRL=0x01 ; //Start the countdown do { temp=SysTick->CTRL; }while((temp&0x01)&&!(temp&(1<<16))); //Waiting for the time to arrive SysTick->CTRL=0x00; //Closed counters SysTick->VAL =0X00; //Clear counters } //Delay nms //nms:0~65535 void delay_ms(u16 nms) { u8 repeat=nms/540; //540 here, some customers may overclock is taken into account, //For example when overclocked to 248M, delay_xms maximum can only delay 541ms u16 remain=nms%540; while(repeat) { delay_xms(540); repeat--; } if(remain)delay_xms(remain); } #endif