This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

LD Scripts is the best approach for BitBanding with GCC?

I have searched information on Bit-Banding in Cortex-M3 and M4 with the GNU GCC ARM EABI NONE, I have seen basic examples on the internet but none works with GNU GCC also seems that no intention to have such feature implemented.

Can someone tell me if the LD via memory remapping really work? the best approach?

What is the best way?

Parents
  • I am teaching this to my class in Embedded Systems this semester.  We are using System Workbench for STM32 (SW4STM32) which is an Eclipse based IDE that uses GCC as the build toolchain.  Anything done in this environment will work just as well with command line versions of GCC as well.  I am not using LD scripts to do any of this, but rather doing much simpler preprocessor directives that provide the effect that I think you are looking for.

    What I find to be the simplest and most direct way to implement both direct memory-mapped register addressing, as well as bitband access is through a few simple #define statements.  These do not allocate any storage in memory and simply direct the compiler on how to access memory locations with fixed pointer addresses.

    To access any particlular register, a statement of the form:

    #define REGISTER_NAME  (*((volatile uint32_t *) 0x400xxxxx))

    will create a variable name (which is a de-referenced pointer) which allows you to access a uint32_t quantity located at address 0x400xxxxx directly.  Setting or resetting a bit would be done like this:

    REGISTER_NAME |= 0x080;

    REGISTER_NAME &= 0xFFFFFF7F;

    Which will set or reset bit 7 respectively with a mask that will prevent unwanted changes to other bits in the register.

    You can also define a macro similarly to calculate a bitband address that takes as input the register address and the bit number and returns the 32 bit address value in the bitband space.  A call to this macro can be substituted for the absolute address in the above define statement so that in one line (after the bitband macro is defined) you can define a variable name that, when used, will write directly to the correct bitband address corresponding to the bit position and register address of interest.

    The bitband macro for the peripheral bitband space (the 0x40000000 band, if you want the SRAM bitband just change the base addresses appropriately) can be defined as:

    #define BITBAND_PERIPH(addr,bitpos) (((addr - 0x40000000)*32 + bitpos*4) + 0x42000000)

    then BITBAND_PERIPH() can be inserted in place of the address value above, so to create a variable name which, when used, will access the bitband location alias for Bit position 12 in the register located at 0x40020014, you would write:

    #define GPIO_REG_BB (*((volatile uint32_t *) BITBAND_PERIPH(0x40020014, 12))

    Once done, reads and writes to GPIO_REG_BB will access the alias address in the BitBand region for the register and bit position described above.

Reply
  • I am teaching this to my class in Embedded Systems this semester.  We are using System Workbench for STM32 (SW4STM32) which is an Eclipse based IDE that uses GCC as the build toolchain.  Anything done in this environment will work just as well with command line versions of GCC as well.  I am not using LD scripts to do any of this, but rather doing much simpler preprocessor directives that provide the effect that I think you are looking for.

    What I find to be the simplest and most direct way to implement both direct memory-mapped register addressing, as well as bitband access is through a few simple #define statements.  These do not allocate any storage in memory and simply direct the compiler on how to access memory locations with fixed pointer addresses.

    To access any particlular register, a statement of the form:

    #define REGISTER_NAME  (*((volatile uint32_t *) 0x400xxxxx))

    will create a variable name (which is a de-referenced pointer) which allows you to access a uint32_t quantity located at address 0x400xxxxx directly.  Setting or resetting a bit would be done like this:

    REGISTER_NAME |= 0x080;

    REGISTER_NAME &= 0xFFFFFF7F;

    Which will set or reset bit 7 respectively with a mask that will prevent unwanted changes to other bits in the register.

    You can also define a macro similarly to calculate a bitband address that takes as input the register address and the bit number and returns the 32 bit address value in the bitband space.  A call to this macro can be substituted for the absolute address in the above define statement so that in one line (after the bitband macro is defined) you can define a variable name that, when used, will write directly to the correct bitband address corresponding to the bit position and register address of interest.

    The bitband macro for the peripheral bitband space (the 0x40000000 band, if you want the SRAM bitband just change the base addresses appropriately) can be defined as:

    #define BITBAND_PERIPH(addr,bitpos) (((addr - 0x40000000)*32 + bitpos*4) + 0x42000000)

    then BITBAND_PERIPH() can be inserted in place of the address value above, so to create a variable name which, when used, will access the bitband location alias for Bit position 12 in the register located at 0x40020014, you would write:

    #define GPIO_REG_BB (*((volatile uint32_t *) BITBAND_PERIPH(0x40020014, 12))

    Once done, reads and writes to GPIO_REG_BB will access the alias address in the BitBand region for the register and bit position described above.

Children
No data