В настоящее время я пишу в C для STM32F446RE (ARM-компилятор), и поскольку я хочу получить опыт встроенного программирования, я не пользуюсь никакими библиотеками. Для моей инициализации мне было интересно, было бы неплохо получить доступ к регистрам, увеличив один указатель на смещение этого регистра с периферийной базы.Могу ли я получить доступ к нескольким регистрам устройств с помощью одного указателя?
void I2C_Init(void)
{
volatile uint32_t *reg_ptr = (uint32_t *) GPIOB_LOC;
*(reg_ptr + GPIOB_MODE_OFFSET) &= ~((0xFU<<16) | (0xFU<<20)); //clear before updating
*(reg_ptr + GPIOB_MODE_OFFSET) |= ((0xAU<<16) | (0xAU<<20)); //set pins 8, 9, 10, 11 to alt func
*(reg_ptr + GPIOB_OTYPE_OFFSET) &= ~(0xFU<<8); //no types
*(reg_ptr + GPIOB_OSPEED_OFFSET) &= ~((0xFU<<16) | (0xFU<<20)); //clear before updating
*(reg_ptr + GPIOB_OSPEED_OFFSET) |= ((0x5U<<16) | (0x5U<<20)); //set to normal speed (will get overriden by alt func)
*(reg_ptr + GPIOB_PUPD_OFFSET) &= ~((0xFU<<16) | (0xFU<<20)); //no pull up or pull down
*(reg_ptr + GPIOB_AFH_OFFSET) &= ~0xFFFFU; //clear before updating
*(reg_ptr + GPIOB_AFH_OFFSET) |= 0x4444U; //set pins 8, 9, 10, 11 to alt func 4 (i2c1 & i2c2 SCL and SDA respectively)
}
В моем файле заголовка:
#define GPIOB_LOC 0x40020400UL //base
#define GPIOB_MODE_OFFSET (0x00)
#define GPIOB_OTYPE_OFFSET (0x04)
#define GPIOB_OSPEED_OFFSET (0x08)
#define GPIOB_PUPD_OFFSET (0x0C)
#define GPIOB_AFH_OFFSET (0x24)
небезопасным ли эта практика? Есть ли лучший, более общепринятый способ доступа к нескольким регистрам устройств без накладных расходов на создание указателя для каждого конкретного регистра?
Спасибо, ребята! Это мой первый пост, так что дайте мне знать, есть ли что-нибудь, что я могу сделать, чтобы улучшить мой вопрос или любую дополнительную информацию, которая была бы полезной.
Несомненно. Обычная схема состоит в том, чтобы определить структуру, соответствующую макету регистров, и настроить указатель на его базовый адрес, хотя это эквивалентно, но безопасно с типом и довольно приятным для работы. – doynax
Вы должны быть осторожны при добавлении смещения к адресу (указателю?) В C. Если вы добавите 4 к значению от указателя к 32 биту, компилятор добавит 16. Арифметика указателя работает так же, как индексирование элемента массива, то есть он учитывает размер элемента. –
Зачем вам это делать, а затем использовать заголовок stm32f4xx.h, предоставленный ST? Гораздо меньше подвержено ошибкам, полному и простому. – Clifford