130 lines
3.2 KiB
C
130 lines
3.2 KiB
C
/*
|
||
* @Author: jiejie
|
||
* @Github: https://github.com/jiejieTop
|
||
* @Date: 2020-02-15 20:51:38
|
||
* @LastEditTime : 2020-02-16 00:06:40
|
||
* @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
|
||
*/
|
||
|
||
#include "bsp_dwt.h"
|
||
#include "stm32f1xx_hal.h"
|
||
/*
|
||
**********************************************************************
|
||
* 时间戳相关寄存器定义
|
||
**********************************************************************
|
||
*/
|
||
/*
|
||
在Cortex-M里面有一个外设叫DWT(Data Watchpoint and Trace),
|
||
该外设有一个32位的寄存器叫CYCCNT,它是一个向上的计数器,
|
||
记录的是内核时钟运行的个数,最长能记录的时间为:
|
||
60s=2的32次方/72000000
|
||
(假设内核频率为72M,内核跳一次的时间大概为1/72M=13.8ns)
|
||
当CYCCNT溢出之后,会清0重新开始向上计数。
|
||
使能CYCCNT计数的操作步骤:
|
||
1、先使能DWT外设,这个由另外内核调试寄存器DEMCR的位24控制,写1使能
|
||
2、使能CYCCNT寄存器之前,先清0
|
||
3、使能CYCCNT寄存器,这个由DWT_CTRL(代码上宏定义为DWT_CR)的位0控制,写1使能
|
||
*/
|
||
|
||
#if USE_DWT_DELAY
|
||
|
||
|
||
#define DWT_CR *(__IO uint32_t *)0xE0001000
|
||
#define DWT_CYCCNT *(__IO uint32_t *)0xE0001004
|
||
#define DEM_CR *(__IO uint32_t *)0xE000EDFC
|
||
|
||
|
||
#define DEM_CR_TRCENA (1 << 24)
|
||
#define DWT_CR_CYCCNTENA (1 << 0)
|
||
|
||
|
||
/**
|
||
* @brief 初始化时间戳
|
||
* @param 无
|
||
* @retval 无
|
||
* @note 使用延时函数前,必须调用本函数
|
||
*/
|
||
void dwt_init(void)
|
||
{
|
||
/* 使能DWT外设 */
|
||
DEM_CR |= (uint32_t)DEM_CR_TRCENA;
|
||
|
||
/* DWT CYCCNT寄存器计数清0 */
|
||
DWT_CYCCNT = (uint32_t)0u;
|
||
|
||
/* 使能Cortex-M DWT CYCCNT寄存器 */
|
||
DWT_CR |= (uint32_t)DWT_CR_CYCCNTENA;
|
||
}
|
||
|
||
/**
|
||
* @brief 读取当前时间戳
|
||
* @param 无
|
||
* @retval 当前时间戳,即DWT_CYCCNT寄存器的值
|
||
*/
|
||
uint32_t dwt_read(void)
|
||
{
|
||
return ((uint32_t)DWT_CYCCNT);
|
||
}
|
||
|
||
///**
|
||
// * @brief 读取当前时间戳
|
||
// * @param 无
|
||
// * @retval 当前时间戳,即DWT_CYCCNT寄存器的值
|
||
// * 此处给HAL库替换HAL_GetTick函数,用于os
|
||
// */
|
||
//uint32_t HAL_GetTick(void)
|
||
//{
|
||
// //先除后乘,防止溢出
|
||
// return ((uint32_t)DWT_CYCCNT / system_clk_freq * 1000);
|
||
//}
|
||
|
||
/**
|
||
* @brief 采用CPU的内部计数实现精确延时,32位计数器
|
||
* @param us : 延迟长度,单位1 us
|
||
* @retval 无
|
||
* @note 使用本函数前必须先调用dwt_init函数使能计数器,
|
||
或使能宏CPU_TS_INIT_IN_DELAY_FUNCTION
|
||
最大延时值为8秒,即8*1000*1000
|
||
*/
|
||
void dwt_delay_us(__IO uint32_t us)
|
||
{
|
||
uint32_t ticks;
|
||
uint32_t told,tnow,tcnt=0;
|
||
|
||
/* 在函数内部初始化时间戳寄存器, */
|
||
#if (CPU_TS_INIT_IN_DELAY_FUNCTION)
|
||
/* 初始化时间戳并清零 */
|
||
dwt_init();
|
||
#endif
|
||
|
||
ticks = us * (get_cpu_clk_freq() / 1000000); /* 需要的节拍数 */
|
||
tcnt = 0;
|
||
told = (uint32_t)dwt_read(); /* 刚进入时的计数器值 */
|
||
|
||
while(1)
|
||
{
|
||
tnow = (uint32_t)dwt_read();
|
||
if(tnow != told)
|
||
{
|
||
/* 32位计数器是递增计数器 */
|
||
if(tnow > told)
|
||
{
|
||
tcnt += tnow - told;
|
||
}
|
||
/* 重新装载 */
|
||
else
|
||
{
|
||
tcnt += UINT32_MAX - told + tnow;
|
||
}
|
||
|
||
told = tnow;
|
||
|
||
/*时间超过/等于要延迟的时间,则退出 */
|
||
if(tcnt >= ticks)break;
|
||
}
|
||
}
|
||
}
|
||
|
||
#endif
|
||
|