Author Topic: STM32F030 Bare metal - finding answers on documentation  (Read 2827 times)

0 Members and 1 Guest are viewing this topic.

Offline anso-engineerTopic starter

  • Regular Contributor
  • *
  • Posts: 103
  • Country: ua
STM32F030 Bare metal - finding answers on documentation
« on: April 22, 2026, 02:52:20 pm »
Hello, I plan to beless addicted on HAL Library, and more concentrate on the bare metal.

Some tutorials uses already predefined structs, but it's good to understand the concepts. I work with STM32F030, so most of my questions and notes are dedicated to these materials:

1) For a letting periptherial acces clock we need to allow throug the AHB2, as I found it handles GPIO peripherials
2) For the GPIOAEN register we need to set, it has offset 0x14. From where all these offsets count? From the upper partent element?
3) Why this Reset values is 0x0000 0014?
 

Offline Pseudobyte

  • Frequent Contributor
  • **
  • Posts: 358
  • Country: us
  • Embedded Systems Engineer / PCB Designer
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #1 on: April 22, 2026, 03:18:29 pm »
1) Clock gating is common for microcontrollers as a way to save power. So by default most peripherals are disabled via them having no clock/enable signal.
2) If you look at the definitions in the header file for the microcontroller you will see where these offsets from the datasheet are used. But yes it is counting from the base peripheral address for RCC example.
Code: [Select]
#define RCC_BASE              (AHBPERIPH_BASE + 0x00001000UL)

typedef struct
{
  __IO uint32_t CR;            /*!< RCC clock control register,                                   Address offset: 0x00 */
  __IO uint32_t CFGR;       /*!< RCC clock configuration register,                            Address offset: 0x04 */
  __IO uint32_t CIR;        /*!< RCC clock interrupt register,                                Address offset: 0x08 */
  __IO uint32_t APB2RSTR;   /*!< RCC APB2 peripheral reset register,                          Address offset: 0x0C */
  __IO uint32_t APB1RSTR;   /*!< RCC APB1 peripheral reset register,                          Address offset: 0x10 */
  __IO uint32_t AHBENR;     /*!< RCC AHB peripheral clock register,                           Address offset: 0x14 */
  __IO uint32_t APB2ENR;    /*!< RCC APB2 peripheral clock enable register,                   Address offset: 0x18 */
  __IO uint32_t APB1ENR;    /*!< RCC APB1 peripheral clock enable register,                   Address offset: 0x1C */
  __IO uint32_t BDCR;       /*!< RCC Backup domain control register,                          Address offset: 0x20 */
  __IO uint32_t CSR;        /*!< RCC clock control & status register,                         Address offset: 0x24 */
  __IO uint32_t AHBRSTR;    /*!< RCC AHB peripheral reset register,                           Address offset: 0x28 */
  __IO uint32_t CFGR2;      /*!< RCC clock configuration register 2,                          Address offset: 0x2C */
  __IO uint32_t CFGR3;      /*!< RCC clock configuration register 3,                          Address offset: 0x30 */
  __IO uint32_t CR2;        /*!< RCC clock control register 2,                                Address offset: 0x34 */
} RCC_TypeDef;

#define RCC                 ((RCC_TypeDef *) RCC_BASE)

3) The reset value is 0x14 so that SRAM and FILTF are enabled by default.

I would recommend you use the corresponding device header file even if you are not using the HAL.
“They Don’t Think It Be Like It Is, But It Do”
 
The following users thanked this post: thm_w, anso-engineer

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4641
  • Country: us
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #2 on: April 22, 2026, 08:23:59 pm »
Quote
From where all these offsets count?
From the start of the "peripheral" being discussed.  In this case, the "RCC" "Reset and Clock Control" peripheral, documented elsewhere in the manual as being located at 0x40021000...

I would caution that ignoring the pre-defined symbols and structures goes way beyond "bare metal programming."  Avoiding libraries is one thing, but re-defining your own symbols for each peripheal is getting pretty close to "silly."  (although I guess it's unfortunate that getting those .h files seems to involved downloaded very large packages including other stuff.  Sigh.)
I guess it does require some familiarity with how a C compiler deals with structures (very efficiently. usually!)

(Back when we were talking about programming STM32F103s in assembly language with minimal downloads (https://www.eevblog.com/forum/microcontrollers/one-dollar-one-minute-arm-development/ ), I went so far as to translate the .h files into assembler-friendly formats ( https://github.com/WestfW/Minimal-ARM ) )
 
The following users thanked this post: anso-engineer

Offline voltsandjolts

  • Supporter
  • ****
  • Posts: 3752
  • Country: gb
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #3 on: April 22, 2026, 08:31:17 pm »
 
The following users thanked this post: thm_w

Offline cv007

  • Super Contributor
  • ***
  • Posts: 1061
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #4 on: April 23, 2026, 06:29:01 am »
Quote
but re-defining your own symbols for each peripheal is getting pretty close to "silly."
Its not that silly. For starters, there is usually a limited set of peripherals needed for each project so there is usually no need to create the whole set at once so they get created as needed. These peripheral register structs are not that complicated or difficult to create, although there is potential for errors so static asserting the size is a good idea.

When you spend a little bit of time creating the register struct you are forced to read the datasheet and will be a little more familiar with the peripheral so this time will not be wasted. Having the peripheral register struct in the same file as the peripheral code means you will not have to spend time going on a treasure hunt with the manufacturer's headers which will inevitably require you to lookup the meaning of various defines. In theory you shouldn't have to lookup the header names as the datasheet register names should match (assuming you already know how to access the base peripheral), but I'm not using any datasheet register struct names without looking them up first in the header/code to make sure they match, including my own code (at least for the first register access of a particular name).

Another advantage is you can code to what suits your style instead of always having to bend to some manufacturer's scheme, which will be at least slightly different among manufacturers. So in the end you can have the same scheme for every mcu you use where there is now consistency. I do this with avr (new series) and cortex-m. The code ends up looking very similar.

I would put any other needed values related to the peripheral in the same category- create as needed, located where they will be used. For example, there is no real need to have a thousand defines for every bit/bitfield position and bitmask. Just create enums as needed to do what is needed, and they can be 'local' to the peripheral code when no one else has a need to use them. Using C++ will be a little nicer for this as you can have these local/private enums in header files without the need for extended naming to prevent collisions.

This does not mean you shouldn't use manufacture's headers, it just means that they are not that special. Some mcu's I wouldn't even bother creating my own driver/header code (Pi RP), others are either so simple (avr) or the manufacturer provided code is horrible enough where it is easier to go off on your own.

Here is an example for an stm32g0, which uses no manufacturers headers-
https://godbolt.org/z/rr7WeEhrG
(and this also means I can use the online compiler to create code, as I would otherwise have to get the manufacturers headers in place first- not an easy job as you will end up with a lot of headers to deal with as there is usually a lot of needed includes within the headers)

You will note this code does not require me to handle all the little details- the gpio class can handle dealing with rcc to enable a port, the uart takes care of dealing with the baud register based on the current clock speed (which the rcc has), and so on. There is also the ability to name register/var types as atomic (cortex-m0 has no atomic instructions) so in some cases 'shared' registers can be atomic type so RMW access is protected.

For stm32 I use the gcc arm compiler, and use a relatively simple makefile. So a code editor (vscode), creating my own code, compile/program via command line, and debugging via uart.



The bottom line is you have registers that need to be accessed using what is available from the programming language. If you at least spend a little time without any help in the form of manufacturers headers, you can start to understand what it takes and will realize there is more than one way to get this done. You will become better in the use of the language and will also understand manufacturers headers more easily. Using defines is also not a requirement, and I would avoid using them to get a better idea of what the the language can do without the use of them.

simple examples of a simple peripheral, using C and C++
https://godbolt.org/z/4h5rahc1b
https://godbolt.org/z/b8jhK6f1n

They both do the same job, but in the case of C when using both h (header) and c (source) files you will typically end up with the 'public' functions as called functions. There are ways to make the C version produce the same output as the C++ version, but am just demonstrating typical C usage and my typical C++ usage (headers only).

There are many ways to do the same thing and I showed one way. Now, every peripheral you have can follow a similar recipe and you just scale to various levels depending on how many registers the peripheral has and how many functions you need.
 
The following users thanked this post: anso-engineer

Offline Simon

  • Global Moderator
  • *****
  • Posts: 18887
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #5 on: April 23, 2026, 06:49:16 am »
I mainly use the manufacturers header files. For microchip parts you can download the device pack files which are basically zip files with a different exstension.

Unfortunately there has been this move which I gather is recommended by ARM to not have bit fielded structures for the registers. I very much prefered using bit fields although you have to pay attention and sometimes learn through trial and error that some registers prefer to be written all in one go and you should do that if you want to save time and code space but I don't see an issue for code used to set something up once if it simplifies things. So I use a mix of older header files with bit fields (as well as full register access fields) and the now standard header files that just declare registers as uint8_t, uint16_t and uint32_t.

What makes the non bit fielded definitions harder to work with is that I am forever searching the header files for the over the top #defines for the bits, using these still requires caution as it is still just masks.
 

Offline cv007

  • Super Contributor
  • ***
  • Posts: 1061
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #6 on: April 23, 2026, 08:01:52 am »
Quote
I very much prefered using bit fields
I used to like them, but they obfuscate what is actually happening and you can easily miss that a rmw is taking place which you will not notice until it reveals itself- most likely after the mcu is put to use in the form of some odd bug taking place very infrequently. Without the bitfields it also becomes simpler to deal with setting register values that span multiple bitfields rather than have a separate line of code for each bitfield access. You have one way to access a single whole register instead of multiple ways (and there are various ways to create these bitfields which can have different naming schemes).


here is the previous c++ example modified to use a register bitfield-
https://godbolt.org/z/nM4Gc1vWe

Now, the only difference to you is the one time you had to create the
reg_.CTRLA or_eq ONbm;
as opposed to the one time you created
reg_.CTRLA.ON = 1;

In both cases, you spent about the same time creating them, and the added enum for the named bitmask is pretty simple and very little time is spent on it (you do not have to search the thousands of defines, you have the datasheet open so simply created an enum so you have a friendly name to use and it will be located by your code). You will also notice that the or_eq is a rmw which may or may not be important, but in the other case you will simply see an assignment and not notice the rmw.

Your functions are the ones that get used repeatedly, and register access inside of peripheral functions are not going to see many changes.

An example where bitfields create a mess-
https://raw.githubusercontent.com/renesas/fsp/refs/heads/master/ra/fsp/src/bsp/cmsis/Device/RENESAS/Include/R7FA4M1AB.h
over 20000 lines of header and most of it is unreadable
 

Offline Simon

  • Global Moderator
  • *****
  • Posts: 18887
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #7 on: April 23, 2026, 08:43:15 am »
Try looking at any microchip header file set. It's a massive list of defines. Every field has several: its mask, it's position, values for it written such that it's really clear what they are but now so long your code is unreadable, a definition function for placing the value into the location but ignoring the fact that this will only work if the field is empty as you normally are doing |=. You need &= of inverted stuff to clear bits and soon you have more than your knickers in a twist.

|= and &= are still read modify write operations. you will always do RMW operations like a bit field access is. set/clear registers are the only other way.
Yes if I am putting multiple values into a register I will do it with a whole register write with all of the values at once but it is nice to have the choice.

in code you may want to enable or disable something, and then you have to check the sync register where while ( register_name.bit == 1) becomes:

while ((stupidly_long_register_name & stupidly_long_bit_field_mask_with_register_name) == stupidly_long_bit_field_mask_with_register_name)

And none of that fits on the screen in one line and it hard to read back.



I read in a book that you can use the bit banding instructions ARM has on some CPU types but that is a whole load of work setting up pointers to the 32 bit location that represents each bit of each register so I guess no one bothers.
 

Offline Jeroen3

  • Super Contributor
  • ***
  • Posts: 4564
  • Country: nl
  • Embedded Engineer
    • jeroen3.nl
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #8 on: April 23, 2026, 09:17:46 am »
Does ST still offer the LL HAL (low level hal)?

This is basically little snippets in macro's that operate peripherals such that you do not have to worry about RCC offsets.
But also not have to use those device structs the full HAL wants you to use as a emulated of "object oriented" programming for C.
 

Offline Karel

  • Super Contributor
  • ***
  • Posts: 2539
  • Country: 00
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #9 on: April 23, 2026, 12:11:49 pm »
I read in a book that you can use the bit banding instructions ARM has on some CPU types but that is a whole load of work setting up pointers to the 32 bit location that represents each bit of each register so I guess no one bothers.

I use it regularly and it's quiet easy to use once you have declared a couple of macros in some (global) header file:

Code: [Select]
#define set_bit_pbb(ADDRESS, BIT) (*(volatile unsigned int *) (PERIPH_BB_BASE + ((((unsigned int)ADDRESS) - PERIPH_BASE) << 5) + ((BIT) << 2)) = 1)
#define clear_bit_pbb(ADDRESS, BIT) (*(volatile unsigned int *) (PERIPH_BB_BASE + ((((unsigned int)ADDRESS) - PERIPH_BASE) << 5) + ((BIT) << 2)) = 0)
#define test_bit_pbb(ADDRESS, BIT) (*(volatile unsigned int *) (PERIPH_BB_BASE + ((((unsigned int)ADDRESS) - PERIPH_BASE) << 5) + ((BIT) << 2)))

Now you can write something like:

Code: [Select]
set_bit_pbb(&DMA1_Channel5->CCR, DMA_CCR_EN_Pos);  /* enable DMA channel */

Pay attention though that there's at least one peripheral that does not support bit banding, e.g. the ADC peripheral.


 

Offline Simon

  • Global Moderator
  • *****
  • Posts: 18887
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #10 on: April 23, 2026, 12:30:18 pm »
Does ST still offer the LL HAL (low level hal)?

This is basically little snippets in macro's that operate peripherals such that you do not have to worry about RCC offsets.
But also not have to use those device structs the full HAL wants you to use as a emulated of "object oriented" programming for C.


I really don't get the desperate cling to C to the point that people use object oriented programming in C rather than just write in object oriented C AKA C++..... So much easier and clearer to others what the cost is - oh I forgot, the art of programming is to write stuff in such an obfuscated way that no one else can understand it.
 
The following users thanked this post: Jeroen3

Offline Karel

  • Super Contributor
  • ***
  • Posts: 2539
  • Country: 00
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #11 on: April 23, 2026, 12:39:59 pm »
I really don't get the desperate cling to C to the point that people use object oriented programming in C rather than just write in object oriented C AKA C++.....

I guess it's personal but I don't like C++. Don't get me wrong, it has some good things like parameter overloading.
But overal I find it too complex and the compile times are huge compared to C.
I do use C++ when writing GUI using Qt and still, all parts of the program that doesn't interact directly with the Qt framework I write in plain C.
 

Offline Jeroen3

  • Super Contributor
  • ***
  • Posts: 4564
  • Country: nl
  • Embedded Engineer
    • jeroen3.nl
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #12 on: April 23, 2026, 01:16:29 pm »
It's true some syntax in C++ is literally against you.

If compile times are slower your dependencies are not separated correctly. Refer to the SOLID principles.

 

Online Psi

  • Super Contributor
  • ***
  • Posts: 12597
  • Country: nz
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #13 on: April 23, 2026, 01:22:57 pm »
Probably not relevant for what you're doing but just FYI STM32F030 cant do USB and CAN at the same time.
It's a bit of a trap as it's not that obvious.
The STM32F072 can do it.
Greek letter 'Psi' (not Pounds per Square Inch)
 

Offline Simon

  • Global Moderator
  • *****
  • Posts: 18887
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #14 on: April 23, 2026, 04:12:22 pm »
Just because you use the C++ compiler does not mean to say you have to find a use for every part of the language. I use it as bare metal programming for the object oriented part that is written in a consistent way with a better compiler.
 

Offline Unixon

  • Frequent Contributor
  • **
  • Posts: 761
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #15 on: April 23, 2026, 04:23:16 pm »
Hello, I plan to beless addicted on HAL Library, and more concentrate on the bare metal.
You may want to try LibOpenCM3 ( https://github.com/libopencm3/libopencm3 ) as a lightweight alternative to HAL.
 

Offline cv007

  • Super Contributor
  • ***
  • Posts: 1061
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #16 on: April 23, 2026, 05:20:06 pm »
Quote
I read in a book that you can use the bit banding instructions ARM has on some CPU types but that is a whole load of work setting up pointers to the 32 bit location that represents each bit of each register so I guess no one bothers.
Silabs gives most of its peripherals 'bit access' registers- a set/clr/tgl version of each register at offset 0x1000/0x2000/0x3000, which is a lot 'cleaner' to deal with than bit banding. Its nice to be able to deal with bitfields without affecting other bits in the register (your target bitfield may have an intermediate state if doing clr+set, but other bits in the register will not). They also do not have a lot of combining of bitfields into a single register, which limits the need for the set/clr/tgl registers as simple assignment for a register is quite common. The pic32 mips also has set/clr/tgl registers and is probably more useful in that case since they put more bitfields into a single register.

class S { //efr32/efm32
struct Reg { uint32_t CTRLA, CTRLB; };
enum { BASE = 0x5000'0000 };
static inline Reg& reg_{ *reinterpret_cast<Reg*>(BASE) };
static inline Reg& regSet_{ *reinterpret_cast<Reg*>(BASE +0x1000) };
static inline Reg& regClr_{ *reinterpret_cast<Reg*>(BASE +0x2000) };
static inline Reg& regTgl_{ *reinterpret_cast<Reg*>(BASE +0x3000) };
enum { SPEEDbp = 2, SPEEDbm = 7<<SPEEDbp }; //SPEED bitfield- 3bits [4:2]
public:
enum SPEED { LOW, MEDIUM, HIGH };
//note C++ will not let you use any argument other than a SPEED enum value, so we already have argument validation at compile time here
auto setSpeed(SPEED s){ regClr_.CTRLB = SPEEDbm; regSet_.CTRLB = s<<SPEEDbp; } //SPEED bitfield has an intermediate state, other bits do not
};


Quote
Try looking at any microchip header file set. It's a massive list of defines.
Most manufacturers seem to have a competition to see who can create the most defines. They end up with so many define names that are similar that it becomes quite easy to use the wrong one. There is no mechanism to make sure you are using the right one, except to create more defines/macros which will be asserted to see if the define value you are using is at least something that looks valid.
 

Offline Simon

  • Global Moderator
  • *****
  • Posts: 18887
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #17 on: April 23, 2026, 06:21:16 pm »
They have the whole set of flag masks for the interrupt status register, the interrupt set register and the interrupt clear register, so 3 identical copies of masks for the same layout because they are 3 registers.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4641
  • Country: us
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #18 on: April 24, 2026, 06:07:35 am »
Quote
I read in a book that you can use the bit banding instructions ARM has on some CPU types
Bit banding was present on some early CM3 ARMs, but seems to be mostly gone these days.  Rumor had it that it doesn't play well with caching and slow buses.  And it got poor support in libraries.

NXP/Freescale/Kinetis had/has an expanded form of bitfield processing that works similar to bit-banding, but also supports multi-bit fields.  (The "Bit Manipulation Engine" or BME)

They're both (IMO) examples of features that needed to be implemented more widely before they'd really catch on.  No one wants to write code that looks like straightforward C code, only to have it mysteriously fail if you have to switch vendors.
(We could have had genuine arrays of single bits, in C, using bit banding.  Might have been interesting.)

The existance of set/clear/toggle registers within individual peripherals is much more common.
 

Offline Simon

  • Global Moderator
  • *****
  • Posts: 18887
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #19 on: April 24, 2026, 07:43:14 am »
Oh so even though the first 500MB of memory space is bit banded this still has to be implemented by the vendor?

I don't know if this is one of these things that has a simple solution and unless a device is bit addressed which none never will be the only way to access data is at the byte level which will still not help sub bye fields in registers. Many registers are byte addressable, so say you needed to do 8 bit parallel communication, it could be done with single cycle access and no RMW on a SAM based device.
 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1906
  • Country: se
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #20 on: April 24, 2026, 07:54:07 am »
The existance of set/clear/toggle registers within individual peripherals is much more common.
As for Silabs, this is also implemented by RP2040 and RP2350:
Quote from:  either RP2040 or RP2350 datasheet
Each peripheral register block is allocated 4 kB of address space, with registers accessed using one of 4 methods,selected by address decode.
• Addr + 0x0000 : normal read write access
• Addr + 0x1000 : atomic XOR on write
• Addr + 0x2000 : atomic bitmask set on write
• Addr + 0x3000 : atomic bitmask clear on write

Much better than bit banding, IMO, allowing multi bit atomic changes to registers.

Oh so even though the first 500MB of memory space is bit banded this still has to be implemented by the vendor?
Yes, it was on optional feature for M4 and M3 but already removed in M7, so, as a matter of fact short lived and creating portability problems:
Quote from: Arm Cortex-M7 Processor Technical Reference Manual r1p2
Code designed for the Cortex-M3 and Cortex-M4 processors is compatible with the Cortex-M7 processor as long as it does not rely on bit-banding.
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4641
  • Country: us
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #21 on: April 24, 2026, 07:35:44 pm »
Quote
Oh so even though the first 500MB of memory space is bit banded this still has to be implemented by the vendor?
It's an ARM-V7M "optional" feature; vendors can include it in their product, or not.  I don't think they have to actually do anything else to "implement" it.
And it wasn't "500MB of memory space:
Quote
A bit-band region maps each word in a bit-band alias region to a single bit in the bit-band region. The bit-band regions occupy the lowest 1MB of the SRAM and peripheral memory regions.
The memory map has two 32MB alias regions that map to two 1MB bit-band regions:
• accesses to the 32MB SRAM alias region map to the 1MB SRAM bit-band region, as
shown in Table 2-13
• accesses to the 32MB peripheral alias region map to the 1MB peripheral bit-band region, as shown in Table 2-14.
Quote
[peripheral set/clear/toggle registers are] Much better than bit banding IMO

Note that bit-banding included the RAM space as well as the peripherals.
At least, on the chips I've looked at.
« Last Edit: April 24, 2026, 07:50:28 pm by westfw »
 

Offline Jeroen3

  • Super Contributor
  • ***
  • Posts: 4564
  • Country: nl
  • Embedded Engineer
    • jeroen3.nl
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #22 on: April 25, 2026, 04:46:02 pm »
Bit banding is a feature of the core, it is optional. If a chip has it, it is only valid for one of the busses. This gives a pipeline penalty.
It is not available for DMA.

It should not be worth it unless you have really strict timings. Compare bit banding to manually writing optimized assembler sir routines.

If you are going to use it, put it in macro functions so you can replace them if your part does not support it.
 

Offline Karel

  • Super Contributor
  • ***
  • Posts: 2539
  • Country: 00
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #23 on: April 26, 2026, 07:58:57 am »
It is not available for DMA.

What do you mean? Here it works fine with DMA:
Code: [Select]
#define set_bit_pbb(ADDRESS, BIT) (*(volatile unsigned int *) (PERIPH_BB_BASE + ((((unsigned int)ADDRESS) - PERIPH_BASE) << 5) + ((BIT) << 2)) = 1)
#define clear_bit_pbb(ADDRESS, BIT) (*(volatile unsigned int *) (PERIPH_BB_BASE + ((((unsigned int)ADDRESS) - PERIPH_BASE) << 5) + ((BIT) << 2)) = 0)
#define test_bit_pbb(ADDRESS, BIT) (*(volatile unsigned int *) (PERIPH_BB_BASE + ((((unsigned int)ADDRESS) - PERIPH_BASE) << 5) + ((BIT) << 2)))

Code: [Select]
  set_bit_pbb(&DMA1->IFCR, DMA_IFCR_CTCIF3_Pos);  /* clear interrupt flag */

  set_bit_pbb(&DMA1_Channel3->CCR, 0);  /* enable DMA channel */

In the manual is written:
Quote
The Cortex®-M4 memory map includes two bit-band regions. These regions map each word
in an alias region of memory to a bit in a bit-band region of memory. Writing to a word in the
alias region has the same effect as a read-modify-write operation on the targeted bit in the
bit-band region.
In the STM32L41xxx/42xxx/43xxx/44xxx/45xxx/46xxx devices both the peripheral registers
and the SRAM1 are mapped to a bit-band region, so that single bit-band write and read
operations are allowed. The operations are only available for Cortex®-M4 accesses, and not
from other bus masters (for example, DMA).

In my experience, bitbanding the DMA registers works fine. It's the ADC peripheral that doesn't work
with bit banding. Maybe an error in the manual? (talking about the STM32L452 here)
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4641
  • Country: us
Re: STM32F030 Bare metal - finding answers on documentation
« Reply #24 on: April 26, 2026, 09:21:45 am »
Quote
bitbanding the DMA registers works fine
Bit banding the dma registers should work fine.  Trying to use dma to read or write to one of the “bitband regions” is not permitted.

 
The following users thanked this post: Karel


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf