Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to change stm32 m4 adc channel?

86 views
Skip to first unread message

Ed Lee

unread,
Apr 26, 2021, 12:52:19 PM4/26/21
to
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;

Rick C

unread,
Apr 26, 2021, 1:09:16 PM4/26/21
to
Have you tried asking your question in comp.arch.embedded? Certainly there is more expertise in this area in that group.

--

Rick C.

- Get 1,000 miles of free Supercharging
- Tesla referral code - https://ts.la/richard11209

Ed Lee

unread,
Apr 26, 2021, 1:23:51 PM4/26/21
to
On Monday, April 26, 2021 at 10:09:16 AM UTC-7, gnuarm.del...@gmail.com wrote:
> On Monday, April 26, 2021 at 12:52:19 PM UTC-4, Ed Lee wrote:
> > 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.

OK, will do.

Lasse Langwadt Christensen

unread,
Apr 26, 2021, 1:29:53 PM4/26/21
to
why are you doing it the hard way? just install stm32cubeIDE and be done with it

Don Y

unread,
Apr 26, 2021, 1:32:38 PM4/26/21
to
On 4/26/2021 9:52 AM, Ed Lee wrote:
> 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;

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")

Don Y

unread,
Apr 26, 2021, 1:34:16 PM4/26/21
to
On 4/26/2021 10:32 AM, Don Y wrote:
> On 4/26/2021 9:52 AM, Ed Lee wrote:
>> 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;

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

Ed Lee

unread,
Apr 26, 2021, 1:40:37 PM4/26/21
to
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.

Ed Lee

unread,
Apr 26, 2021, 1:50:08 PM4/26/21
to
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;

Don Y

unread,
Apr 26, 2021, 1:52:38 PM4/26/21
to
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"]

Lasse Langwadt Christensen

unread,
Apr 26, 2021, 1:59:50 PM4/26/21
to
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




Ed Lee

unread,
Apr 26, 2021, 2:13:49 PM4/26/21
to
Not from gcc. All I/O ends up with 8 bits read and write.

Ed Lee

unread,
Apr 26, 2021, 2:15:30 PM4/26/21
to
On Monday, April 26, 2021 at 10:52:38 AM UTC-7, Don Y wrote:
> On 4/26/2021 10:40 AM, Ed Lee wrote:
> > On Monday, April 26, 2021 at 10:32:38 AM UTC-7, Don Y wrote:
> >> On 4/26/2021 9:52 AM, Ed Lee wrote:
> >>> 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;
> >> 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")
> >
> > 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.
> 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).

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

Don Y

unread,
Apr 26, 2021, 2:30:36 PM4/26/21
to
You're engaging in excusitis. One surefire way to end up with a buggy product!

["That can't happen so I don't have to worry about it". If I had a nickel for
every time someone WITNESSED a "can't happen"...]

Is there any way another thread can reprogram the I/Os that are resolved
at the address(es) you're accessing? Or, if a single-threaded application,
any way some earlier conditional execution can cause that to happen?

I.e., a *bug* could potentially cause your code to hang -- by reprogramming
the "port" to be a GPIO, etc.

Ed Lee

unread,
Apr 26, 2021, 2:44:36 PM4/26/21
to
No, it's a single thread app, with the adc status bit at a fixed physical address. No other program can change it.

> I.e., a *bug* could potentially cause your code to hang -- by reprogramming
> the "port" to be a GPIO, etc.

The adc registers cannot be reprogrammed as I/O.

Don Y

unread,
Apr 26, 2021, 2:56:35 PM4/26/21
to
Have you heard the mantra "Program Defensively"?

Would you stake your life on that code ALWAYS terminating "in a fixed number
of clock cycles"? (some of us write code that DOES have peoples' lives at
stake).

But, hey, chances are, YOU won't be around to blame when/if it manifests.
And, no one will likely be able to point to THAT as the problem. Sounds
like a great way to avoid designing responsibly!

[And turn off that pesky watchdog, too! The code *can't* fail!]

Ed Lee

unread,
Apr 26, 2021, 3:04:16 PM4/26/21
to
No, but this app is not so life critical anyway. The adc sampling cycles should be clocked by a hardware counter inside the chip. Yes, it could fail, and that mean the chip is marginal. In that case, just throw away the chip, and the board as well.

Don Y

unread,
Apr 26, 2021, 3:26:25 PM4/26/21
to
As I said, you're engaging in excusitis.

I don't know anyone who would hire you with an attitude of rationalizing
away possible sources for latent bugs. Most of us try to make *reliable*
devices that behave in predictable ways (and locking up with no indication
of why -- when such information would have been available -- is not
"predictable")

Good luck!

Lasse Langwadt Christensen

unread,
Apr 26, 2021, 4:11:08 PM4/26/21
to
nonsense

Ed Lee

unread,
Apr 26, 2021, 5:34:50 PM4/26/21
to
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

Lasse Langwadt Christensen

unread,
Apr 26, 2021, 6:05:01 PM4/26/21
to
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

Ed Lee

unread,
Apr 26, 2021, 6:16:27 PM4/26/21
to
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

Ed Lee

unread,
Apr 26, 2021, 6:41:06 PM4/26/21
to
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;

Lasse Langwadt Christensen

unread,
Apr 26, 2021, 6:46:31 PM4/26/21
to
I'm surprised it compiled at all, because it makes no sense

Ed Lee

unread,
Apr 26, 2021, 6:51:38 PM4/26/21
to
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.

anti...@math.uni.wroc.pl

unread,
May 4, 2021, 9:14:23 PM5/4/21
to
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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

> volatile GPIO_t* const pc = (GPIO_t*)0x40020800;

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.

--
Waldek Hebisch
0 new messages