当前位置:网站首页>Pandora IOT development board learning (HAL Library) - Experiment 7 window watchdog experiment (learning notes)
Pandora IOT development board learning (HAL Library) - Experiment 7 window watchdog experiment (learning notes)
2022-07-05 13:00:00 【Xiaohui_ Super】
This code refers to the punctual atomic routine
List of articles
The reason why it is called window is that its dog feeding time is a range with upper and lower limits ( window ), You can set the relevant registers , Set its upper limit time ( The lower limit is fixed ). You can't feed the dog too early or too late .
Experimental function
main.c Only peripheral initialization code , The dog feeding code is placed in the watchdog interrupt . The window watchdog interrupts and barks “ Wake up ahead interrupt ”, When the down counter is equal to the lower limit of the window (0x40) when , Trigger a “ Wake up ahead interrupt (EWI).
If not in interruption “ feed a dog ”,LED_R Will keep flashing , It shows that the MCU is always reset .
Routine source code :(main.c)
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "wwdg.h"
/********************************************************************************* ___ _ _____ _____ _ _ _____ _____ _ __ / _ \ | | |_ _|| ___|| \ | ||_ _|| ___|| | / / / /_\ \| | | | | |__ | \| | | | | |__ | |/ / | _ || | | | | __| | . ` | | | | __| | \ | | | || |_____| |_ | |___ | |\ | | | | |___ | |\ \ \_| |_/\_____/\___/ \____/ \_| \_/ \_/ \____/ \_| \_/ * ****************************************************************************** * The punctual atoms Pandora STM32L475 IoT Development board experiment 7 * Window watchdog experiment HAL Library version * Technical support :www.openedv.com * Taobao shop :http://openedv.taobao.com * Focus on wechat public platform wechat :" The punctual atoms ", Free access STM32 Information . * Guangzhou Xingyi Electronic Technology Co., Ltd * author : The punctual atoms @ALIENTEK * ******************************************************************************/
int main(void)
{
HAL_Init();
SystemClock_Config(); // Initialize the system clock to 80M
delay_init(80); // Initialization delay function 80M The system clock
uart_init(115200); // Initialize serial port , The baud rate is 115200
LED_Init(); // initialization LED
LED_R(0);
delay_ms(300); // Time delay 300ms Then initialize the watchdog ,LED_R The change of " so "
WWDG_Init(0X7F, 0X5F, WWDG_PRESCALER_8); // The counter value is 7F, The window register is 5F, The frequency division number is 8
while(1)
{
LED_R(1); // Extinguish LED_R The lamp
}
}
Code analysis
HAL_Init()
HAL_Init()
The definition is as follows :( See notes for specific functions )
HAL_StatusTypeDef HAL_Init(void)
{
HAL_StatusTypeDef status = HAL_OK;
/* To configure Flash Prefetch , Instruction cache , Data caching */
/* Default configuration is : Pre access is closed Instruction cache and data cache are enabled */
#if (INSTRUCTION_CACHE_ENABLE == 0) // Flash Enable pre access configuration , Can accelerate CPU Execution of code
__HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
#endif /* INSTRUCTION_CACHE_ENABLE */
#if (DATA_CACHE_ENABLE == 0)
__HAL_FLASH_DATA_CACHE_DISABLE();
#endif /* DATA_CACHE_ENABLE */
#if (PREFETCH_ENABLE != 0)
__HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#endif /* PREFETCH_ENABLE */
/* Set Interrupt Group Priority */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2); // To configure NVIC Priority groups
/* Use SysTick as time base source and configure 1ms tick (default clock after Reset is MSI) */
if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) // Initialize tick timer , The clock beat is set to 1ms
{
status = HAL_ERROR;
}
else
{
/* Init the low level hardware */
HAL_MspInit(); // Low speed peripheral initialization , such as GPIO、 Interrupt, etc ( Use STM32CubeMx Low speed peripherals are initialized when generating code
// The code is in this kind of function , In other cases, this function can be ignored
}
/* Return function status */
return status;
}
HAL_InitTick()
Tick timer clock beat initialization function
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
HAL_StatusTypeDef status = HAL_OK;
/*Configure the SysTick to have interrupt in 1ms time basis*/
if (HAL_SYSTICK_Config(SystemCoreClock/1000UL) != 0U) // The system clock /1000, The interruption period is 1ms
{
status = HAL_ERROR;
}
else
{
/*Configure the SysTick IRQ priority */
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0); // Set the interrupt priority of the tick timer to the highest
}
/* Return function status */
return status;
}
SystemClock_Config()
SystemClock_Config()
The function is defined as follows :( See notes for specific functions , For reference only )
void SystemClock_Config(void)
{
HAL_StatusTypeDef ret = HAL_OK;
RCC_OscInitTypeDef RCC_OscInitStruct; // Define oscillator initialization structure variables
RCC_ClkInitTypeDef RCC_ClkInitStruct; // Define clock initialization structure variables
__HAL_RCC_PWR_CLK_ENABLE(); // Enable power control clock
/*Initializes the CPU, AHB and APB busses clocks*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; // take HSE( External high-speed clock ) As a clock source
RCC_OscInitStruct.HSEState = RCC_HSE_ON; // Turn on HSE
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // Turn on PLL( PLL )
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; // take HSE As PLL The clock source of
RCC_OscInitStruct.PLL.PLLM = 1; // PLL-VCO Input clock frequency division coefficient ,1 Express 2 frequency division (8 / 2 = 4M, The external crystal oscillator frequency of the development board is 8MHz)
RCC_OscInitStruct.PLL.PLLN = 20; // PLL-VCO Output clock frequency multiplication coefficient ,4 * 20 = 80M, That is, the output clock frequency is 80MHz
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7; // SAI Frequency division coefficient of clock
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; // SDMMC1, RNG and USB Clock frequency division coefficient
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; // Frequency division coefficient of the main system clock
ret = HAL_RCC_OscConfig(&RCC_OscInitStruct); // Initialize clock configuration
if(ret != HAL_OK) while(1);
/*Initializes the CPU, AHB and APB busses clocks*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; // Configure all clocks at the same time
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // take PLL As the clock source of the system
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB Regardless of the frequency
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; // APB1 Regardless of the frequency
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // APB2 Regardless of the frequency
ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4); // Configure the initial structure variable of the clock ,
// Use Flash Delay 4, Wait state ( Delay ) The quantity of should be according to CPU The clock (HCLK) Frequency and internal voltage range , How to
// Please refer to the chip manual
if(ret != HAL_OK) while(1);
/*Configure the main internal regulator output voltage*/
ret = HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); // Internal register output voltage configuration
// Here is HAL_PWREx_ControlVoltageScaling() Part of the function description :
//PWR_REGULATOR_VOLTAGE_SCALE1 Regulator voltage output range 1 mode, typical output voltage
// at 1.2 V, system frequency up to 80 MHz.
if(ret != HAL_OK) while(1);
}
delay_init()
The tick timer is already HAL_Init()
Initialization in , The following function is actually for fac_us
Given a value ( At present, the operating system is not involved , Other code will not be studied for the time being ).
static u32 fac_us = 0; //us Delay multiplier
/** * @brief Initialization delay function ,SYSTICK The clock is fixed to AHB The clock * * @param SYSCLK System clock frequency * * @return void */
void delay_init(u8 SYSCLK)
{
#if SYSTEM_SUPPORT_OS // If support is needed OS.
u32 reload;
#endif
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);//SysTick The frequency is HCLK
fac_us = SYSCLK; // Whether used or not OS,fac_us You need to use
#if SYSTEM_SUPPORT_OS // If support is needed OS.
reload = SYSCLK; // The number of counts per second Unit is K
reload *= 1000000 / delay_ostickspersec; // according to delay_ostickspersec Set the overflow time
//reload by 24 Bit register , Maximum :16777216, stay 80M Next , about 209.7ms about
fac_ms = 1000 / delay_ostickspersec; // representative OS The minimum unit that can delay
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; // Turn on SYSTICK interrupt
SysTick->LOAD = reload; // Every time 1/OS_TICKS_PER_SEC Second break once
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // Turn on SYSTICK
#else
#endif
}
LED_Init()
/** * @brief LED IO Initialization function * * @param void * * @return void */
void LED_Init(void)
{
/* LED-B PE9 LED-G PE8 LED-R PE7 */
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOE_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9, GPIO_PIN_SET);
}
LED Operation function
LED The control function of is a macro function , We used HAL_GPIO_WritePin()
and HAL_GPIO_TogglePin()
Two library functions .
//RGB Interface definition
#define LED_R(n) (n?HAL_GPIO_WritePin(GPIOE,GPIO_PIN_7,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOE,GPIO_PIN_7,GPIO_PIN_RESET))
#define LED_R_TogglePin HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_7) //LED_R Level flip
#define LED_G(n) (n?HAL_GPIO_WritePin(GPIOE,GPIO_PIN_8,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOE,GPIO_PIN_8,GPIO_PIN_RESET))
#define LED_G_TogglePin HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_8) //LED_G Level flip
#define LED_B(n) (n?HAL_GPIO_WritePin(GPIOE,GPIO_PIN_9,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOE,GPIO_PIN_9,GPIO_PIN_RESET))
#define LED_B_TogglePin HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_9) //LED_B Level flip
delay_ms()
delay_ms()
What runs in the is delay_us()
, delay_us()
Delay by ticking timer . above delay_init()
Have already put fac_us Set up in order to 80, Tick timer counts 80 Time required 10-6 second ( The system clock is 80MHz), namely 1us.
/** * @brief Delay milliseconds (ms) function * * @param nms How many milliseconds does it take * * @return void */
void delay_ms(u16 nms)
{
u32 i;
for(i = 0; i < nms; i++) delay_us(1000);
}
/** * @brief Delay microseconds (us) function * * @remark nus:0~190887435( The maximum value is 2^32/[email protected]_us=22.5) * * @param nus How many microseconds do you need to delay * * @return void */
void delay_us(u32 nus)
{
u32 ticks;
u32 told, tnow, tcnt = 0;
u32 reload = SysTick->LOAD; //LOAD Value
ticks = nus * fac_us; // The number of beats needed
told = SysTick->VAL; // Counter value at the time of first entry
while(1)
{
tnow = SysTick->VAL;
if(tnow != told)
{
if(tnow < told)tcnt += told - tnow; // Notice here SYSTICK It's a decreasing counter .
else tcnt += reload - tnow + told;
told = tnow;
if(tcnt >= ticks)break; // For more than / Equal to the time to delay , The exit .
}
}
}
WWDG_Init()
Window watchdog initialization function ,main() Function , The parameters of this function are : Counter value 0X7F( The count value should be greater than the window value , It's a 7bit data ), Window value 0x5F( The acceptable range of window value is 0X40~0X7F), Division coefficient WWDG_PRESCALER_8( The corresponding value is 3). The window here refers to the upper window , The lower window is fixed as 0X40.
According to the time calculation formula of the window watchdog ( See the picture below ), Combined with the above parameters , It can be calculated that the watchdog timeout of this experiment is 4096*23*(63+1)]/48000=43.69ms
- PCLK yes APB1 The clock frequency of (48MHz), In the formula is time , And need to be converted to ms, So the corresponding value is 1/48000,
- WDGTB Is the frequency division coefficient (0~3),
- T[5:0] Is the low of the counter 6 position ,
There is one caveat here , The reason for taking the low of the counter 6 position , Because 0X7F-0X40=0x3F(111111), namely “ Count value - Window lower limit ” The maximum time difference is 0X3F, and 0X40~0X7F Of the 7 Bit is always 1, So take the low directly 6 position , Namely “ Count value - Window lower limit ” Time difference .
WWDG_Handler.Init.EWIMode = WWDG_EWI_DISABLE;
I don't understand this industry for the time being , close EWI Pattern , The early wake-up interrupt will still trigger .
/** * @brief Initialize the window watchdog * * @param tr T[6:0], Counter value * @param wr W[6:0], Window value * @param fprer Division coefficient (WDGTB), Only the lowest 2 Bit effective * * @return void */
void WWDG_Init(u8 tr, u8 wr, u32 fprer)
{
WWDG_Handler.Instance = WWDG;
WWDG_Handler.Init.Prescaler = fprer; // Set the frequency division coefficient
WWDG_Handler.Init.Window = wr; // Set window values
WWDG_Handler.Init.Counter = tr; // Set counter value
WWDG_Handler.Init.EWIMode = WWDG_EWI_DISABLE;
HAL_WWDG_Init(&WWDG_Handler); // initialization WWDG
__HAL_WWDG_ENABLE_IT(&WWDG_Handler, WWDG_IT_EWI); // Turn on wake-up interrupt
}
The following function is the bottom driver initialization function of the window watchdog ,HAL The library will automatically call this function .
/** * @brief WWDG Bottom drive , Clock configuration , Interrupt configuration * This function will be HAL_WWDG_Init() call * * @param hwwdg Window watchdog handle * * @return void */
void HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg)
{
__HAL_RCC_WWDG_CLK_ENABLE(); // Enable the window watchdog clock
HAL_NVIC_SetPriority(WWDG_IRQn, 2, 3); // preemption 2, The sub priority is 3
HAL_NVIC_EnableIRQ(WWDG_IRQn); // Enable window watchdog interrupt
}
Interrupt service function
Call... In the underlying interrupt service function HAL Interrupt service function of Library .
/** * @brief Window watchdog interrupt service function * * @param void * * @return void */
void WWDG_IRQHandler(void)
{
HAL_WWDG_IRQHandler(&WWDG_Handler);// call WWDG Common interrupt handling function
}
HAL_WWDG_IRQHandler()
Some interrupt callback functions will be run in , Among them is HAL_WWDG_EarlyWakeupCallback()
Wake up interrupt callback function in advance , In this function , Mainly completed the operation of feeding dogs .
When the count is equal to 0X40 ( Window lower limit ) when , The system will trigger the early wake-up interrupt .
/** * @brief Interrupt service function processing * This function will be HAL_WWDG_IRQHandler() call * * @param hwwdg Window watchdog handle * * @return void */
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef* hwwdg)
{
HAL_WWDG_Refresh(&WWDG_Handler);// Update window watchdog value
LED_B_TogglePin;
}
The dog feeding operation is actually to refill the count of the window watchdog .
/** * @brief Refresh the WWDG. * @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains * the configuration information for the specified WWDG module. * @retval HAL status */
HAL_StatusTypeDef HAL_WWDG_Refresh(WWDG_HandleTypeDef *hwwdg)
{
/* Write to WWDG CR the WWDG Counter value to refresh with */
WRITE_REG(hwwdg->Instance->CR, (hwwdg->Init.Counter));
/* Return function status */
return HAL_OK;
}
边栏推荐
- 太方便了,钉钉上就可完成代码发布审批啦!
- Wechat enterprise payment to change access, open quickly
- NFT: how to make money with unique assets?
- 155. 最小栈
- Time conversion error
- Compilation principle reading notes (1/12)
- Transactions from December 29, 2021 to January 4, 2022
- Principle and performance analysis of lepton lossless compression
- Overflow toolbar control in SAP ui5 view
- A possible investment strategy and a possible fuzzy fast stock valuation method
猜你喜欢
Transactions from January 6 to October 2022
【云原生】Nacos-TaskManager 任务管理的使用
RHCSA3
Discussion on error messages and API versions of SAP ui5 getsaplogonlanguage is not a function
简单上手的页面请求和解析案例
DNS的原理介绍
使用 jMeter 对 SAP Spartacus 进行并发性能测试
Taobao short videos are automatically released in batches without manual RPA open source
Annotation problem and hidden Markov model
Comprehensive upgrade of Taobao short video photosynthetic platform
随机推荐
SAP UI5 ObjectPageLayout 控件使用方法分享
RHCSA7
Language model
Comprehensive upgrade of Taobao short video photosynthetic platform
SAP UI5 DynamicPage 控件介绍
跨平台(32bit和64bit)的 printf 格式符 %lld 输出64位的解决方式
Hiengine: comparable to the local cloud native memory database engine
MySQL splits strings for conditional queries
leetcode:221. 最大正方形【dp状态转移的精髓】
RHCSA4
Simply take stock reading notes (2/8)
HiEngine:可媲美本地的云原生内存数据库引擎
Kotlin function
Get to know linkerd project for the first time
《信息系统项目管理师》备考笔记---信息化知识
I'm doing open source in Didi
10 minute fitness method reading notes (5/5)
Why is your next computer a computer? Explore different remote operations
太方便了,钉钉上就可完成代码发布审批啦!
How can non-technical departments participate in Devops?