Hi,
A bit new to embedded programming. I am trying to trace down where all
the registers (such as pll setting, IO, ...) get updated.
For example, for the STM32F0 processor, below are the code to set system
clock but the codes only have the registers that get modified, but how
the register get updated by the processor? My guess is there is some
type of interrupt mechanism that detects if there is a change in the
internal registers, the interrupt will trigger a subroutine that will
update the registers.
My other question is what part of the linker that associate each of the
internal register to the actual register of the hardware? For example
if you look at the STM32F0 driver file, there are a lot of "structs"
defined for the IO but how are these basically purely C variables get
associated with the actual register?
If you look at the SetSysClock() function below, the "RCC" type is only
a C variables, where does this variable get assign to a hard register in
the processor?
1
/**
2
* @brief Configures the System clock frequency, AHB/APBx prescalers and Flash
3
* settings.
4
* @note This function should be called only once the RCC clock configuration
5
* is reset to the default reset state (done in SystemInit() function).
It is much less complicated than you might think.
All these names like RCC are simply pointers to structures (usually
hidden as preprocessing macros), and the actual elements of these
structures simply are the (IO) registers. All ARM IO registers
are memory-mapped, i.e. they appear to be a part of the normal
address space, but when the processor decodes the respective address,
it does not access SRAM or Flash but triggers a read or write operation
to an IO register.
As a sidenote, it may be worth tracing down the actual declaration and
definition of RCC and other I/O likewise.
The word "trigger" may cause some doubt, whether the controller behaves
in a way which deviates only slightly from what your, Andy, hypothesis
was. (Sorry, Jörg. I say that with all respect). But "trigger" does not
mean the causing of a (sub-)process.
It may be reworded as, "that a certain address, which belongs to an
I/O-register, directs whatever shall be read or written to that
register".
Hope, that this remark is usefull.
Jörg W. wrote:> It is much less complicated than you might think.>> All these names like RCC are simply pointers to structures (usually> hidden as preprocessing macros), and the actual elements of these> structures simply are the (IO) registers. All ARM IO registers> are memory-mapped, i.e. they appear to be a part of the normal> address space, but when the processor decodes the respective address,> it does not access SRAM or Flash but triggers a read or write operation> to an IO register.
Hi Jorg,
Thanks for the reply.
"(usually hidden as preprocessing macros)"
I am using Eclipse CDT. Where can I look into these preprocessing
macros?
For example, here is an excerpt of the IO data structures but these are
only the data structures. How do the macros map these data structures
to the actual registers or memory location?
There has to be some prior knowledge between the compiler and the
STM32F0 IO structure, because these are purely C declare variables. I
assume as you mentioned, the preprocessing macros has some prior
knowledge of these data structure before hand and map these into the
memory accordingly.
Could you point me to where I can read about the preprocessing macros?
Thanks, -Andy
file :stm32f0xx.h
/***********************************************************************
*******/
/*
*/
/* General Purpose IOs (GPIO)
*/
/*
*/
/***********************************************************************
*******/
/******************* Bit definition for GPIO_MODER register
*****************/
#define GPIO_MODER_MODER0 ((uint32_t)0x00000003)
#define GPIO_MODER_MODER0_0 ((uint32_t)0x00000001)
#define GPIO_MODER_MODER0_1 ((uint32_t)0x00000002)
#define GPIO_MODER_MODER1 ((uint32_t)0x0000000C)
#define GPIO_MODER_MODER1_0 ((uint32_t)0x00000004)
#define GPIO_MODER_MODER1_1 ((uint32_t)0x00000008)
#define GPIO_MODER_MODER2 ((uint32_t)0x00000030)
#define GPIO_MODER_MODER2_0 ((uint32_t)0x00000010)
#define GPIO_MODER_MODER2_1 ((uint32_t)0x00000020)
#define GPIO_MODER_MODER3 ((uint32_t)0x000000C0)
Here are the RCC typedefs. These are basically generic C declarations.
There are really nothing unique about them.
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;
Andy V. wrote:> Where can I look into these preprocessing macros?
Sorry, no idea. I've been using some Atmel ARMs so far, and there's
a rather scattered filesystem subtree under a directory name CMSIS
where these macros come from.
Jörg W. wrote:> Andy V. wrote:>> Where can I look into these preprocessing macros?>> Sorry, no idea. I've been using some Atmel ARMs so far, and there's> a rather scattered filesystem subtree under a directory name CMSIS> where these macros come from.
Thanks. I'll try to look into this, but it seems you're right in
general. There seems to be a convention for these hardware related
registers that have to be declared in certain way.
SMSIS stands for: Cortex Microcontroller Software Interface Standard
So it has to do with the compiler, preprocessor parsing these files and
compiler these specifically for the hardware.
Here's a link to CMSIS:
file:///C:/LinuxEmbSrc/STM32F0-Discovery_FW_V1.0.0/Libraries/CMSIS/Docum
entation/CMSIS_Core.htm
Andy V. wrote:> SMSIS stands for: Cortex Microcontroller Software Interface Standard
Yep, but Atmel also deliveres their per-CPU definitions along with
the official CMSIS stuff (which is standardized by ARM), just in a
different directory tree.
Jörg W. wrote:> Andy V. wrote:>> SMSIS stands for: Cortex Microcontroller Software Interface Standard>> Yep, but Atmel also deliveres their per-CPU definitions along with> the official CMSIS stuff (which is standardized by ARM), just in a> different directory tree.
OK, I mean STM32F0 also has its own "drivers" but these drivers
basically calls the functions from CMSIS. By the way, do you happen to
know where to download the Atmel drivers? (I can search ...)
A more complete definition of CMSIS is from Keil website
http://www.keil.com/pack/doc/CMSIS/Driver/html/index.html
I guess all these hardware related "C" variables have to be standardized
otherwise how would the compiler know which is ARM core specifics and
which are user app specific.
The part I am still trying to figure out is when you compile your
program, explicitly where exactly in the GNU_GCC that read in these core
drivers? I mean it has to be somewhere int he GNU_GCC just that I am
not able to find it yet.
Andy V. wrote:> By the way, do you happen to know where to download the Atmel drivers?
Unfortunately, they ship these header (and C) files only as part of
their (several 100 MB fat) Atmel Studio.
Note that I explicitly don't mean anything like a "driver" (that would
be Atmel's ASF) but really simply a processor (rather: MCU) definition.
Example (PIO port):