2012-09-14 05:29 AM
I'm working on a project on a STM32F4 CPU, generating signals (VGA) with DMA.
I have a generic timer on CPU clock (no prescaler) on a STM32 triggering interrupts on overflow, to generate a periodic signal with GPIO afterwards.
I need to trigger thr GPIO at a very regular time (basically down to a CPU cycle precision). I've managed to reduce this jitter to +-5 cycles by setting priorities & al, but this jitter exists, depending on what the CPU was doing and the interrupted instruction.
I need to compensate this few cycles jitter. Adding a few cycles more latency isn't a problem as long as I toggle GPIOs always at the same counter cycle.
My idea was to read the current value of the counter after the interrupt, and have an active loop of (FIXED_NUMBER-CNT->VAL) time, ensuring I would exit the loop at precise times.
However, doing a simple loop in C - being a FOR loop, or a while(counter->value < TARGET); doesn't work as it ADDS jitter instead of reducing it.
I ensured with empty, non optimized but not hitting memory loop body (asm(''''))See this example on AVR (more predictable timings) See by example
http://lucidscience.com/pro-vga video generator-7.aspx
(search for ''jitter'')I tried a simple loop in assembly such as (r0 has the number of cycles to wait to compensate counter value)
loop : SUBS r0,#1 ; tried with 2 also BGE loop
and, again, jitter is better without it.
To sum it up, I already know how much I should delay. Unfortunately, branches alone don't seem to work (nondeterminisctic pipeline refill ?) and IT conditional expressions don't either because they always take the same number of cycles (sometimes doing nothing).
Would running from RAM instead of flash improve consistency ?
Maybe I'm out of my league here ... any help would appreciated, thanks! (crosspost from stackoverflow as I think I'd have more success here than there, sorry) #interrupts-counter2013-05-27 07:11 AM
:D i found the attach link after klik the ok button, maybe next time i use it option.
thx for your replay... im try your suggest..The one with modulated signal does not appear to get low enough to read a zero state.
my opinion why it can be, because the pin on output mode and previous signal is high.what about you?ricky2013-05-27 06:48 PM
solved,
change Port E to Port C.. and the data receive normaly....ricky2014-03-18 04:08 PM
Not work for me this is my own code can you help me
/** ****************************************************************************** * @file IO_Toggle/main.c * @author MCD Application Team * @version V1.0.0 * @date 19-September-2011 * @brief Main program body ****************************************************************************** * @attention * * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * * <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2> ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/#include ''stm32f4_discovery.h''/** @addtogroup STM32F4_Discovery_Peripheral_Examples * @{ *//** @addtogroup IO_Toggle * @{ */ /* Private typedef -----------------------------------------------------------*/GPIO_InitTypeDef GPIO_InitStructure;/* Private define ------------------------------------------------------------*//* Private macro -------------------------------------------------------------*//* Private variables ---------------------------------------------------------*//* Private function prototypes -----------------------------------------------*/void TimingDelay(unsigned int tick);void EnableTiming(void);/* Private functions ---------------------------------------------------------*//** * @brief Main program * @param None * @retval None */int main(void){ /*!< At this stage the microcontroller clock setting is already configured, this is done through SystemInit() function which is called from startup file (startup_stm32f4xx.s) before to branch to application main. To reconfigure the default setting of SystemInit() function, refer to system_stm32f4xx.c file */ /* GPIOD Periph clock enable */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); /* Configure PD12, PD13, PD14 and PD15 in output pushpull mode */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOD, &GPIO_InitStructure); while (1) { /* PD15 to be toggled */ GPIO_SetBits(GPIOD, GPIO_Pin_15); /* Insert delay */ TimingDelay(10); GPIO_ResetBits(GPIOD, GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); /* Insert delay */ TimingDelay(1000); }}/** * @brief Delay Function. * @param nCount:specifies the Delay time length. * @retval None */volatile unsigned int *DWT_CYCCNT = (volatile unsigned int *)0xE0001004; //address of the registervolatile unsigned int *DWT_CONTROL = (volatile unsigned int *)0xE0001000; //address of the registervolatile unsigned int *SCB_DEMCR = (volatile unsigned int *)0xE000EDFC; //address of the register //****************************************************************************** void EnableTiming(void){ static int enabled = 0; if (!enabled) { *SCB_DEMCR = *SCB_DEMCR | 0xF42400; *DWT_CYCCNT = 0; // reset the counter *DWT_CONTROL = *DWT_CONTROL | 1 ; // enable the counter enabled = 1; }} //****************************************************************************** void TimingDelay(unsigned int tick){ unsigned int start, current; start = *DWT_CYCCNT; do { current = *DWT_CYCCNT; } while((current - start) < tick);} //******************************************************************************#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 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) */ /* Infinite loop */ while (1) { }}#endif/** * @} */ /** * @} */ /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/2014-03-18 05:36 PM
Not work for me this is my own code can you help me
You'd need to be calling EnableTiming() prior to entering the loop. For 1 us, use TimingDelay(SystemCoreClock / 1000000), ideally computing the constant outside the loop. For 1 ms, use TimingDelay(SystemCoreClock / 1000)