cancel
Showing results for 
Search instead for 
Did you mean: 

Delay in us

l90mehdi
Associate II
Posted on April 08, 2016 at 13:17

hi

I am coding with HAL driver.I need delay in us range.but HAL driver can creation delay in ms.

so How can i use HAL Driver in us? 

#hal_delay
13 REPLIES 13
Posted on April 08, 2016 at 13:39

Use the count register of a fast free running timer or DWT_CYCCNT

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
l90mehdi
Associate II
Posted on April 12, 2016 at 20:04

I will test your solution.

Thank you .

Siragh ASUTP
Associate II

Posted on March 12, 2017 at 23:57

Why does my code not work?

STM32F103VET6

/* Includes ------------------------------------------------------------------*/
 
 
 
#include ''stm32f1xx_hal.h''
 
 
 
#include ''gpio.h''
 
/* USER CODE BEGIN Includes */
 
/* USER CODE END Includes */
 
/* Private variables ---------------------------------------------------------*/
 
/* USER CODE BEGIN PV */
 
 
 
/* Private variables ---------------------------------------------------------*/
 
 
 
volatile unsigned int *DWT_CYCCNT = (volatile unsigned int *)0xE0001004; //address of the register
 
 
 
volatile unsigned int *DWT_CONTROL = (volatile unsigned int *)0xE0001000; //address of the register
 
 
 
volatile unsigned int *SCB_DEMCR = (volatile unsigned int *)0xE000EDFC; //address of the register 
 
/* USER CODE END PV */
 
/* Private function prototypes -----------------------------------------------*/
 
 
 
void SystemClock_Config(void);
 
 
 
void Error_Handler(void);
 
/* USER CODE BEGIN PFP */
 
 
 
/* Private function prototypes -----------------------------------------------*/
 
/* USER CODE END PFP */
 
/* USER CODE BEGIN 0 */
 
 
 
void EnableTiming(void)
 
 
 
 {
 
 
 
 *SCB_DEMCR = *SCB_DEMCR | 0x01000000;
 
*DWT_CYCCNT = 0; // reset the counter
 
 
 
 *DWT_CONTROL = *DWT_CONTROL | 1 ; // enable the counter
 
 
 
 }
 
 
 
 void TimingDelay(unsigned int tick)
 
 
 
 {
 
 
 
 unsigned int start, current;
 
start = *DWT_CYCCNT;
 
do
 
 
 
 {
 
 
 
 current = *DWT_CYCCNT;
 
 
 
 } while((current - start) < tick);
 
 
 
 }
 
/* USER CODE END 0 */
 
int main(void)
 
 
 
{
 
/* USER CODE BEGIN 1 */
 
/* USER CODE END 1 */
 
/* MCU Configuration----------------------------------------------------------*/
 
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 
 
 
 HAL_Init();
 
/* Configure the system clock */
 
 
 
 SystemClock_Config();
 
/* Initialize all configured peripherals */
 
 
 
 MX_GPIO_Init();
 
/* USER CODE BEGIN 2 */
 
/* USER CODE END 2 */
 
/* Infinite loop */
 
 
 
 /* USER CODE BEGIN WHILE */
 
 
 
 while (1)
 
 
 
 {
 
 
 
 /* USER CODE END WHILE */
 
 
 
 HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, GPIO_PIN_RESET);
 
 
 
 TimingDelay(50);
 
 
 
 HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, GPIO_PIN_SET);
 
 
 
 TimingDelay(50);
 
 
 
 /* USER CODE BEGIN 3 */
 
}
 
 
 
 /* USER CODE END 3 */
 
}
 
/** System Clock Configuration
 
 
 
*/
 
 
 
void SystemClock_Config(void)
 
 
 
{
 
RCC_OscInitTypeDef RCC_OscInitStruct;
 
 
 
 RCC_ClkInitTypeDef RCC_ClkInitStruct;
 
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
 
 
 
 RCC_OscInitStruct.HSIState = RCC_HSI_ON;
 
 
 
 RCC_OscInitStruct.HSICalibrationValue = 16;
 
 
 
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
 
 
 
 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
 
 
 
 RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16;
 
 
 
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
 
 
 
 {
 
 
 
 Error_Handler();
 
 
 
 }
 
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
 
 
 
 |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
 
 
 
 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
 
 
 
 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
 
 
 
 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
 
 
 
 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 
 
 
 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
 
 
 
 {
 
 
 
 Error_Handler();
 
 
 
 }
 
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
 
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
 
/* SysTick_IRQn interrupt configuration */
 
 
 
 HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
 
 
 
}
 
/* USER CODE BEGIN 4 */
 
/* USER CODE END 4 */
 
/**
 
 
 
 * @brief This function is executed in case of error occurrence.
 
 
 
 * @param None
 
 
 
 * @retval None
 
 
 
 */
 
 
 
void Error_Handler(void)
 
 
 
{
 
 
 
 /* USER CODE BEGIN Error_Handler */
 
 
 
 /* User can add his own implementation to report the HAL error return state */
 
 
 
 while(1) 
 
 
 
 {
 
 
 
 }
 
 
 
 /* USER CODE END Error_Handler */ 
 
 
 
}
 
#ifdef USE_FULL_ASSERT
 
/**
 
 
 
 * @brief Reports the name of the source file and the source line number
 
 
 
 * where the assert_param error has occurred.
 
 
 
 * @param file: pointer to the source file name
 
 
 
 * @param line: assert_param error line source number
 
 
 
 * @retval None
 
 
 
 */
 
 
 
void assert_failed(uint8_t* file, uint32_t line)
 
 
 
{
 
 
 
 /* USER CODE BEGIN 6 */
 
 
 
 /* User can add his own implementation to report the file name and line number,
 
 
 
 ex: printf(''Wrong parameters value: file %s on line %d\r\n'', file, line) */
 
 
 
 /* USER CODE END 6 */
 
}
 
#endif
 
/**
 
 
 
 * @}
 
 
 
 */
 
/**
 
 
 
 * @}
 
 
 
*/
 
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

0690X00000603lxQAA.jpg

ChrisH
Associate III
Posted on March 13, 2017 at 01:01

You can use this:

uint32_t getUs(void) {

uint32_t usTicks = HAL_RCC_GetSysClockFreq() / 1000000;

register uint32_t ms, cycle_cnt;

do {

ms = HAL_GetTick();

cycle_cnt = SysTick->VAL;

} while (ms != HAL_GetTick());

return (ms * 1000) + (usTicks * 1000 - cycle_cnt) / usTicks;

}

void delayUs(uint16_t micros) {

uint32_t start = getUs();

while (getUs()-start < (uint32_t) micros) {

asm('nop');

}

}
Knut Knusper
Associate II
Posted on March 13, 2017 at 13:03

I use the following Code in an STM32F4 with DWT:

dwt_stm32_delay.h

#ifndef DWT_STM32_DELAY_H
#define DWT_STM32_DELAY_H
#ifdef __cplusplus
extern 'C' {
#endif

#include 'stm32f4xx_hal.h'
/**
 * @brief Initializes DWT_Cycle_Count for DWT_Delay_us function
 * @return Error DWT counter
 * 1: DWT counter Error
 * 0: DWT counter works
 */
uint32_t DWT_Delay_Init(void);

/**
 * @brief This function provides a delay (in microseconds)
 * @param microseconds: delay in microseconds
 */
__STATIC_INLINE void DWT_Delay_us(volatile uint32_t microseconds)
{
 uint32_t clk_cycle_start = DWT->CYCCNT;
 /* Go to number of cycles for system */
 microseconds *= (HAL_RCC_GetHCLKFreq() / 1000000);
 /* Delay till end */
 while ((DWT->CYCCNT - clk_cycle_start) < microseconds);
}

#ifdef __cplusplus
}
#endif
#endif
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

dwt_stm32_delay.c

#include 'dwt_stm32_delay.h'

/**
 * @brief Initializes DWT_Clock_Cycle_Count for DWT_Delay_us function
 * @return Error DWT counter
 * 1: clock cycle counter not started
 * 0: clock cycle counter works
 */
uint32_t DWT_Delay_Init(void) {
 /* Disable TRC */
 CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk; // ~0x01000000;
 /* Enable TRC */
 CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; // 0x01000000;
 /* Disable clock cycle counter */
 DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk; //~0x00000001;
 /* Enable clock cycle counter */
 DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; //0x00000001;
 /* Reset the clock cycle counter value */
 DWT->CYCCNT = 0;
/* 3 NO OPERATION instructions */
__ASM volatile ('NOP');
__ASM volatile ('NOP');
 __ASM volatile ('NOP');
 /* Check if clock cycle counter has started */
if(DWT->CYCCNT)
{
 return 0; /*clock cycle counter started*/
}
else
 {
 return 1; /*clock cycle counter not started*/
 }
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

main.c

/* Includes ------------------------------------------------------------------*/
#include 'stm32f4xx_hal.h'
#include 'dwt_stm32_delay.h'
int main(void)
{
 /* USER CODE BEGIN 1 */
 /* USER CODE END 1 */
 /* MCU Configuration----------------------------------------------------------*/
 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 HAL_Init();
 /* Configure the system clock */
 SystemClock_Config();
 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 /* USER CODE BEGIN 2 */
 if(DWT_Delay_Init())
 {
 Error_Handler(); /* Call Error Handler */
 }
 while(1)
 {
 /* 10s Delay */
 DWT_Delay_us(10000000);
 HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
 }
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Posted on March 13, 2017 at 15:50

You actually have to call 

EnableTiming() for it to do it's job... otherwise the cycle counter isn't enabled.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..

Posted on April 06, 2017 at 15:10

Hi 

Stockert.Stefan

thank you for your code, it was very helpful, 

however, i would like to implement DWT using interrupt ! 

Can you help me please ? I have no idea about it's implementation.

S.Ma
Principal
Posted on April 06, 2017 at 18:35

One traditional approach is to use a timer output compare for minimum elapsed time. Benefit comes if the core frequency changes or stops as some timers can use different clocks. Don t know if debug cycle counter is accessible if the mcu is protected on level 2...

Posted on April 06, 2017 at 17:26

I doesn't provide interrupts. And the WHOLE point of using a free running hardware counter is to AVOID the idiocy of using interrupt based software counters (ie SysTick) and the kinds of priority inversions and blocking that come with them. Once enabled you can read DWT_CYCCNT at ANY time.

DWT_CYCCNT is a cycle counter within the debug unit of the core, it counts clock ticks at very high rates, and is good for sub-microsecond timing due to it's resolution. It is also 32-bit wide giving it a longer wrap time.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..