Author Topic: STM32F407 – ADC & DMA without IRQ  (Read 726 times)

0 Members and 1 Guest are viewing this topic.

Offline jcfotoTopic starter

  • Contributor
  • Posts: 25
  • Country: fr
STM32F407 – ADC & DMA without IRQ
« on: July 24, 2023, 04:01:59 pm »
Hi.
I've 2 problems :
   first is that my english is awfull. Sooooooorry.
   Second is why i post  ...
I use STM32F407 in bare metal code,  Code::Blocks and gcc toolchain on Linux. Perfect !
My last project is to use ADC to convert 4 GPIO with DMA but without IRQ. It's the user software who enable conversion when i want ! Fréquency of µC is 8MHz ( low consomption and no clock management).
I've readen RM0090 §10 and 13 but i think i forgot one thing.
Without DMA, i can read ADC data in a scan mode ( group of channels) after InitADC1_DMA_F4() function .
ADC1 is connected to DMA2 channel 0 stream 0 ( RM0090 table 43 p.308).
Base adress of DMA2 registers is 0x4002 6400 ( RM0090 p.65) - Offset in RM0090 p.335.
But with DMA, the area of data don't have real data. Values must be 0 <= v <= 4096 ...
For information, i use DMA ( DMA2 - channel4 - stream2) with USART1 in bare metal code without problem.
Code: [Select]
start cycle n° 0
SWSTAR enable.

analog value  IN1 = 23658498
analog value  IN2 = 46465603
analog value  IN3 = 51118835
analog value  IN6 = 52298478
End cycle n° 0
It seems that data area ( BufferADC1[] ) don't contain values.
Strange : work fine in SCAN mode without DMA ...
Is, community, can help me ?
Thank you

Part of main program :
Code: [Select]
//----------------------------------  setup zone
#define SIZEBuffADC1 4    //Number of data ( 4 GPIO = 4 Data)

volatile unsigned long BufferADC1[SIZEBuffADC1];  //Area of datas ADC in RAM

InitPIOA_F4();            //Pour UART1 PA9-10 et DAC1 PA1,2,3,6
InitADC1_DMA_F4((unsigned long) SIZEBuffADC1); //ADC1 Param
InitDMA4ADC1_F4( BufferADC1, (unsigned long) SIZEBuffADC1); //DMA Param
//---------------------------------  loop zone
...
  //................. Enable a software start for ADC
if( *ADC1_SR & 0x00000002)  //if [EOC] != 0 ...
  {
   *ADC1_SR &= 0xFFFFFFFD ; //... Reset EOC - bit1 - (AND on a complete register)
   *ADC1_CR2 |= ( 1<<30);    //[SWSART] Enable a software start for ADC
  }

//Later : Read BufferADC1[n] ( no problem in scan mode without DMA)
...
//--------------------------------  End of main

Init ADC function
Code: [Select]
void InitADC1_DMA_F4( unsigned long NbreConv)
{
          //Enable ADC1 clock bus
  *APB2_ENR |=   (1<<8);            //[ADC1EN] bit 8 = 1

    //----------------- RAZ used registers before use-----------------
  *ADC1_SQR1 &=  0xFF000000;       //Reset all fields without reserved
  *ADC1_SQR2 &=  0xC0000000;       //Reset all fields without reserved
  *ADC1_SQR3 &=  0xC0000000;       //Reset all fields without reserved
  *ADC1_CR1  &=  0xF43F0000;       //Reset all fields without reserved
  *ADC1_CR2  &=  0xC0000000;       //Reset all fields without reserved

    //------------------ Paramétrage des canaux IN ------------
          //Number of channels for conversion ( [L] = n-1)
  *ADC1_SQR1 |=  (((NbreConv-1)&0x0000000F)<<20);   //[L] bits 20 to 23

          //Ordrer & numéro of channels  ( IN1, 2, 3 &6)
  *ADC1_SQR3 |=  ( 0b00001<<0);    //[SQ1] bits 0 à 4 = 00001 -> IN1
  *ADC1_SQR3 |=  ( 0b00010<<5);    //[SQ2] bits 5 à 9 = 00010 -> IN2
  *ADC1_SQR3 |=  ( 0b00011<<10);   //[SQ3] bits 10 à 14 = 00011 -> IN3
  *ADC1_SQR3 |=  ( 0b00110<<15);   //[SQ4] bits 15 à 19 = 00110 -> IN6

          //Duration of each channel conversion
          //SMPR2 = canaux 0 à 9 - Used : ch1,2,3,6
          //Duration of conversion = 13,5 cycles  (+12,5 de base)
  *ADC1_SMPR2 |= ( 0b010<<3);       //[SMP1] bits 3,4,5  = 010
  *ADC1_SMPR2 |= ( 0b010<<6);       //[SMP2] bits 6,7,8  = 010
  *ADC1_SMPR2 |= ( 0b010<<9);       //[SMP3] bits 9,10,11   = 010
  *ADC1_SMPR2 |= ( 0b010<<18);      //[SMP6] bits 18,19,20  = 010

    //----------------------- Modes of conversion ------------------
/*------ By fault ( after RAZ), these fields have good value ( = 0) :
ADC_CR2     [EXTSEL]    unselected
ADC_CR2     [CONT]      User launch conversion. No continue
------------------------------------------------------------------*/

          //Mode SCAN of regulars channels §13.3.8 - Scan validate
  *ADC1_CR1  |=  ( 1<<8);      //Bit 8 [SCAN] = 1

          //EOC set after each channel converted. ( No at the end of group)
  *ADC1_CR2  |=  ( 1<<10);    //Bit 10 [EOCS] = 1 - EOC set after each conv

  *ADC1_CR2  |=  ( 1<<9);  //Bit 9 (DDCS) = 1 - DMA request if data available
  *ADC1_CR2  |=  ( 1<<8);    //Bit 8 [DMA] = 1 - Use DMA
    //-----------------  End modes of conversion ------------------

           //Start ADC
  *ADC1_CR2  |=  ( 1<<0);           //Bit 0 (ADON) = 1

  return;
}

Init DMA function
Code: [Select]
void InitDMA4ADC1_F4( volatile unsigned long *BuffADC, unsigned long BuffADC1size )
{
    //Valide les horloges du bus AHB si pas déjà fait
  *AHB1_ENR |= ( 1<<22);     // ... pour la DMA2 - bit DMA2EN

    //Memories/registers adress for data stream
  *DMA2_S0PA  = (unsigned long) ADC1_DR;      //Data register ADC1 ( source)
  *DMA2_S0M0A = (unsigned long) BuffADC;      //Destination area in RAM

    //Size of recept buffer = Nbre of IN to scan
  *DMA2_S0NDT = (unsigned long) BuffADC1size;  //buff size = transmit argument

    //RAZ authorised fields
  *DMA2_S0CR &= 0xF0100000;   //Reset all fields without reserved

/*------ By fault ( after RAZ), these fields have good value ( = 0) :
DMA2_S0CR     [DIR]     Data stream direction periph->memory
DMA2_S0CR     [CHSEL]   Use chanel 0    ( ADC1 use DMA2-channel0-stream0)
------------------------------------------------------------------*/

  *DMA2_S0CR |= (0b01<<16);   //Priority - [PL] -> bits 17-16 = 01 = Medium
  *DMA2_S0CR |= (0b01<<13);   //Size of data mém- [MSIZE]-> 01 = 16bits
  *DMA2_S0CR |= (0b01<<11);   //Size of data périph- [PSIZE]-> 01 = 16bits
  *DMA2_S0CR |= (1<<10);      //Incrément memory pointer - [MINC]-> bit 10 = 1
  *DMA2_S0CR |= (1<<8);       //Buffer circulaire - [CIRC]-> bit 8 = 1

  *DMA2_S0CR |= (1<<0);       //Enable DMA2 - [EN] -> bit 0 = 1
}

 

Offline wek

  • Frequent Contributor
  • **
  • Posts: 529
  • Country: sk
Re: STM32F407 – ADC & DMA without IRQ
« Reply #1 on: July 24, 2023, 04:32:59 pm »
You declare an array of 32-bit variables:

Quote
volatile unsigned long BufferADC1[SIZEBuffADC1];  //Area of datas ADC in RAM

and then make DMA to store 16-bits into them,

Quote
*DMA2_S0CR |= (0b01<<13);   //Size of data mém- [MSIZE]-> 01 = 16bits

so one variable in BufferADC1 contains values from two ADC conversions.

JW
 

Offline jcfotoTopic starter

  • Contributor
  • Posts: 25
  • Country: fr
Re: STM32F407 – ADC & DMA without IRQ
« Reply #2 on: July 24, 2023, 05:46:30 pm »
 :clap:

Exact, Wek.

I'd tried now and it's work fine ...  :palm:
Problem is that gcc (arm-none-eabi 10) have, natively, 3 size of data : 1, 4 or 8 bytes.
No 2 bytes ! This made me confuse ! A type int have a size of 4 bytes ...
RM0090 give information at p.315 in the last lines of table 46 !

This says that DMA is OK for USART ( 1 byte type char ) => no problem.
The best solution is to use uint_xx librarie but it's very heavy for only use this functionnality.

Thank you very much.


 

Online langwadt

  • Super Contributor
  • ***
  • Posts: 4696
  • Country: dk
Re: STM32F407 – ADC & DMA without IRQ
« Reply #3 on: July 24, 2023, 06:32:24 pm »
:clap:

Exact, Wek.

I'd tried now and it's work fine ...  :palm:
Problem is that gcc (arm-none-eabi 10) have, natively, 3 size of data : 1, 4 or 8 bytes.
No 2 bytes ! This made me confuse ! A type int have a size of 4 bytes ...
RM0090 give information at p.315 in the last lines of table 46 !

This says that DMA is OK for USART ( 1 byte type char ) => no problem.
The best solution is to use uint_xx librarie but it's very heavy for only use this functionnality.

Thank you very much.

a short is 2 bytes

uintxx_t in stdint.h is just type definitions it doesn't add any code


 

Offline bingo600

  • Super Contributor
  • ***
  • Posts: 2032
  • Country: dk
Re: STM32F407 – ADC & DMA without IRQ
« Reply #4 on: July 24, 2023, 06:33:08 pm »
Problem is that gcc (arm-none-eabi 10) have, natively, 3 size of data : 1, 4 or 8 bytes.
No 2 bytes ! This made me confuse ! A type int have a size of 4 bytes ...
..
..

The best solution is to use uint_xx librarie but it's very heavy for only use this functionnality.


If you write unsigned short , instead of unsigned long you would get 16-bit values.

But i'd recommend you to use the uintxx_t - here it would be uint16_t
NB: You need to include stdint.h or inttypes.h to get the uint16_t definition

I doubt that including one of the above files would increase the object size.

/Bingo
 

Offline jcfotoTopic starter

  • Contributor
  • Posts: 25
  • Country: fr
Re: STM32F407 – ADC & DMA without IRQ
« Reply #5 on: July 25, 2023, 08:00:48 am »
Hello, Bingo and langwadt.

I've tried whith your remarks : all what you said is true.
1) gcc accept short type for a size of 2 bytes. My transfert to 32 bits µC is incomplete !!!
2) utilisation of uint16_t with stdlib don't make the code more heavy => same size. I don't know why, but a long time ago (!), i've had the case with 8Ko more ... perhaps an error.

Thank you for actualisation of my ... education !
 

Offline jcfotoTopic starter

  • Contributor
  • Posts: 25
  • Country: fr
Re: STM32F407 – ADC & DMA without IRQ
« Reply #6 on: July 25, 2023, 08:08:12 am »
Bingo : a long type have a 4 bytes size.
 

Offline bingo600

  • Super Contributor
  • ***
  • Posts: 2032
  • Country: dk
Re: STM32F407 – ADC & DMA without IRQ
« Reply #7 on: July 25, 2023, 02:16:59 pm »
Bingo : a long type have a 4 bytes size.

Yes and ??

 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf