Page 1 of 1

question on using timer and DMA for complex signal generatio

Posted: Mon Jan 20, 2014 4:02 pm
by jscott
I have a couple of questions about using a timer and DMA for signal generation on the STM32F4-discovery.

I want to use a timer to generate 3 "interrupts" to trigger three different DMA transfers.
I am planning on using the "reload" interrupt and 2 capture compare interrupts to trigger the DMA transfers.

A. The first interrupt will trigger on timer reload to DMA a fixed value to a 16-bit port.

B. The second interrupt will trigger a DMA transfer of the next half-word of a buffer to the same 16-bit port.

C. The third interrupt will trigger a DMA transfer of a different fixed value to the same 16-bit port.

Basically, I want to transfer 1000 16-bit values from a buffer at 800kHz with a fixed value before and after the value from the buffer. This cycle will repeat at about 800kHz until the buffer is transferred.

A couple of "quick" questions....

1. Do any of the Chibios timer functions let me use the three DMA triggers? It looks
like I will need to directly control the timer config. Just wanted to know if I was missing something.

2. Is there a way to set up a DMA transfer of a 1000 half-word buffer and trigger each transfer individually, or will the trigger start the dma transfer and run till the complete buffer is transferred?

Thanks!
-John Scott

Re: question on using timer and DMA for complex signal gener

Posted: Mon Jan 20, 2014 4:20 pm
by Giovanni
I never did that but I think that the GPT is close to what you need but it does not perform some DMA-related settings, you may operate on registers after starting a GPT.

Giovanni

Re: question on using timer and DMA for complex signal gener

Posted: Tue Jan 28, 2014 5:29 am
by jscott
OK, I think I got most of the timer stuff setup using...

Code: Select all

/*
 * GPT3 configuration.
 */
static GPTConfig gpt3cfg =
{
  84000000,   /* timer clock.  84000000 / 800000 = 105 */
  NULL,        /* Timer callback.*/
  STM32_TIM_DIER_CC1DE | STM32_TIM_DIER_CC2DE |
  STM32_TIM_DIER_CC4DE | STM32_TIM_DIER_UDE
};


and

Code: Select all

    gptStart(&GPTD3, &gpt3cfg);

    // configure the timer to reload after 105 timer clock tics
    //   The clock is running at 84,000,000Hz,
    //   so 84,000,000 / 105 = 800,000Hz
    gptStartContinuous(&GPTD4, 105);



But I am stumped as to setting the Counter Compare Registers
// TIM3_CCR1 = 0X000a;
// TIM3_CCR2 = 0X002c;
// TIM3_CCR4 = 0X004F;

I have been reading lots of the Chibios code, but I am not clear about
a clean way to access the timer registers from user code.

Also, if I understand correctly, I should set these registers between calls
to gptStart() and gptStartContinuous(). Is that correct?

Thanks
-John Scott

Re: question on using timer and DMA for complex signal gener

Posted: Tue Jan 28, 2014 9:53 am
by Giovanni
Hi,

Accessing the HW unit associated to a driver is very simple, each driver instance maintains a pointer to the registers block. For the GPT it would be:

GPTDx.tim->CCR1 = xxxx;

From callbacks:

gptp->tim->CCR1 = xxxx;

About the procedure, start the driver using gptStart() then change the settings by accessing the control registers (do not change the whole register, use OR/AND on the existing value).

Giovanni

Re: question on using timer and DMA for complex signal gener

Posted: Wed Jan 29, 2014 11:10 pm
by jscott
OK, I think I am getting a handle on how to set the dma transactions up, here is my
code for setting up one of the DMA streams... This stream should move data from
a 14K output buffer to PORTE one HWORD per trigger.

Will this work correctly, or am I missing something....

Also, how do I set up a callback to indicate when this buffer is completely sent?
I saw a reference to it somewhere, but can't find it now... :oops:

Code: Select all

  // Allocate the stream
  dmaStreamAllocate( STM32_DMA1_STREAM5, 0, NULL, NULL );

  // Set the source Address
  dmaStreamSetPeripheral( STM32_DMA1_STREAM5, pattern1 );

  // Set the destination address
  dmaStreamSetMemory0( STM32_DMA1_STREAM5, GPIO_PORTE );

  // set the size of the output buffer
  dmaStreamSetTransactionSize( STM32_DMA1_STREAM5, sizeof (pattern1) );

  // config 16-bit HWORD transfers, memory to peripheral,
  //inc source address, fixed dest address
  dmaStreamSetMode( STM32_DMA1_STREAM5,
                    STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD |
                    STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2P |
                    STM32_DMA_CR_PINC );