Repository navigation
Bare metal C Ch06 CMSIS
목표
Ch02의 직접 주소/포인터 방식에서 CMSIS peripheral structure 방식으로 전환한다.
CMSIS는 Cortex-M 기반 MCU software interface를 표준화하는 header/interface 체계다.
Ch02:
#define GPIOB_ODR (*(volatile unsigned int *)0x40020414UL)
Ch06:
GPIOB->ODR
개념적으로 CMSIS는 peripheral register layout을 C structure로 표현한다.
typedef struct
{
volatile uint32_t MODER;
volatile uint32_t OTYPER;
volatile uint32_t OSPEEDR;
volatile uint32_t PUPDR;
volatile uint32_t IDR;
volatile uint32_t ODR;
} GPIO_TypeDef;
그리고 base address에 structure pointer를 연결한다.
항목 | 직접 주소 방식 | CMSIS -- | -- | -- Register 주소 | 직접 계산 | Header에 정의 표현 | *(volatile uint32_t *)... | GPIOB->MODER Bit 이름 | 직접 정의 | ST header에 정의 가독성 | 낮음 | 높음 실제 HW access | 동일 | 동일
CMSIS도 여전히 register 직접 접근이다.
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
은 Ch02의 direct register write와 같은 의미다.
Ch06_cmsis/
├── Src/
│ └── main.c
├── Startup/
│ └── startup_stm32f439zitx.s
├── STM32F439ZITX_FLASH.ld
└── STM32F439ZITX_RAM.ld
공통 startup/linker/syscalls는 Ch04에서 다뤘으므로 Chapter 기능 코드인 main.c를 아래에 전부 기록한다.
/*
* Ch06 - The Common Microcontroller Software Interface Standard (CMSIS)
*/
#include "stm32f4xx.h" /* STM32F439xx 매크로에 따라 stm32f439xx.h를 자동 포함 */
#define LD1_PIN (1UL << 0) /* PB0 = LD1 (녹색) */
static void delay(volatile unsigned int count)
{
while (count--) { __NOP(); }
}
int main(void)
{
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
GPIOB->MODER &= ~(0x3UL << (0 * 2));
GPIOB->MODER |= (0x1UL << (0 * 2));
while (1)
{
GPIOB->ODR ^= LD1_PIN;
delay(800000);
}
}
#include "stm32f4xx.h"
이 header를 통해 RCC, GPIOB, RCC_AHB1ENR_GPIOBEN, __NOP() 등을 사용할 수 있다.
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
GPIOB->MODER &= ~(0x3UL << (0 * 2));
GPIOB->MODER |= (0x1UL << (0 * 2));
GPIOB->ODR ^= LD1_PIN;
Ch02
주소를 직접 계산
↓
volatile pointer 직접 생성
↓
register access
Ch06
CMSIS header
↓
Peripheral structure
↓
register access
실제 hardware access의 의미는 동일하다.
Notion 기록 기준:
STM32CubeIDE CMSIS include 구성
Build / Debug / Run
LD1(PB0) 점멸 확인
.text = 664 bytes
CMSIS도 register-level programming이다.
GPIOB->MODER는 base address + structure member offset으로 접근한다.직접 pointer 방식보다 가독성과 유지보수성이 좋다.
이후 Chapter는 CMSIS 구조체 방식을 기본으로 사용한다.