diff --git a/drivers/rcc.c b/drivers/rcc.c index c4c7bb0..20dfcff 100644 --- a/drivers/rcc.c +++ b/drivers/rcc.c @@ -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); } diff --git a/drivers/rcc.h b/drivers/rcc.h index 61a5307..770b7a0 100644 --- a/drivers/rcc.h +++ b/drivers/rcc.h @@ -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_ diff --git a/drivers/rcc_regs.h b/drivers/rcc_regs.h index 047f7e9..44f7eff 100644 --- a/drivers/rcc_regs.h +++ b/drivers/rcc_regs.h @@ -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; diff --git a/drivers/reg.h b/drivers/reg.h new file mode 100644 index 0000000..05cdc19 --- /dev/null +++ b/drivers/reg.h @@ -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) \ +