DAC driver for the STM32

ChibiOS public support forum for topics related to the STMicroelectronics STM32 family of micro-controllers.

Moderator: RoccoMarco

alex0
Posts: 5
Joined: Sat Nov 16, 2013 9:18 pm

Re: DAC driver for the STM32

Post by alex0 »

Hello! :?:

I wanted to try the DAC driver for STM32F4xx.

First, I made a clone of the repository https://github.com/mobyfab/ChibiOS/tree/dac

Then, compile the example shown in the folder ChibiOS\testhal\STM32F4xx\DAC\

But it throws the following errors:

../../../os/hal/platforms/STM32/DACv1/dac_lld.h:258:3: error: unknown type name 'dacmode_t'
In file included from ../../../os/hal/include/hal.h:50:0,
from ../../../test/test.c:26:
../../../os/hal/include/dac.h:308:3: error: unknown type name 'DACConversionGroup'
../../../os/hal/include/dac.h:309:27: error: unknown type name 'dacsample_t'
../../../os/hal/include/dac.h:310:3: error: unknown type name 'DACConversionGroup'
../../../os/hal/include/dac.h:311:28: error: unknown type name 'dacsample_t'
../../../os/hal/include/dac.h:315:3: error: unknown type name 'DACConversionGroup'
../../../os/hal/include/dac.h:316:20: error: unknown type name 'dacsample_t'
make: *** [build/obj/test.o] Error 1

How well are the steps you took?

From what I see the problem is compatibility between files dac_lld.c/.h and dac.c/.h :oops:

Thank you!
Greetings!
beaming
Posts: 11
Joined: Sun Nov 10, 2013 9:27 pm

Re: DAC driver for the STM32

Post by beaming »

You should have cloned the dac-new tree instead of just dac.
https://github.com/mobyfab/ChibiOS/tree/dac-new
alex0
Posts: 5
Joined: Sat Nov 16, 2013 9:18 pm

Re: DAC driver for the STM32

Post by alex0 »

Thank you! :P
mobyfab
Posts: 484
Joined: Sat Nov 19, 2011 6:47 pm
Has thanked: 21 times
Been thanked: 31 times

Re: DAC driver for the STM32

Post by mobyfab »

Hey,

I Added demos for all STM32 devices now, F1 included.

I have fixed callbacks so it should work pretty well now.

Also there is now a dac branch forked from v3.0:
https://github.com/mobyfab/ChibiOS/tree/dac-3.0
Still very experimental.

Let me know if you have any issues.
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: DAC driver for the STM32

Post by Giovanni »

Hi,

I am integrating the driver in the 3.0 branch unchanged but there is some points that I think we should address:

1) Move the timers handling outside the driver, the GPT should be used for that (after doing few changes). the rationale is you may want to use any of the possible triggering sources for the DAC. This will also make the driver simpler.
2) Support for linked mode, it is required for stereo playback using a single DMA.

Giovanni
mobyfab
Posts: 484
Joined: Sat Nov 19, 2011 6:47 pm
Has thanked: 21 times
Been thanked: 31 times

Re: DAC driver for the STM32

Post by mobyfab »

Sounds good, I'll make the changes.
dismirlian
Posts: 65
Joined: Fri Dec 20, 2013 3:59 pm
Has thanked: 1 time
Been thanked: 16 times

Re: DAC driver for the STM32

Post by dismirlian »

Hello, I've been testing the excellent DAC driver, and found some bugs:

1. Incorrect mask for CR (function dac_lld_start). When regshift is 16, the following lines behave incorrectly:

Code: Select all

void dac_lld_start(DACDriver *dacp) {
    ...
    /* DAC configuration */
    dacp->dac->CR |= ( (dacp->dac->CR & ~STM32_DAC_CR_MASK) | \
      (STM32_DAC_CR_EN | STM32_DAC_CR_DMAEN | dacp->config->cr_flags) ) << regshift;
    ...

They could be changed to something like:

Code: Select all

    dacp->dac->CR &=  ~(STM32_DAC_CR_MASK << regshift);
    dacp->dac->CR |= (STM32_DAC_CR_EN | STM32_DAC_CR_DMAEN | dacp->config->cr_flags) << regshift;


2. I think that dac_lld_stop should release the DMA stream, mirroring the ADC driver. Please note that I haven't analyzed the driver's state machine in detail... The modified code could look like this:

Code: Select all

void dac_lld_stop(DACDriver *dacp) {

  /* If in ready state then disables the DAC clock.*/
  if (dacp->state == DAC_READY) {
    
   dmaStreamRelease(dacp->dma);

#if STM32_DAC_USE_CHN1


3. Maybe dac_lld_stop_conversion should disable the DMA stream, instead of releasing it:

Code: Select all

void dac_lld_stop_conversion(DACDriver *dacp) {
   
  /* If in active state then disables the DAC.*/
  if (dacp->state == DAC_ACTIVE) {

    /* DMA disable.*/
    dmaStreamDisable(dacp->dma);
    dacp->state = DAC_READY;
  }
}


4. The DAC driver causes the uC to hang sporadically. Disabling the timer before stopping the conversion solves the issue, and the uC doesn't hang any more, but my fix is rather dirty, because I had to move code from dac_lld_start to dac_lld_start_conversion. This is my "final" code:

Code: Select all

void dac_lld_start(DACDriver *dacp) {
    ...
#if STM32_DAC_USE_CHN1 || STM32_DAC_USE_CHN2 || STM32_DAC_USE_CHN3
    dacp->clock = STM32_TIMCLK1;
//    arr = (dacp->clock / dacp->config->frequency);
//    chDbgAssert((arr <= 0xFFFF),
//        "dac_lld_start(), #1", "invalid frequency");

    /* Timer configuration.*/
    dacp->tim->CR1  = 0;                        /* Initially stopped.   */
    dacp->tim->PSC  = 0;                        /* Prescaler value.     */
    dacp->tim->DIER = 0;
//    dacp->tim->ARR  = arr;
    dacp->tim->EGR  = TIM_EGR_UG;               /* Update event.        */
    dacp->tim->CR2  &= (uint16_t)~TIM_CR2_MMS;
    dacp->tim->CR2  |= (uint16_t)TIM_CR2_MMS_1; /* Enable TRGO updates. */
    //dacp->tim->CNT  = 0;                        /* Reset counter.       */
    //dacp->tim->SR   = 0;                        /* Clear pending IRQs.  */
    /* Update Event IRQ enabled. */
    /* Timer start.*/
    //dacp->tim->CR1  = TIM_CR1_CEN;

    /* DAC configuration */
    dacp->dac->CR &=  ~(STM32_DAC_CR_MASK << regshift);
    dacp->dac->CR |= (STM32_DAC_CR_EN | STM32_DAC_CR_DMAEN | dacp->config->cr_flags) << regshift;
 
    ...
}


void dac_lld_stop(DACDriver *dacp) {

  /* If in ready state then disables the DAC clock.*/
  if (dacp->state == DAC_READY) {
    
   dmaStreamRelease(dacp->dma);
        ...
}


void dac_lld_start_conversion(DACDriver *dacp) {
  chDbgAssert(dacp->samples, "dac_lld_start_conversion(), #1",
    "dacp->samples is NULL pointer");
  dmaStreamSetMemory0(dacp->dma, dacp->samples);
  dmaStreamSetTransactionSize(dacp->dma, dacp->depth);
  dmaStreamSetMode(dacp->dma, dacp->dmamode | STM32_DMA_CR_EN |
  STM32_DMA_CR_CIRC);

  dacp->tim->ARR = (dacp->clock / dacp->config->frequency);
  dacp->tim->CNT  = 0;                        /* Reset counter.       */
  dacp->tim->SR   = 0;                        /* Clear pending IRQs.  */
    /* Update Event IRQ enabled. */
    /* Timer start.*/
  dacp->tim->CR1  = TIM_CR1_CEN;

}

void dac_lld_stop_conversion(DACDriver *dacp) {
   
  /* If in active state then disables the DAC.*/
  if (dacp->state == DAC_ACTIVE) {

   dacp->tim->CR1 = 0;

    /* DMA disable.*/
   dmaStreamDisable(dacp->dma);
    dacp->state = DAC_READY;
  }

}


Thanks,
Diego
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: DAC driver for the STM32

Post by Giovanni »

Hi,

Thanks for finding, I am doing changes to the DAC driver and will look in the above points too.

Giovanni
c2issy
Posts: 5
Joined: Tue Oct 28, 2014 2:32 am

Re: DAC driver for the STM32

Post by c2issy »

Hi,

I have started working on the dac driver recently to build a random waveform generator when I saw your post.
As a newbie to chibiOS, I tried to look at your code but it seems that the git links you provided have expired.
Could you kindly send me your implementation of the dac driver? I would be really grateful if you could help. Stuck by the problem for a long time.

I'm using STM32F4 discovery board and chibiOS RT right now.

Cheers,
CC
Post Reply