STM32 - Указатели и сумма - PullRequest
       74

STM32 - Указатели и сумма

1 голос
/ 20 апреля 2020

Я учусь программировать плату STM32 Nucleo F446RE, используя регистры.

Чтобы узнать положение регистра, я беру из таблиц адрес границы и смещение. Однако я не могу рассчитать их сумму. Я показываю пример:

volatile uint32_t *GPIOA = 0x0; // Initialization of the boundary adress
GPIOA = (uint32_t*)0x40020000; // Boundary adress from datasheet

volatile uint32_t *GPIOA_ODR = 0x0; // Initialization of GPIOA_ODR register
GPIOA_ODR = GPIOA +  (uint32_t*)0x14; // Calculation of GPIOA_ODR as the sum of the boundary adress and the offset (i.e. 0x14.

Строка 5 дает мне ошибку, вы знаете, как правильно ее рассчитать?

Заранее большое спасибо.

Ответы [ 3 ]

1 голос
/ 20 апреля 2020

Это неправильно. Если вы хотите использовать этот крайне неудобный способ:

#define GPIOA 0x4002000
#define ODR_OFFSET 0x14

#define GPIO_ODR (*(volatile uint32_t *)(GPIOA + ODR_OFFSET))

, почему #define не указатель? Это просто более дружественно к компилятору и экономит одно чтение памяти.

https://godbolt.org/z/LdLLVN

#define GPIOA 0x4002000
#define ODR_OFFSET 0x14

#define GPIO_ODR (*(volatile uint32_t *)(GPIOA + ODR_OFFSET))

volatile uint32_t *pGPIO_ODR = (volatile uint32_t *)(GPIOA + ODR_OFFSET);

void foo(uint32_t x)
{
    GPIO_ODR = x;
}

void bar(uint32_t x)
{
    *pGPIO_ODR = x;
}

и полученный код

foo:
        ldr     r3, .L3
        str     r0, [r3, #20]
        bx      lr
.L3:
        .word   67117056
bar:
        ldr     r3, .L6
        ldr     r3, [r3]
        str     r0, [r3]
        bx      lr
.L6:
        .word   .LANCHOR0
pGPIO_ODR:
        .word   67117076
0 голосов
/ 20 апреля 2020

Я пытался, но ничего. Если я вставляю GPIOA_ODR = (uint32_t*)(0x40020000 + 0x14);, это работает, вместо этого, если я вставляю GPIOA_ODR = (uint32_t*)(GPIOA + 0x14);, это не работает. Некоторые другие идеи?

Большое спасибо за ответ. Полный код, который я использую, следующий:

int main(int argc, char* argv[])
{
    /** RCC **/
    /* RCC */
    volatile uint32_t *RCC = 0x0;
    RCC = (uint32_t*)0x40023800;
    /* RCC_AHB1ENR */
    volatile uint32_t *RCC_AHB1ENR = 0x0;
    RCC_AHB1ENR = (uint32_t*)(0x40023800 + 0x30);
    *RCC_AHB1ENR |= 0x1;

    /** GPIOA **/
    /* GPIOA */
    volatile uint32_t *GPIOA = 0x0;
    GPIOA = (uint32_t*)0x40020000;
    /* GPIOA_MODER */
    volatile uint32_t *GPIOA_MODER = 0x0;
    GPIOA_MODER = (uint32_t*)(0x40020000 + 0x00);
    *GPIOA_MODER |= 1 << 16;
    *GPIOA_MODER &= ~(0 << 17);
    /* GPIOA_ODR */
    volatile uint32_t *GPIOA_ODR = 0x0;
    GPIOA_ODR = (uint32_t*)(GPIOA + 0x14);
    *GPIOA_ODR |= 1 << 8;
}

Этот код работает неправильно из-за строки GPIOA_ODR = (uint32_t*)(GPIOA + 0x14);. Если я вставлю GPIOA_ODR = (uint32_t*)(0x40020000 + 0x14), он будет работать правильно.

0 голосов
/ 20 апреля 2020

Приведение должно быть за пределами постоянного значения, другими словами, вы добавляете адрес GPIOA + 14 для генерации нового адреса. Таким образом, актерский состав должен быть вне их:

GPIOA_ODR = (uint32_t*)(GPIOA +  0x14);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...