cancel
Showing results for 
Search instead for 
Did you mean: 

Different triggers on the same clock

matteo
Associate II
Posted on March 28, 2014 at 21:35

Hello,

For a project I am working on I would like to generate interrupts on both edges of the HSI clock, for synchronization purposes. The sysclk is based on the main PLL, sourced from HSE. I output HSI on the MCO1 (pin PA8), and I am able to generate interrupts on either or both edges on the EXTI line 8 from that pin. However, if I do it like that I have found no way to distinguish between rising and falling transitions. My workaround (that does not work) would be to wire the PA8 pin (on which I output the clock) to the PC9 pin (I use a jumper between them). I would then detect falling edge transitions on PA8 through EXTI line 8, and rising edge transitions on PC9 through EXTI line 9. However, with my configuration I only detect the falling edge transitions on PA8. Here is my code:

/*Initialization*/
//MCO1 outputs the HSI clock
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource8,GPIO_AF_MCO);
//With a jumper, I also wire MCO1 to the PC9 pin.
//Using two pins I can discriminate between clock edges
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/*Interrupt settings*/
NVIC_InitTypeDef NVIC_InitStructure;
/*Configure the mask bits for the interrupt on MCO1 */
EXTI->IMR |= 0x1 << 
8
;
/*Configure trigger selection bits for the interrupt on MCO1 */
EXTI->RTSR &= EXTI8_RISING_EDGE_NO; //Disable rising edge as trigger EXTI8_RISING_EDGE_NO == (uint32_t)0xFFFFFEFF
EXTI->FTSR |= EXTI8_FALLING_EDGE_YES; //Enable falling edge as trigger EXTI8_FALLING_EDGE_YES == (uint32_t)0x100
/*Configure the mask bits for the interrupt on PC9 (externally wired to MCO1)*/
EXTI->IMR |= 0x1 << 
9
;
//Configure trigger selection bits for interrupt on PC9
EXTI->RTSR |= EXTI9_RISING_EDGE_YES; //Enable rising edge as trigger EXTI9_RISING_EDGE_YES == (uint32_t)0x200
EXTI->FTSR &= EXTI9_FALLING_EDGE_NO; //Disable falling edge as trigger EXTI9_FALLING_EDGE_NO == (uint32_t)0xFFFFFDFF
/*Configure the enable and mask bits on the NVIC IRQ channel
* HSI on pin PA8, goes to EXTI line 8
* PC9 goes to EXTI line 9*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

And here is the handler:

void EXTI9_5_IRQHandler(void)
{
if(EXTI->PR & PR_EXTI8) //Interrupt on EXTI line 8, on which we registered the SCLK falling edge
{
if(debug_led_count++ == 5000000)
{
STM_EVAL_LEDToggle(LED3); //blinks correctly
debug_led_count = 0;
}
}
else if(EXTI->PR & PR_EXTI9) //Interrupt on EXTI line 9, on which we registered the SCLK rising edge
{
if(debug_led_count2++ == 5000000)
{
STM_EVAL_LEDToggle(LED4); //does not blink ever
debug_led_count2 = 0;
}
}
}

Could anyone point me in the direction of a solution? Is there some configuration I am missing? O perhaps my approach is entirely wrong? Cheers, Matteo
14 REPLIES 14
Posted on March 29, 2014 at 18:27

The DMA can read a single pin, or up to 16 within a bank. If your data is sparsely distributed in the pin bank you'll have to process the half-words and extract it. DMA is not smart, and you'd need one DMA unit (stream) per GPIO bank. So the smart method is to group the pins together.

You have to think how it's efficient for the hardware to do the work, not the convenience of random pin selection. You could manually fit the pin utilization, or use something like Micro Xplorer.

The DMA2 (of the STM32F2/4) can read a stream of data from a GPIOx->IDR bank, or write to a GPIOx->ODR bank, and synchronize it to a TIM, which can also output via a pin. The IDR would be easier because pins used for other purposes could simply be masked from the captured data.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
matteo
Associate II
Posted on March 29, 2014 at 19:29

The DMA can read a single pin, or up to 16 within a bank. If your data is sparsely distributed in the pin bank you'll have to process the half-words and extract it. DMA is not smart, and you'd need one DMA unit (stream) per GPIO bank. So the smart method is to group the pins together.

I am trying to understand that paragraph. When you say that the DMA can read a single pin, are you referring to what you then say, that the dma actually reads the whole bank, puts it in memory, and then I have to extract the info from those half-words in memory?

I am curious about this, because if I put my 8 ADCs connected to a single GPIO bank, then I will find in it, in each instant of measurement, 8 bits from 8 different measured values. After 8 cycles (assume 8 bit ADCs) I will have read 8 bytes, each one containing bits from all ADCs. This is an issue I had when I tried something similar on a board with a PIC18: after readout I had to transpose those 8 bytes to obtain the actual values form the ADCs.

Cheers,

Matteo

Posted on March 29, 2014 at 19:37

You read everything, either as an 8 or 16-bit read of GPIOx->IDR as needed to get the pin coverage you are looking for, and then after you have a large sample buffer, go in on the HT/TC DMA interrupts and extract the bit patterns from the bytes/half-words to reconstitute your serial data stream into bytes.

The data is sampled on a fixed clock to maintain time domain accuracy, you can process the data in at deferred time, and decode a burst.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
matteo
Associate II
Posted on March 29, 2014 at 20:52

Thank you for clarifying.

I have a further question. I am looking for this information in the reference manual but I cannot find it.

Suppose I connect all my ADCs to GPIOA[0...7]. Then I set the DMA to read bytes and store them in the FIFO. Will the DMA read GPIOA[0...7] each time, or will it do something silly like reading GPIOA[0...7], then reading GPIOA[8...15] and so on?

Cheers,

Matteo

Posted on March 29, 2014 at 21:21

In byte non-incrementing mode it will keep reading GPIOA[0...7]

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