CMSIS register values - arm

I have just started to explore the CMSIS for ARM controllers. It seems rather convenient to use it, however I was wondering where are the actual register values defined. Let's just take for example the GPIOs.
There is a structure GPIOA_AHB_Type defined with various members. Then, for GPIOB, there is a memory (or register?) address defined, let's say GPIOB_AHB_BASE. Afterwards, a pointer is set to GPIOB_AHB_BASE, like this:
#define GPIOB_AHB ((GPIOA_AHB_Type*) GPIOB_AHB_BASE)
GPIOB_AHB's member variables as GPIOB_AHB->DIR for example, to set it input or output. My question is, where precisely are these member variables initialized? I guess the actual address of the registers is device specific, so I tried to find them in the device specific header, but all I found was the GPIOB_AHB_BASE define and the declaration of the member variables. How does the compiler know that when I type GPIOB_AHB->DIR, I want to write into the register that sets that port's I/O direction?

If you look in your CMSIS header, you'll see all the structure definitions. Here's an example from my current project:
typedef struct
{
__IO uint32_t DATA; /*!< Port A Data Register */
__IO uint32_t CR; /*!< Port A Output Control Register */
__IO uint32_t FR1; /*!< Port A Function Register 1 */
__IO uint32_t FR2; /*!< Port A Function Register 2 */
uint32_t RESERVED0[6];
__IO uint32_t OD; /*!< Port A Open Drain Control Register */
__IO uint32_t PUP; /*!< Port A Pull-up Control Register */
uint32_t RESERVED1[2];
__IO uint32_t IE; /*!< Port A Input Control Register */
} TSB_PA_TypeDef;
Later on, a pointer to a structure of that type is defined:
#define PERI_BASE (0x40000000UL)
#define TSB_PA_BASE (PERI_BASE + 0x00C0000UL)
#define TSB_PA (( TSB_PA_TypeDef *) TSB_PA_BASE)
So that you can use it like:
TSB_PA->CR |= (1U << 2); // make Port A, bit 2 an output
value = TSB_PA->DATA & (1U << 5); // read Port A, bit 5.

Related

How do I fix reference to register is pointing to the wrong one?

I'm trying to use the ADC in STM32 and I want to modify the ISR register so I'm doing ADC->ISR |= <bit>. However when I control-click on ISR it's bringing me to in stm32f0xx/cmsis_boot/core_cm0.h
/** \brief Union type to access the Interrupt Program Status Register (IPSR).
*/
typedef union
{
struct
{
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} IPSR_Type;
I want to be brought to in stm32f0xx/cmsis_boot/stm32f0xx.h:
typedef struct
{
__IO uint32_t ISR; /*!< ADC Interrupt and Status register, Address offset:0x00 */
// other registers here
} ADC_TypeDef;
In my file, I'm not including either of those files so I'm not sure how the linking works. If I try to reference another register in ADC_TypeDef it works but I think because there are 2 ISR it can't find the right one. How do I fix this so that it's referencing the right one? Thanks!

#define statement for address of memory

What does this #define statement do? It is used to define an address of memory. But I don't understand the (uint32_t *) part
#define GPxDAT (uint32_t *) 0x6FC0
It is usually used to access hardware registers mapped into the address space, or some particular memory addresses
Hardware registers should be defined as volatile as registers can change without any program activity (as they are changed by the hardware).
#define GPIOREGA ((volatile uint32_t *) 0x6FC0)
then you can assign or read this memory location (*GPIOREGA = something; something = *GPIOREGA )
Sometimes much more complex data structures are used this way (example from the STM32 headers)
#define __IO volatile
typedef struct
{
__IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */
__IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */
__IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */
__IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */
__IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */
__IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */
__IO uint32_t BSRR; /*!< GPIO port bit set/reset register, Address offset: 0x18 */
__IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */
__IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */
} GPIO_TypeDef;
#define PERIPH_BASE 0x40000000U /*!< Peripheral base address in the alias region */
#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000U)
#define GPIOA_BASE (AHB1PERIPH_BASE + 0x0000U)
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
And you can use it is as any normal pointer
GPIOA -> MODER |= (1 << 15);
The (uint32_t *) part is what is called a cast, it converts the integer number 0x6FC0 to a pointer(an address) to an unsigned integer, 32bits wide (which is what the uint32_t type represents.) Basically a type conversion to a pointer to an unsigned integer. In my opinion, the expression is not completely safe. While the cast operator is high precedence, it should be written as:
#define GPxDAT ((uint32_t *) 0x6FC0)
rounding the whole expression in parenthesis, so it will not fail, wherever you put it.
Writing this kind of defines, you can access GPxDAT[0] as a 32bit unsigned integer at the address 0x6fc0, GPxDAT[1] as the next 32bit address (above the previous one) all of them based at the address represented by the number.

CMSIS - Peripheral Definitions - Structs With Unions Syntax?

I've moving over from 8 bit bare-metal registers, and having to learn some new C Kungfu to wrap my head around the CMSIS Core approach.
I have a snippet of code here from a Peripheral Access Layer from a ARM Cortex M vendor. They create this SN_WDT_TYPE structure, which you can use to set watch-dog timer registers using their notation.
Why do they use the unions? I haven't seen this kind of syntax before.
If you use unions to create structures like that, do you they go several layers deep with pointers? Memory management with the unions? Is there some C syntax thing I'm missing here?
This might be CMSIS specific, does anyone know what the ": 1" is doing in those struct declarations...? I know the __IO ties back to some CMSIS definition of read/write.
HELPFUL STUFF I FOUND AFTER COMMENTS & ANSWERS:
ARM'S CMSCIS PERIPHERAL NAMING CONVENTION -- This example code doesn't seem to confirm too gracefully...
ARM'S BITFIELD COMPILER NOTES ON STRUCTS & UNIONS
/**
* #brief Watchdog Timer (SN_WDT)
*/
typedef struct { /*!< SN_WDT Structure */
union {
__IO uint32_t CFG; /*!< Offset:0x00 WDT Configuration Register */
struct {
__IO uint32_t WDTEN : 1; /*!< WDT enable */
__IO uint32_t WDTIE : 1; /*!< WDT interrupt enable */
__IO uint32_t WDTINT : 1; /*!< WDT interrupt flag */
uint32_t : 13;
__O uint32_t WDKEY : 16; /*!< Watchdog register key */
} CFG_b; /*!< BitSize */
};
union {
__IO uint32_t CLKSOURCE; /*!< Offset:0x04 WDT Clock Source Register */
struct {
__IO uint32_t CLKSOURCE : 2; /*!< WDT clock source */
uint32_t : 14;
__O uint32_t WDKEY : 16; /*!< Watchdog register key */
} CLKSOURCE_b; /*!< BitSize */
};
union {
__IO uint32_t TC; /*!< Offset:0x08 WDT Timer Constant Register */
struct {
__IO uint32_t TC : 8; /*!< Watchdog timer constant reload value */
uint32_t : 8;
__O uint32_t WDKEY : 16; /*!< Watchdog register key */
} TC_b; /*!< BitSize */
};
union {
__O uint32_t FEED; /*!< Offset:0x0C WDT Feed Register */
struct {
__O uint32_t FV : 16; /*!< Watchdog feed value */
__O uint32_t WDKEY : 16; /*!< Watchdog register key */
} FEED_b; /*!< BitSize */
};
} SN_WDT_Type;
The union allows you to access the hardware register as either a 32 bit word or as the bit fields contained in the register. Both representations have their uses. Perhaps you are missing the bit field syntax as it is not used in most application level coding. Bit field layout is compiler specific, but CMSIS headers are built to work with the intended compilers.

How to access struct fields pointers inside another struct and write correctly?

I have the following structs (from a library I'm using) with some fields and I would like to assign with OR operation a new value. But I'm debugging and I can't see how anything is writing there in stm32l4xx_hal_tim.c file:
typedef struct
{
TIM_TypeDef *Instance; /*!< Register base address */
TIM_Base_InitTypeDef Init; /*!< TIM Time Base required parameters */
HAL_TIM_ActiveChannel Channel; /*!< Active channel */
DMA_HandleTypeDef *hdma[7]; /*!< DMA Handlers array This array is accessed by a #ref DMA_Handle_index */
HAL_LockTypeDef Lock; /*!< Locking object */
__IO HAL_TIM_StateTypeDef State; /*!< TIM operation state */
}TIM_HandleTypeDef;
typedef struct
{
__IO uint32_t CR1; /*!< TIM control register 1, Address offset: 0x00 */
__IO uint32_t CR2; /*!< TIM control register 2, Address offset: 0x04 */
__IO uint32_t SMCR; /*!< TIM slave mode control register, Address offset: 0x08 */
__IO uint32_t DIER; /*!< TIM DMA/interrupt enable register, Address offset: 0x0C */
__IO uint32_t SR; /*!< TIM status register, Address offset: 0x10 */
__IO uint32_t EGR; /*!< TIM event generation register, Address offset: 0x14 */
__IO uint32_t CCMR1; /*!< TIM capture/compare mode register 1, Address offset: 0x18 */
__IO uint32_t CCMR2; /*!< TIM capture/compare mode register 2, Address offset: 0x1C */
__IO uint32_t CCER; /*!< TIM capture/compare enable register, Address offset: 0x20 */
__IO uint32_t CNT; /*!< TIM counter register,
} TIM_TypeDef;
I have a part of code where I defined: TIM_HandleTypeDef TIMER_Struct;
And I would like to access the field "CR1" of TIM_TypeDef struct that is "*Instance" field of TIM_HandleTypeDef. So I have done it by this way in a function DRV_TIMER_init():
#include "main.h"
#include "stm32l4xx_hal_tim.h"
uint32_t uwPrescalerValue = 0;
TIM_HandleTypeDef TIMER_Struct;
void DRV_TIMER_init(void);
int main(void)
{
DRV_TIMER_init();
while(1)
{
}
}
//where uint32_t SystemCoreClock = 4000000; in other system source file.
void DRV_TIMER_init(void)
{
uwPrescalerValue = (uint32_t)(SystemCoreClock / 1000000) - 1;
TIMER_Struct.Init.Period = 100 - 1;
TIMER_Struct.Init.Prescaler = uwPrescalerValue;
TIMER_Struct.Init.ClockDivision = 0; // these accesses work
TIMER_Struct.Instance -> CR1 |= 0x01 << 3; // this no works
}
Even if I write directly:
TIMER_Struct.Instance -> CR1 = 0xFFFFFFFF;
It stills without having effect.
I think It could be a fact that I'm not controlling appropiately the pointer access or similar. But I don't see how can I access and modify the content of the commented field. Since I can see (debug mode) how the rest of struct fields updates are writen correctly.
Any correction suggested here?
TIMER_Struct.Instance -> CR1 = 0xFFFFFFFF;
I try different ways to get it with no success. I need new ideas.
TIM_TypeDef *Instance;
is just a pointer which is not pointing to anywhere so you can't dereference it
you have defined somewhere in the lib a macro like this:
#define TIM (TIM_TypeDef*)0xDEADBEEF;
this is how you map the registers to the memory
try modifying your code like this:
TIMER_Struct.Instance = (TIM_Typedef*)0xDEADBEEF;
or just
TIMER_Struct.Instance = TIM;
than
TIMER_Struct.Instance -> CR1 |= 0x01 << 3;
should work
I think you forgot to define TIMER_Struct.Instance
TIM_HandleTypeDef TIMER_Struct;
TIMER_Struct.Instance = TIM1;
//Now you can access TIMER_Struct.Instance
TIMER_Struct.Instance->CR1 = (uint32_t)0xFFFFFFFF;
But I prefer to use CMSIS for writing to registers. No need for the HAL. With CMSIS writing to a register could look like:
TIM1->CR1=(uint32_t)0xFFFFFFFF
I have found the solution. First you must enable the peripheral clock. If not, there won't be any effect over timer registers, because the pointer structs fields were pointing directly to the hardware registers allocation. This was the cause why I can't see any update when watching my struct var at debugging.
I was enabling clk (with hal_xxx_init()) after writing to the allocation. That was my mistake.
Here in this part of code is the correction:
//where uint32_t SystemCoreClock = 4000000; in other system source file.
void DRV_TIMER_init(void)
{
uwPrescalerValue = (uint32_t)(SystemCoreClock / 1000000) - 1;
TIMER_Struct.Init.Period = 100 - 1;
TIMER_Struct.Init.Prescaler = uwPrescalerValue;
TIMER_Struct.Init.ClockDivision = 0; // these accesses work
if (HAL_TIM_Base_Init(&TIMER_Struct) != HAL_OK)
{
/* Initialization Error */
TIM_Error_Handler();
}
TIMER_Struct.Instance -> CR1 |= 0x01 << 3; // this works now
}
If you try to put the last sentence before the:
HAL_TIM_Base_Init(&TIMER_Struct);
no
TIMER_Struct.Instance -> CR1 = xxx; //write mode register acces
will have effect.

Peripheral definition

Could someone please explain the following construction to a beginner:
typedef struct
{
__IO uint32_t CTRL; /**< Control Register */
__IO uint32_t CNT; /**< Counter Value Register */
__IO uint32_t COMP0; /**< Compare Value Register 0 */
__IO uint32_t COMP1; /**< Compare Value Register 1 */
__I uint32_t IF; /**< Interrupt Flag Register */
__IO uint32_t IFS; /**< Interrupt Flag Set Register */
__IO uint32_t IFC; /**< Interrupt Flag Clear Register */
__IO uint32_t IEN; /**< Interrupt Enable Register */
__IO uint32_t FREEZE; /**< Freeze Register */
__I uint32_t SYNCBUSY; /**< Synchronization Busy Register */
} RTC_TypeDef;
#define RTC_BASE (0x40080000UL)
#define RTC ((RTC_TypeDef *) RTC_BASE)
especially the last line
Why are the brackets so unusual? What does the * mean? Pointer or multiply operator ?
Thanks
Why are the brackets so unusual? What does the * mean? Pointer or
multiply operator ?
* here is a pointer not multiplication operator.
There is nothing unusual here about the macro. It is just type casting the address to be of type struct RTC_TypeDef
Whenever you will encounter a single or multiple * after a datatype (even a user defined datatype), its a pointer.
What you are calling a constructions:
typedef struct
{
__IO uint32_t CTRL; /**< Control Register */
__IO uint32_t CNT; /**< Counter Value Register */
__IO uint32_t COMP0; /**< Compare Value Register 0 */
__IO uint32_t COMP1; /**< Compare Value Register 1 */
__I uint32_t IF; /**< Interrupt Flag Register */
__IO uint32_t IFS; /**< Interrupt Flag Set Register */
__IO uint32_t IFC; /**< Interrupt Flag Clear Register */
__IO uint32_t IEN; /**< Interrupt Enable Register */
__IO uint32_t FREEZE; /**< Freeze Register */
__I uint32_t SYNCBUSY; /**< Synchronization Busy Register */
} RTC_TypeDef;
is a structure and programmatically called a struct, a user-defined datatype. struct is keyword in C. And so is typedef. To keep it simple as of now, I'll say, typedef here is specifically used to have the convenience to write RTC_TypeDef; instead of having the need to write struct stRTC for example.
RTC_BASE is a macro. So, before compilation pre-processor will replace RTC_BASE with the value (0x40080000UL), again, it is for convenience and readability.
This last line:
#define RTC ((RTC_TypeDef *) RTC_BASE)
also is a macro defined. Which is nothing but a pointer of the RTC_Typedef type, pointing to whatever is located at the address (0x40080000UL)
So, before the compilation the pre-processor will replace all instances of RTC with ((RTC_TypeDef *)0x40080000UL).
If you increment RTC pointer, it will increment by sizeof(RTC_Typedef).
The structure definition is pretty straight forward, variables are encapsulated in a structure. That structure can then be referenced as RTC_TypeDef because you use typedef.
typedef struct
{
__IO uint32_t CTRL; /**< Control Register */
__IO uint32_t CNT; /**< Counter Value Register */
__IO uint32_t COMP0; /**< Compare Value Register 0 */
__IO uint32_t COMP1; /**< Compare Value Register 1 */
__I uint32_t IF; /**< Interrupt Flag Register */
__IO uint32_t IFS; /**< Interrupt Flag Set Register */
__IO uint32_t IFC; /**< Interrupt Flag Clear Register */
__IO uint32_t IEN; /**< Interrupt Enable Register */
__IO uint32_t FREEZE; /**< Freeze Register */
__I uint32_t SYNCBUSY; /**< Synchronization Busy Register */
} RTC_TypeDef; /** #} */
The following line means every time you write RTC_BASE, the compiler will replace that line with (0x40080000UL)
#define RTC_BASE (0x40080000UL)
And finally, the following line can be broken into two parts:
(RTB_TypeDef *)RTC_BASE
Which means (RTB_TypeDef *)(0x40080000UL) - basically tells the compiler to treat memory address 0x40080000UL as a pointer to RTB_TypeDef
and the extra parenthesis are there to denote a single variable as a compund expression RTC.
From that point on, whenever the compiler sees RTC, it will replace it with (RTB_TypeDef *)(0x40080000UL), basically a convenient way to mark the beginning of this structure in memory

Resources