How to change stm32 m4 adc channel?

Apr 26, 2021 Last reply: 5 years ago 24 Replies

Does anyone know how to do it in register level?



I see many code examples using:



ADC_ChannelConfTypeDef sConfig = {ADC_CHANNEL_0, 1, ADC_SAMPLETIME_28CYCLES}; HAL_ADC_ConfigChannel(&hadc1, &sConfig); or ADC_RegularChannelConfig(ADC1, ADC_channel_0, 1, ADC_SampleTime_480Cycles);



but i don't have access to these routines from arm-gcc.



By the way, i am using this to read the adc data:



#include "stm32f407xx.h" ADC1->CR2 |= ADC_CR2_SWSTART; // Start A2D while (!(ADC1->SR & ADC_SR_EOC)); // ready wait r = ADC1->DR;


Have you tried asking your question in comp.arch.embedded? Certainly there is more expertise in this area in that group.

mandag den 26. april 2021 kl. 18.52.19 UTC+2 skrev Ed Lee:

why are you doing it the hard way? just install stm32cubeIDE and be done with it

Ick. If you *really* need to "hang around" until the result is available (instead of checking it, again, "some time later"), AT LEAST put a limit on how many iterations you'll spin. You *know* when it is specified to be complete; if it isn't, something DETECTABLE is broken (and your code should report it instead of just "lock up")

And, if you're gonna spin on a NoOp, do it in a noticeable way:

while (!(ADC1->SR & ADC_SR_EOC)) { // ready wait }

Yes, if it lock up, will put in timeout in the real code. But if the chip does not stop after the specified cycles, there is serious hardware problem of the chip anyway.

Just to be consistent and a bit faster. Default STM codes read 4 bytes and write 4 bytes to change a bit. I re-coded most registers to do bytes. I can do port I/O, usart and adc. Just haven't figure out mux channels yet.

typedef struct { union { struct { uint8_t b3; uint8_t b2; uint8_t b1; uint8_t b0; } b; uint32_t r; }; } REG;

Of course! But, the *user* just sees "it died"; he has no way of knowing (nor does he care) that it locked up spinning (vs. locked up due to a failure of Vcc at the chip).

The point is, you (can) know something that you can use to inform the user of a problem. Or, prevent some OTHER aspect of the code from chugging along on the assumption that "all is well".

["Can't Happen" should effectively PANIC so everything goes "safe"]

you do know that the stm32 is 32 bit processsor so it reads and writes 32 bits at a time? and that IO's have bitset and bitreset registers

doing things in bytes is pointless and takes more cycles and code space

Not from gcc. All I/O ends up with 8 bits read and write.

If Vcc failed, the stm32 m4 with internal adc won't run anyway.

uint32_t ODR; // output data register, offset: 0x14 #define COUNT (pc->ODR)

COUNT = 0x12345678; 297 @ 179 "main.c" 1 298 # beg init COUNT 299 @ 0 "" 2 300 .arm 301 .syntax unified 302 036c C0339FE5 ldr r3, .L11+32 303 0370 1420D3E5 ldrb r2, [r3, #20] 304 0374 0020A0E3 mov r2, #0 305 0378 782082E3 orr r2, r2, #120 306 037c 1420C3E5 strb r2, [r3, #20] 307 0380 1520D3E5 ldrb r2, [r3, #21] 308 0384 0020A0E3 mov r2, #0 309 0388 562082E3 orr r2, r2, #86 310 038c 1520C3E5 strb r2, [r3, #21] 311 0390 1620D3E5 ldrb r2, [r3, #22] 312 0394 0020A0E3 mov r2, #0 313 0398 342082E3 orr r2, r2, #52 314 039c 1620C3E5 strb r2, [r3, #22] 315 03a0 1720D3E5 ldrb r2, [r3, #23] 316 03a4 0020A0E3 mov r2, #0 317 03a8 122082E3 orr r2, r2, #18 318 03ac 1720C3E5 strb r2, [r3, #23] COUNT += 1; 335 03b0 7C339FE5 ldr r3, .L11+32 336 03b4 1420D3E5 ldrb r2, [r3, #20] 337 03b8 FF2002E2 and r2, r2, #255 338 03bc 1510D3E5 ldrb r1, [r3, #21] 339 03c0 FF1001E2 and r1, r1, #255 340 03c4 0114A0E1 lsl r1, r1, #8 341 03c8 022081E1 orr r2, r1, r2 342 03cc 1610D3E5 ldrb r1, [r3, #22] 343 03d0 FF1001E2 and r1, r1, #255 344 03d4 0118A0E1 lsl r1, r1, #16 345 03d8 022081E1 orr r2, r1, r2 346 03dc 1730D3E5 ldrb r3, [r3, #23] 347 03e0 FF3003E2 and r3, r3, #255 348 03e4 033CA0E1 lsl r3, r3, #24 349 03e8 023083E1 orr r3, r3, r2

makes no sense

arm-none-eabi-gcc compiling for a cortex-m4

. . GPIOE->ODR = 0x12345678; 8000f34: f503 3300 add.w r3, r3, #131072 ; 0x20000 8000f38: 4a03 ldr r2, [pc, #12] ; (8000f48 <main+0x40>) 8000f3a: 615a str r2, [r3, #20] GPIOE->ODR += 1; 8000f3c: 695a ldr r2, [r3, #20] 8000f3e: 3201 adds r2, #1 8000f40: 615a str r2, [r3, #20] 8000f42: e7fe b.n 8000f42 <main+0x3a>

8000f44: 40001000 .word 0x40001000 8000f48: 12345678 .word 0x12345678

Something wrong with latest gcc?

gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-gcc -g -o stm.rom boot.s main.c

Something wrong with a local struct.

GPIOC->ODR works fine. I'll get rid of the local declaration.

typedef struct { ... uint32_t ODR; // output data register, offset: 0x14 ... } __attribute__((packed)) GPIO_t; volatile GPIO_t* const pc = (GPIO_t*)0x40020800;

I'm surprised it compiled at all, because it makes no sense

I copied it from an example, before pulling in all the st header files. I don't need it anymore, but wondering how and why it generated 8 bit codes.

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Do not use this. It causes 8-bit writes and inefficient code.

I use definition like this:

typedef struct { ... volatile uint32_t ODR; // output data register, offset: 0x14 ... } GPIO_STRUCT;

typedef GPIO_STRUCT * GPIO;

#define pc ((GPIO)0x40020800);

My changes are mostly stylistic and you my prefer your style. But do not make the struct packed. I am not sure if having volatile on each member is necessery, but it looks clearer and works.

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required