STM32F407 – ADC & DMA without IRQ - Page 1
Forum section: electronics / general

author: jcfoto
author_rank: Contributor
timestamp: July 24, 2023, 04:01:59 pm
content: 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:start cycle n° 0SWSTAR enable.analog value IN1 = 23658498analog value IN2 = 46465603analog value IN3 = 51118835analog value IN6 = 52298478End cycle n° 0It seems that data area ( BufferADC1[] ) don't contain values.Strange : work fine in SCAN mode without DMA ...Is, community, can help me ?Thank youPart of main program :Code://---------------------------------- setup zone#define SIZEBuffADC1 4 //Number of data ( 4 GPIO = 4 Data)volatile unsigned long BufferADC1; //Area of datas ADC in RAMInitPIOA_F4(); //Pour UART1 PA9-10 et DAC1 PA1,2,3,6InitADC1_DMA_F4((unsigned long) SIZEBuffADC1);//ADC1 ParamInitDMA4ADC1_F4( BufferADC1, (unsigned long) SIZEBuffADC1);//DMA Param//--------------------------------- loop zone...//................. Enable a software start for ADCif( *ADC1_SR & 0x00000002) //if  != 0 ...{*ADC1_SR &= 0xFFFFFFFD ;//... Reset EOC - bit1 - (AND on a complete register)*ADC1_CR2 |= ( 1<<30); // Enable a software start for ADC}//Later : Read BufferADC1 ( no problem in scan mode without DMA)...//-------------------------------- End of mainInit ADC functionCode:void InitADC1_DMA_F4( unsigned long NbreConv){//Enable ADC1 clock bus*APB2_ENR |= (1<<8); // 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 (  = n-1)*ADC1_SQR1 |= (((NbreConv-1)&0x0000000F)<<20); // bits 20 to 23//Ordrer & numéro of channels ( IN1, 2, 3 &6)*ADC1_SQR3 |= ( 0b00001<<0); // bits 0 à 4 = 00001 -> IN1*ADC1_SQR3 |= ( 0b00010<<5); // bits 5 à 9 = 00010 -> IN2*ADC1_SQR3 |= ( 0b00011<<10); // bits 10 à 14 = 00011 -> IN3*ADC1_SQR3 |= ( 0b00110<<15); // 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); // bits 3,4,5 = 010*ADC1_SMPR2 |= ( 0b010<<6); // bits 6,7,8 = 010*ADC1_SMPR2 |= ( 0b010<<9); // bits 9,10,11 = 010*ADC1_SMPR2 |= ( 0b010<<18); // bits 18,19,20 = 010//----------------------- Modes of conversion ------------------/*------ By fault ( after RAZ), these fields have good value ( = 0) :ADC_CR2  unselectedADC_CR2  User launch conversion. No continue------------------------------------------------------------------*///Mode SCAN of regulars channels §13.3.8 - Scan validate*ADC1_CR1 |= ( 1<<8); //Bit 8  = 1//EOC set after each channel converted. ( No at the end of group)*ADC1_CR2 |= ( 1<<10); //Bit 10  = 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  = 1 - Use DMA//----------------- End modes of conversion ------------------//Start ADC*ADC1_CR2 |= ( 1<<0); //Bit 0 (ADON) = 1return;}Init DMA functionCode: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  Data stream direction periph->memoryDMA2_S0CR  Use chanel 0 ( ADC1 use DMA2-channel0-stream0)------------------------------------------------------------------*/*DMA2_S0CR |= (0b01<<16); //Priority -  -> bits 17-16 = 01 = Medium*DMA2_S0CR |= (0b01<<13); //Size of data mém- -> 01 = 16bits*DMA2_S0CR |= (0b01<<11); //Size of data périph- -> 01 = 16bits*DMA2_S0CR |= (1<<10); //Incrément memory pointer - -> bit 10 = 1*DMA2_S0CR |= (1<<8); //Buffer circulaire - -> bit 8 = 1*DMA2_S0CR |= (1<<0); //Enable DMA2 -  -> bit 0 = 1}

author: wek
author_rank: Frequent Contributor
timestamp: July 24, 2023, 04:32:59 pm
content: You declare an array of 32-bit variables:Quoteand then make DMA to store 16-bits into them,Quoteso one variable in BufferADC1 contains values from two ADC conversions.JW

author: jcfoto
author_rank: Contributor
timestamp: July 24, 2023, 05:46:30 pm
content: Exact, Wek.I'd tried now and it's work fine ...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.

author: langwadt
author_rank: Super Contributor
timestamp: July 24, 2023, 06:32:24 pm
content: Quote from: jcfoto on July 24, 2023, 05:46:30 pma short is 2 bytesuintxx_t in stdint.h is just type definitions it doesn't add any code

author: bingo600
author_rank: Super Contributor
timestamp: July 24, 2023, 06:33:08 pm
content: Quote from: jcfoto on July 24, 2023, 05:46:30 pmIf you writeunsigned short, instead ofunsigned longyou would get 16-bit values.But i'd recommend you to use the uintxx_t - here it would beuint16_tNB: You need to include stdint.h or inttypes.h to get the uint16_t definitionI doubt that including one of the above files would increase the object size./Bingo

author: jcfoto
author_rank: Contributor
timestamp: July 25, 2023, 08:00:48 am
content: 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 !

author: jcfoto
author_rank: Contributor
timestamp: July 25, 2023, 08:08:12 am
content: Bingo : alongtype have a 4 bytes size.

author: bingo600
author_rank: Super Contributor
timestamp: July 25, 2023, 02:16:59 pm
content: Quote from: jcfoto on July 25, 2023, 08:08:12 amYes and ??