__HAL_RCC_GPIOC_LK_ENABLE(); //LED가 PORTC의 13번핀으로 설정되있음.
#define __HAL_RCC_GPIOC_CLK_ENABLE() do { \
__IO uint32_t tmpreg; \
SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPCEN);\
/* Delay after an RCC peripheral clock enabling */\
tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPCEN);\
UNUSED(tmpreg); \
} while(0U)
MX_GPIO_Init()을 따라간다음 HAL_RCC_GPIOC_LK_ENABLE()을 따라가보면 위와 같은 소스가 나온다.
GPIOC의 CLK을 ENABLE시켜주기 위해 필요한 소스는 아래와 같다.
( RCC->APB2ENR = *(40021000).APB2ENR )
#define SET_BIT(REG, BIT) ((REG) |= (BIT))
SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPCEN);\
RCC->APB2ENR = REG = (pointer)(0x40021018)
RCC_APB2ENR_IOPCEN = BIT = 16
결과적으로 다음과 같이 표현할 수 있다.
(pointer)(0x40021018) |= 16
1을 왼쪽으로 4번 쉬프트하면 IOPCEN이 1로 SET되는걸 알 수 있다. 그림에서 보다시피 1로 SET된다면 I/O port C Clock이 enabled되는걸 확인할 수 있다.
HAL_GPIO_WritePin(GPIO_LED_GPIO_Port, GPIO_LED_Pin, GPIO_PIN_SET)
void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
{
/* Check the parameters */
assert_param(IS_GPIO_PIN(GPIO_Pin)); //assert_param는 작동안함
assert_param(IS_GPIO_PIN_ACTION(PinState)); //assert_param는 작동안함
if (PinState != GPIO_PIN_RESET)
{
GPIOx->BSRR = GPIO_Pin;
}
else
{
GPIOx->BSRR = (uint32_t)GPIO_Pin << 16u;
}
}
MX_GPIO_Init()을 따라간다음 HAL_GPIO_WritePin()를 따라가보면 위와 같은 소스가 나온다. 실질적으로 HAL_GPIO_WritePin을 작동시키는 소스는 아래와 같다.
if (PinState != GPIO_PIN_RESET)
{
GPIOx->BSRR = GPIO_Pin;
}
else
{
GPIOx->BSRR = (uint32_t)GPIO_Pin << 16u;
}
if (PinState != GPIO_PIN_RESET)
else
2)
GPIO_Pin = GPIO_LED_PIN = 8192(= 1<<13)
*GPIOx = GPIO_LED_GPIO_Port = 0x40011000
GPIOx_BSRR와 관련된 레퍼런스를 보면 다음과 같다.
if문을 보면 " GPIOx->BSRR = GPIO_Pin; "으로 되어있다. GPIOx_BSRR 레지스터에서 GPIO_Pin만큼 쉬프트 하라는 뜻이 된다. GPIO_Pin은 1 << 13이므로 왼쪽으로 13번 움직이면 "BS13"이 1로 SET된다.
결국은 GPIOC_BSRR레지스터에서 BS13을 SET해줌으로써 PC13(LED)을 ON시켜줄 수 있도록 제어해주는 소스이다.
3)
else문을 보면 "GPIOx->BSRR = (uint32_t)GPIO_Pin << 16u;"로 되어있다. if문과 조금 다른것은 이미 왼쪽으로 13번 쉬프트한 레지스터(LED가 ON된 상태)에서 16번 더 왼쪽으로 움직이게 만들었다는 것이다. "BRy"핀의 설명을 읽어보면 1로 SET될 경우 ODRx를 RESET(CLEAR)시킨다는걸 알 수 있다. BR13이 1로 SET된다면 LED를 꺼질 것이다.
4) 즉 BSy핀을 SET시킨다면 LED를 ON시킬 수 있고 BRy를 SET시킨다면 LED를 OFF시킬 수 있다.
HAL_GPIO_WritePin에서는 LED를 제어시킬 수 있고, __HAL_RCC_GPIOx_LK_ENABLE에서는 LED가 작동할 수 있도록 클럭(CLK)를 제어시킬 수 있는걸 알게 됐다.
HAL를 사용하지 않고 코드를 작성해보면 아래같이 표현할 수 있다.
//클록을 제어하기 위해서
volatile unsigned int * reg = 0x40021018;
*reg |= 16;
___________________________________________________________________
//LED를 제어하기 위해서
volatile unsigned int * reg2 = 0x40011000
while (1)
{
*reg2 = 0x2000;
HAL_Delay(100);
*reg2 = (0x2000 << 16);
HAL_Delay(100);
}