Direct Register Access

Direct Register Access for STM32F407

There are different ways to access the hardware, when you do some low level programming, like in case of micro-controller. They can be (broadly) summarized as: -

1. Assembly language
2. C code with direct register access
3. C code with library functions, such as Cube for STM32

While option-1 is for the mightiest ones, the tribe of people who dare to program in assembly for a 32-bit processor, is elusive. On the other hand, there are numerous advantages while going with option-3, it makes the code portable and also makes the code highly readable. But the disadvantage of going with option-3 is that the programmer never knows what is going on in the HW. Also, there are no standard for library functions, when we move from one manufacturer to other (like from STM32 to NXP or PIC32).
I have a fair experience working on HW level and that is where, I find my comfort. At hardware level, the working of a peripheral (say USART) is same whether we work with STM32 or PIC32. They have similar register (not names, but functionality) and if you are familiar with one architecture, its just a matter of spending some time probing the signals on oscilloscope and figuring our the right setting. Hence, I choose the option-2. Following code shows the comparison of option-2 and option-3.

Using Cube for STM32 for LED ON/ OFF:


  /* Configure LED3 and LED4 */
  BSP_LED_Init(LED3);

typedef enum 
{
  LED4 = 0,
  LED3 = 1,
  LED5 = 2,
  LED6 = 3
} Led_TypeDef;

#define LED3_PIN                         GPIO_PIN_13
#define LED3_GPIO_PORT                   GPIOD
#define LED3_GPIO_CLK_ENABLE()           __HAL_RCC_GPIOD_CLK_ENABLE()  
#define LED3_GPIO_CLK_DISABLE()          __HAL_RCC_GPIOD_CLK_DISABLE() 

While the above code is provided by ST, you have to just use it, that part is simple. But you have to link at least 3 to 4 files to your project and read the documentation of ST to figure our the exact function that you need. At the end, you will get your application running, but you will still not know what is really happening in the hardware.

Using direct register access for STM32 for LED ON/ OFF:


/*
 * Configure LED3 and LED4
 * Enable clock for GPIOD
 * MODE Register - LED PD13
 * MODE Register - LED PD14
 *
 */
#define LED_CONFIG()     \
{          \
   RCC->AHB1ENR |= 8;    \
   GPIOD->MODER |= 0x04000000;  \
   GPIOD->MODER |= 0x10000000;  \
}          \


#define LED13_TOGGLE()     \
{          \
 GPIOD->ODR ^= 0x2000;    \
}          \

#define LED13_ON()      \
{          \
 GPIOD->ODR |= 0x2000;    \
}          \

#define LED13_OFF()      \
{          \
 GPIOD->ODR &= ~0x2000;    \
}          \

#define LED14_TOGGLE()     \
{          \
 GPIOD->ODR ^= 0x4000;    \
}          \


#define LED14_ON()      \
{          \
 GPIOD->ODR |= 0x4000;    \
}          \

#define LED14_OFF()      \
{          \
 GPIOD->ODR &= ~0x4000;    \
}          \

The code is far more simple, you do not need to add any other file, other than:


#include "stm32f4xx.h"

Just to explain the working in following few steps, to switch a GPIO port pin as high or low: -


  1. Enable the clock for the respective peripheral (GPIO).
  2. Make the "Mode" as "Output".
  3. Make the output as "zero" or "one".
Let me know what do you think?

Comments

Popular Posts