Replace rcc's bitfields with macros

Bitfields can use byte acces, which the bus doesn't permit. When that happens,
the bus adds extra bytes to form a word, modifying fields that shouldn't be.
Bitfields can be kept for debug and read, but writes must be done though masks
This commit is contained in:
Steins7 2023-07-05 22:20:53 +02:00
parent aeba78cfcc
commit c1b3f0d073
4 changed files with 258 additions and 20 deletions

View File

@ -25,6 +25,7 @@ static void apply_speed_preset(void);
//--local variables-------------------------------------------------------------
static volatile struct RCC* regs = (struct RCC*)RCC_BASE_ADDRESS;
static enum RccPreset current_preset = RCC_PRESET_DEFAULT;
//--public functions------------------------------------------------------------
@ -44,9 +45,11 @@ void rcc_configure(enum RccPreset preset)
switch (preset) {
case RCC_PRESET_DEFAULT:
apply_default_preset();
current_preset = RCC_PRESET_DEFAULT;
break;
case RCC_PRESET_SPEED:
apply_speed_preset();
current_preset = RCC_PRESET_SPEED;
break;
default:
break;
@ -79,6 +82,26 @@ void rcc_reset(enum RccApb1 apb1_mask, enum RccApb2 apb2_mask)
regs->APB2RSTR.word &= !(apb2_mask & APB2_MASK);
}
void rcc_get_clocks(struct RccClocks* clocks)
{
switch (current_preset)
{
case RCC_PRESET_DEFAULT:
clocks->ahb_freq = 8000000;
clocks->apb1_freq = 8000000;
clocks->apb2_freq = 8000000;
break;
case RCC_PRESET_SPEED:
clocks->ahb_freq = 72000000;
clocks->apb1_freq = 36000000;
clocks->apb2_freq = 72000000;
break;
default:
//TODO hardfault
break;
}
}
//--local functions-------------------------------------------------------------
@ -90,25 +113,26 @@ void rcc_reset(enum RccApb1 apb1_mask, enum RccApb2 apb2_mask)
static void apply_default_preset(void)
{
//ensures HSI is enabled
regs->CR.HSION = 0x1;
reg_set(regs->CR, RCC_CR_HSION);
while (regs->CR.HSIRDY != 0x1);
//set HSI as main clock source and disable prescalers
regs->CFGR.word &= ~0x077fff3;
//disable all options
regs->CR.HSITRIM = 0x10;
regs->CR.HSEON = 0x0;
regs->CR.HSEBYP = 0x0;
regs->CR.CCSON = 0x0;
regs->CR.PLLON = 0x0;
reg_reset(regs->CR, RCC_CR_HSITRIM);
reg_write(regs->CR, RCC_CR_HSITRIM, 0x10);
reg_reset(regs->CR, RCC_CR_HSEON);
reg_reset(regs->CR, RCC_CR_HSEBYP);
reg_reset(regs->CR, RCC_CR_CCSON);
reg_reset(regs->CR, RCC_CR_PLLON);
//disable all interrupts
regs->CIR.LSIRDYIE = 0x0;
regs->CIR.LSERDYIE = 0x0;
regs->CIR.HSIRDYIE = 0x0;
regs->CIR.HSERDYIE = 0x0;
regs->CIR.PLLRDYIE = 0x0;
reg_reset(regs->CIR, RCC_CIR_LSIRDYIE);
reg_reset(regs->CIR, RCC_CIR_LSERDYIE);
reg_reset(regs->CIR, RCC_CIR_HSIRDYIE);
reg_reset(regs->CIR, RCC_CIR_HSERDYIE);
reg_reset(regs->CIR, RCC_CIR_PLLRDYIE);
//reconfigure flash
flash_configure(FLASH_PRESET_LOW_CLOCK_SPEED);
@ -125,35 +149,35 @@ static void apply_speed_preset(void)
apply_default_preset();
//try enabling HSE, fallback to HSI if HSE fails
regs->CR.HSEON = 0x1;
reg_set(regs->CR, RCC_CR_HSEON);
for (uint32_t i=0; i<1000; ++i) {
__asm__("nop");
}
if (regs->CR.HSERDY == 0x1) {
regs->CFGR.PLLSCR = 0x1;
reg_set(regs->CFGR, RCC_CFGR_PLLSCR);
} else {
regs->CR.HSEON = 0;
reg_reset(regs->CR, RCC_CR_HSEON);
}
//configure PLL, fallback to HSI if PLL fails
regs->CFGR.PLLMUL = 0x7; //PLL x9
regs->CR.PLLON = 0x1;
reg_write(regs->CFGR, RCC_CFGR_PLLMUL, 0x7); //PLL x9
reg_set(regs->CR, RCC_CR_PLLON);
for (uint32_t i=0; i<1000; ++i) {
__asm__("nop");
}
if (regs->CR.PLLRDY != 0x1) {
regs->CR.PLLON = 0x0;
reg_reset(regs->CR, RCC_CR_PLLON);
return; //clock low enough, no need for prescalers
}
//configure prescalers
regs->CFGR.PPRE1 = 0x4; // /2
regs->CFGR.ADCPRE = 0x2; // /6
reg_write(regs->CFGR, RCC_CFGR_PPRE1, 0x4); // /2
reg_write(regs->CFGR, RCC_CFGR_ADCPRE, 0x2); // /6
//reconfigure flash
flash_configure(FLASH_PRESET_HIGH_CLOCK_SPEED);
//switch to PLL output
regs->CFGR.SW = 0x2;
reg_write(regs->CFGR, RCC_CFGR_SW, 0x2);
}

View File

@ -95,6 +95,12 @@ enum RccApb2 {
RCC_APB2_TIM11 = (0x1 << 21),
};
struct RccClocks {
uint32_t ahb_freq;
uint32_t apb1_freq;
uint32_t apb2_freq;
};
//--functions-------------------------------------------------------------------
@ -129,6 +135,8 @@ void rcc_disable(enum RccAhb ahb_mask, enum RccApb1 apb1_mask,
*/
void rcc_reset(enum RccApb1 apb1_mask, enum RccApb2 apb2_mask);
void rcc_get_clocks(struct RccClocks* clocks);
#endif //_RCC_H_

View File

@ -11,6 +11,8 @@
//--includes--------------------------------------------------------------------
#include "reg.h"
#include "stdint.h"
@ -37,6 +39,20 @@ union RCC_CR {
uint32_t word;
};
#define RCC_CR_HSION reg_def( 0, 1)
#define RCC_CR_HSIRDY reg_def( 1, 1)
#define RCC_CR_reserved1 reg_def( 2, 1)
#define RCC_CR_HSITRIM reg_def( 3, 5)
#define RCC_CR_HSICAL reg_def( 8, 8)
#define RCC_CR_HSEON reg_def(16, 1)
#define RCC_CR_HSERDY reg_def(17, 1)
#define RCC_CR_HSEBYP reg_def(18, 1)
#define RCC_CR_CCSON reg_def(19, 1)
#define RCC_CR_reserved2 reg_def(20, 4)
#define RCC_CR_PLLON reg_def(24, 1)
#define RCC_CR_PLLRDY reg_def(25, 1)
#define RCC_CR_reserved3 reg_def(26, 6)
union RCC_CFGR {
struct __attribute__((packed)) {
uint32_t SW:2;
@ -56,6 +72,20 @@ union RCC_CFGR {
uint32_t word;
};
#define RCC_CFGR_SW reg_def( 0, 2)
#define RCC_CFGR_SWS reg_def( 2, 2)
#define RCC_CFGR_HPRE reg_def( 4, 4)
#define RCC_CFGR_PPRE1 reg_def( 8, 3)
#define RCC_CFGR_PPRE2 reg_def(11, 3)
#define RCC_CFGR_ADCPRE reg_def(14, 2)
#define RCC_CFGR_PLLSCR reg_def(16, 1)
#define RCC_CFGR_PLLXTPRE reg_def(17, 1)
#define RCC_CFGR_PLLMUL reg_def(18, 4)
#define RCC_CFGR_USBPRE reg_def(22, 1)
#define RCC_CFGR_reserved1 reg_def(23, 1)
#define RCC_CFGR_MCO reg_def(24, 3)
#define RCC_CFGR_reserved2 reg_def(27, 5)
union RCC_CIR {
struct __attribute__((packed)) {
uint32_t LSIRDYF:1;
@ -83,6 +113,28 @@ union RCC_CIR {
uint32_t word;
};
#define RCC_CIR_LSIRDYF reg_def( 0, 1)
#define RCC_CIR_LSERDYF reg_def( 1, 1)
#define RCC_CIR_HSIRDYF reg_def( 2, 1)
#define RCC_CIR_HSERDYF reg_def( 3, 1)
#define RCC_CIR_PLLRDYF reg_def( 4, 1)
#define RCC_CIR_reserved1 reg_def( 5, 2)
#define RCC_CIR_CSSF reg_def( 7, 1)
#define RCC_CIR_LSIRDYIE reg_def( 8, 1)
#define RCC_CIR_LSERDYIE reg_def( 9, 1)
#define RCC_CIR_HSIRDYIE reg_def(10, 1)
#define RCC_CIR_HSERDYIE reg_def(11, 1)
#define RCC_CIR_PLLRDYIE reg_def(12, 1)
#define RCC_CIR_RSE2 reg_def(13, 3)
#define RCC_CIR_LSIRDYC reg_def(16, 1)
#define RCC_CIR_LSERDYC reg_def(17, 1)
#define RCC_CIR_HSIRDYC reg_def(18, 1)
#define RCC_CIR_HSERDYC reg_def(19, 1)
#define RCC_CIR_PLLRDYC reg_def(20, 1)
#define RCC_CIR_reserved3 reg_def(21, 2)
#define RCC_CIR_CSSC reg_def(23, 1)
#define RCC_CIR_reserved4 reg_def(24, 8)
union RCC_APB2RSTR {
struct __attribute__((packed)) {
uint32_t AFIORST:1;
@ -110,6 +162,28 @@ union RCC_APB2RSTR {
uint32_t word;
};
#define RCC_APB2RSTR_AFIORST reg_def( 0, 1)
#define RCC_APB2RSTR_reserved1 reg_def( 1, 1)
#define RCC_APB2RSTR_IOPARST reg_def( 2, 1)
#define RCC_APB2RSTR_IOPBRST reg_def( 3, 1)
#define RCC_APB2RSTR_IOPCRST reg_def( 4, 1)
#define RCC_APB2RSTR_IOPDRST reg_def( 5, 1)
#define RCC_APB2RSTR_IOPERST reg_def( 6, 1)
#define RCC_APB2RSTR_IOPFRST reg_def( 7, 1)
#define RCC_APB2RSTR_IOPGRST reg_def( 8, 1)
#define RCC_APB2RSTR_ADC1RST reg_def( 9, 1)
#define RCC_APB2RSTR_ACD2RST reg_def(10, 1)
#define RCC_APB2RSTR_TIM1RST reg_def(11, 1)
#define RCC_APB2RSTR_SPI1RST reg_def(12, 1)
#define RCC_APB2RSTR_TIM8RST reg_def(13, 1)
#define RCC_APB2RSTR_USART1RST reg_def(14, 1)
#define RCC_APB2RSTR_ADC3RST reg_def(15, 1)
#define RCC_APB2RSTR_reserved2 reg_def(16, 3)
#define RCC_APB2RSTR_TIM9RST reg_def(19, 1)
#define RCC_APB2RSTR_TIM10RST reg_def(20, 1)
#define RCC_APB2RSTR_TIM11RST reg_def(21, 1)
#define RCC_APB2RSTR_reserved3 reg_def(22, 10)
union RCC_APB1RSTR {
struct __attribute__((packed)) {
uint32_t TIM2RST:1;
@ -145,6 +219,36 @@ union RCC_APB1RSTR {
uint32_t word;
};
#define RCC_APB1RSTR_TIM2RST reg_def( 0, 1)
#define RCC_APB1RSTR_TIM3RST reg_def( 1, 1)
#define RCC_APB1RSTR_TIM4RST reg_def( 2, 1)
#define RCC_APB1RSTR_TIM5RST reg_def( 3, 1)
#define RCC_APB1RSTR_TIM6RST reg_def( 4, 1)
#define RCC_APB1RSTR_TIM7RST reg_def( 5, 1)
#define RCC_APB1RSTR_TIM12RST reg_def( 6, 1)
#define RCC_APB1RSTR_TIM13RST reg_def( 7, 1)
#define RCC_APB1RSTR_TIM14RST reg_def( 8, 1)
#define RCC_APB1RSTR_reserved1 reg_def( 9, 2)
#define RCC_APB1RSTR_WWDGRST reg_def(11, 1)
#define RCC_APB1RSTR_reserved2 reg_def(12, 2)
#define RCC_APB1RSTR_SPI2RST reg_def(14, 1)
#define RCC_APB1RSTR_SPI3RST reg_def(15, 1)
#define RCC_APB1RSTR_reserved3 reg_def(16, 1)
#define RCC_APB1RSTR_USART2RST reg_def(17, 1)
#define RCC_APB1RSTR_USART3RST reg_def(18, 1)
#define RCC_APB1RSTR_UART4RST reg_def(19, 1)
#define RCC_APB1RSTR_UART5RST reg_def(20, 1)
#define RCC_APB1RSTR_I2C12RST reg_def(21, 1)
#define RCC_APB1RSTR_I2C2RST reg_def(22, 1)
#define RCC_APB1RSTR_USB2RST reg_def(23, 1)
#define RCC_APB1RSTR_reserved4 reg_def(24, 1)
#define RCC_APB1RSTR_CANRST reg_def(25, 1)
#define RCC_APB1RSTR_reserved5 reg_def(26, 1)
#define RCC_APB1RSTR_BKPRST reg_def(27, 1)
#define RCC_APB1RSTR_PWRRST reg_def(28, 1)
#define RCC_APB1RSTR_DACRST reg_def(29, 1)
#define RCC_APB1RSTR_reserved6 reg_def(30, 2)
union RCC_AHBENR {
struct __attribute__((packed)) {
uint32_t DMA1EN:1;
@ -163,6 +267,19 @@ union RCC_AHBENR {
uint32_t word;
};
#define RCC_AHBENR_DMA1EN reg_def( 0, 1)
#define RCC_AHBENR_DMA2EN reg_def( 1, 1)
#define RCC_AHBENR_SRAMEN reg_def( 2, 1)
#define RCC_AHBENR_reserved1 reg_def( 3, 1)
#define RCC_AHBENR_FLITFEN reg_def( 4, 1)
#define RCC_AHBENR_reserved2 reg_def( 5, 1)
#define RCC_AHBENR_CRCEN reg_def( 6, 1)
#define RCC_AHBENR_reserved3 reg_def( 7, 1)
#define RCC_AHBENR_FSMCEN reg_def( 8, 1)
#define RCC_AHBENR_reserved4 reg_def( 9, 1)
#define RCC_AHBENR_SDIOEN reg_def(10, 1)
#define RCC_AHBENR_reserved5 reg_def(11, 21)
union RCC_APB2ENR {
struct __attribute__((packed)) {
uint32_t AFIOEN:1;
@ -190,6 +307,28 @@ union RCC_APB2ENR {
uint32_t word;
};
#define RCC_APB2ENR_AFIOEN reg_def( 0, 1)
#define RCC_APB2ENR_reserved1 reg_def( 1, 1)
#define RCC_APB2ENR_IOPAEN reg_def( 2, 1)
#define RCC_APB2ENR_IOPBEN reg_def( 3, 1)
#define RCC_APB2ENR_IOPCEN reg_def( 4, 1)
#define RCC_APB2ENR_IOPDEN reg_def( 5, 1)
#define RCC_APB2ENR_IOPEEN reg_def( 6, 1)
#define RCC_APB2ENR_IOPFEN reg_def( 7, 1)
#define RCC_APB2ENR_IOPGEN reg_def( 8, 1)
#define RCC_APB2ENR_ADC1EN reg_def( 9, 1)
#define RCC_APB2ENR_ACD2EN reg_def(10, 1)
#define RCC_APB2ENR_TIM1EN reg_def(11, 1)
#define RCC_APB2ENR_SPI1EN reg_def(12, 1)
#define RCC_APB2ENR_TIM8EN reg_def(13, 1)
#define RCC_APB2ENR_USART1EN reg_def(14, 1)
#define RCC_APB2ENR_ADC3EN reg_def(15, 1)
#define RCC_APB2ENR_reserved2 reg_def(16, 3)
#define RCC_APB2ENR_TIM9EN reg_def(19, 1)
#define RCC_APB2ENR_TIM10EN reg_def(20, 1)
#define RCC_APB2ENR_TIM11EN reg_def(21, 1)
#define RCC_APB2ENR_reserved3 reg_def(22, 10)
union RCC_APB1ENR {
struct __attribute__((packed)) {
uint32_t TIM2EN:1;
@ -225,6 +364,36 @@ union RCC_APB1ENR {
uint32_t word;
};
#define RCC_APB1ENR_TIM2EN reg_def( 0, 1)
#define RCC_APB1ENR_TIM3EN reg_def( 1, 1)
#define RCC_APB1ENR_TIM4EN reg_def( 2, 1)
#define RCC_APB1ENR_TIM5EN reg_def( 3, 1)
#define RCC_APB1ENR_TIM6EN reg_def( 4, 1)
#define RCC_APB1ENR_TIM7EN reg_def( 5, 1)
#define RCC_APB1ENR_TIM12EN reg_def( 6, 1)
#define RCC_APB1ENR_TIM13EN reg_def( 7, 1)
#define RCC_APB1ENR_TIM14EN reg_def( 8, 1)
#define RCC_APB1ENR_reserved1 reg_def( 9, 2)
#define RCC_APB1ENR_WWDGEN reg_def(11, 1)
#define RCC_APB1ENR_reserved reg_def(12, 2)
#define RCC_APB1ENR_SPI2EN reg_def(14, 1)
#define RCC_APB1ENR_SPI3EN reg_def(15, 1)
#define RCC_APB1ENR_reserved2 reg_def(16, 1)
#define RCC_APB1ENR_USART2EN reg_def(17, 1)
#define RCC_APB1ENR_USART3EN reg_def(18, 1)
#define RCC_APB1ENR_UART4EN reg_def(19, 1)
#define RCC_APB1ENR_UART5EN reg_def(20, 1)
#define RCC_APB1ENR_I2C12EN reg_def(21, 1)
#define RCC_APB1ENR_I2C2EN reg_def(22, 1)
#define RCC_APB1ENR_USB2EN reg_def(23, 1)
#define RCC_APB1ENR_reserved3 reg_def(24, 1)
#define RCC_APB1ENR_CANEN reg_def(25, 1)
#define RCC_APB1ENR_reserved4 reg_def(26, 1)
#define RCC_APB1ENR_BKPEN reg_def(27, 1)
#define RCC_APB1ENR_PWREN reg_def(28, 1)
#define RCC_APB1ENR_DACEN reg_def(29, 1)
#define RCC_APB1ENR_reserved5 reg_def(30, 2)
union RCC_BDCR {
struct __attribute__((packed)) {
uint32_t LSEON:1;
@ -240,6 +409,16 @@ union RCC_BDCR {
uint32_t word;
};
#define RCC_BDCR_LSEON reg_def( 0, 1)
#define RCC_BDCR_LSERDY reg_def( 1, 1)
#define RCC_BDCR_LSEBYP reg_def( 2, 1)
#define RCC_BDCR_reserved1 reg_def( 3, 5)
#define RCC_BDCR_RTCSEL reg_def( 8, 2)
#define RCC_BDCR_reserved2 reg_def(10, 5)
#define RCC_BDCR_RTCEN reg_def(15, 1)
#define RCC_BDCR_BDRST reg_def(16, 1)
#define RCC_BDCR_reserved3 reg_def(17, 15)
union RCC_CSR {
struct __attribute__((packed)) {
uint32_t LSION:1;
@ -257,6 +436,18 @@ union RCC_CSR {
uint32_t word;
};
#define RCC_CSR_LSION reg_def( 0, 1)
#define RCC_CSR_LSIRDY reg_def( 1, 1)
#define RCC_CSR_reserved1 reg_def( 2, 22)
#define RCC_CSR_RMVF reg_def(24, 1)
#define RCC_CSR_reserved2 reg_def(25, 1)
#define RCC_CSR_PINRSTF reg_def(26, 1)
#define RCC_CSR_PORRSTF reg_def(27, 1)
#define RCC_CSR_SFTRSTF reg_def(28, 1)
#define RCC_CSR_IWDGRSTF reg_def(29, 1)
#define RCC_CSR_WWDGRSTF reg_def(30, 1)
#define RCC_CSR_LPWRSTF reg_def(31, 1)
struct __attribute__((packed)) RCC {
union RCC_CR CR;
union RCC_CFGR CFGR;

15
drivers/reg.h Normal file
View File

@ -0,0 +1,15 @@
#define reg_def(pos, size) pos, (((0x1 << size) - 1) << pos)
#define reg_set(reg, field) _reg_set(reg, field)
#define _reg_set(reg, pos, mask) do { reg.word |= mask; } while (false)
#define reg_reset(reg, field) _reg_reset(reg, field)
#define _reg_reset(reg, pos, mask) do { reg.word &= ~mask; } while (false)
#define reg_write(reg, field, value) _reg_write(reg, field, value)
#define _reg_write(reg, pos, mask, value) \
do { \
reg.word |= value << pos; \
} while (false) \