diff --git a/hw/arm/stm32-mcu.c b/hw/arm/stm32-mcu.c index aedc3c4502..231c8d217a 100644 --- a/hw/arm/stm32-mcu.c +++ b/hw/arm/stm32-mcu.c @@ -268,10 +268,8 @@ static void stm32_mcu_memory_regions_create_callback(DeviceState *dev) static Property stm32_mcu_properties[] = { DEFINE_PROP_STM32CAPABILITIES_PTR("stm32-capabilities", STM32MCUState, param_capabilities), - DEFINE_PROP_UINT32("hse-freq-hz", STM32MCUState, hse_freq_hz, - DEFAULT_HSE_FREQ_HZ), - DEFINE_PROP_UINT32("lse-freq-hz", STM32MCUState, lse_freq_hz, - DEFAULT_RTC_FREQ_HZ), + DEFINE_PROP_UINT32("hse-freq-hz", STM32MCUState, hse_freq_hz, 0), + DEFINE_PROP_UINT32("lse-freq-hz", STM32MCUState, lse_freq_hz, 0), DEFINE_PROP_END_OF_LIST(), /**/ }; diff --git a/hw/arm/stm32-mcus.c b/hw/arm/stm32-mcus.c index f1dd032f73..c4632cca39 100644 --- a/hw/arm/stm32-mcus.c +++ b/hw/arm/stm32-mcus.c @@ -262,7 +262,7 @@ static const STM32Capabilities stm32f405xx = { .is_01_57_xx = true }, .hsi_freq_hz = 16000000, - //.lsi_freq_hz = 40000, + .lsi_freq_hz = 32000, .has_rcc = true, .has_pwr = true, .has_rtc = true, @@ -346,7 +346,7 @@ static const STM32Capabilities stm32f407xx = { .is_01_57_xx = true }, .hsi_freq_hz = 16000000, - //.lsi_freq_hz = 40000, + .lsi_freq_hz = 32000, .has_rcc = true, .has_pwr = true, .has_rtc = true, @@ -424,6 +424,71 @@ static const STM32Capabilities stm32f407xx = { .has_dac1 = true, /* 12-bits */ .has_dac2 = true, }; +static const STM32Capabilities stm32f411xx = { + + .family = STM32_FAMILY_F4, + .f4 = { + .is11xx = true }, + + .hsi_freq_hz = 16000000, + .lsi_freq_hz = 32000, + .has_rcc = true, + .has_pwr = true, + .has_rtc = true, + .num_back_bytes = 80, + .has_periph_bitband = true, + + .has_crc = true, + .has_dma1 = true, + .num_dma1 = 8, + .has_dma2 = true, + .num_dma2 = 8, + //.has_fsmc = true, + .has_exti = true, + .num_exti = 21, + + .has_ac_tim1 = true, + .has_gp_tim2 = true, + .has_gp_tim3 = true, + .has_gp_tim4 = true, + .has_gp_tim5 = true, + .has_gp_tim9 = true, + .has_gp_tim10 = true, + .has_gp_tim11 = true, + + .has_iwdg = true, + .has_wwdg = true, + .has_i2c1 = true, + .has_i2c2 = true, + .has_i2c3 = true, + .has_usart1 = true, + .has_usart2 = true, + .has_usart6 = true, + .has_spi1 = true, + .has_spi2 = true, + .has_spi3 = true, + .has_spi4 = true, + .has_spi5 = true, + .has_i2s1 = true, + .has_i2s2 = true, + .has_plli2s = true, + .has_sdio = true, + + .has_usb_otg_fs = true, + + .has_gpioa = true, + .has_gpiob = true, + .has_gpioc = true, + .has_gpiod = true, + .has_gpioe = true, + + .has_gpioh = true, // TODO: only H0 & H1 are present + + .has_adc1 = true, /* 12-bits, 16 channels */ + .has_ts = true, /* ADC1_IN16 */ + +}; + static const STM32Capabilities stm32f429xx = { .family = STM32_FAMILY_F4, @@ -431,7 +496,7 @@ static const STM32Capabilities stm32f429xx = { .is_23_xxx = true }, .hsi_freq_hz = 16000000, - //.lsi_freq_hz = 40000, + .lsi_freq_hz = 32000, .has_rcc = true, .has_pwr = true, .has_rtc = true, @@ -592,6 +657,14 @@ static const CortexMCoreCapabilities stm32f4_23_xxx_core = { .nvic_bits = 4, /**/ }; +static const CortexMCoreCapabilities stm32f411xx_core = { + .cpu_model = "cortex-m4", /* TODO: make 4f when possible */ + .has_mpu = true, + .has_itm = true, + .num_irq = 62, + .nvic_bits = 4, /**/ +}; + /* ------------------------------------------------------------------------- */ static const STM32PartInfo stm32_mcus[] = { @@ -692,16 +765,14 @@ static const STM32PartInfo stm32_mcus[] = { .core = &stm32f4_01_57_xx_core, }, .stm32 = &stm32f407xx /**/ }, -#if 0 { .name = TYPE_STM32F411RE, .cortexm = { .flash_size_kb = 512, .sram_size_kb = 128, /* No CCM */ - .core = &stm32f4xx_core, /* TODO: Add .stm32 */ - }, /**/ + .core = &stm32f411xx_core, }, + .stm32 = &stm32f411xx /**/ }, -#endif { .name = TYPE_STM32F429ZI, .cortexm = { diff --git a/hw/gpio/stm32-gpio.c b/hw/gpio/stm32-gpio.c index eb7cf1cea3..6d296e30ad 100644 --- a/hw/gpio/stm32-gpio.c +++ b/hw/gpio/stm32-gpio.c @@ -43,6 +43,9 @@ * STM32F405xx/07xx, STM32F415xx/17xx, STM32F42xxx and STM32F43xxx * advanced ARM-based 32-bit MCUs" * + * - Doc ID 026448 Rev 1, "ST RM0383 Reference manual, + * STM32F411xC/E advanced ARM-based 32-bit MCUs" + * * All STM32 reference manuals available from: * http://www.st.com/stonline/stappl/resourceSelector/\ * app?page=fullResourceSelector&doctype=reference_manual&FamilyID=141 @@ -341,7 +344,7 @@ static void stm32f1_gpio_update_dir_mask(STM32GPIOState *state, int index) /* ===== F4 ================================================================ */ -/* STM32F4[01][57]xx, STM32F4[23]xxx */ +/* STM32F4[01][57]xx, STM32F4[23]xxx, STM32F411xx */ uint32_t stm32f4_gpio_get_config_bits(uint32_t value, uint32_t bit); static void stm32f4_gpio_update_dir_mask(STM32GPIOState *state); diff --git a/hw/misc/stm32-flash.c b/hw/misc/stm32-flash.c index 1165013b8f..88a29cd1c4 100644 --- a/hw/misc/stm32-flash.c +++ b/hw/misc/stm32-flash.c @@ -35,6 +35,9 @@ * STM32F405xx/07xx, STM32F415xx/17xx, STM32F42xxx and STM32F43xxx * advanced ARM-based 32-bit MCUs" * + * - Doc ID 026448 Rev 1, "ST RM0383 Reference manual, + * STM32F411xC/E advanced ARM-based 32-bit MCUs" + * * All STM32 reference manuals available from: * http://www.st.com/stonline/stappl/resourceSelector/\ * app?page=fullResourceSelector&doctype=reference_manual&FamilyID=141 @@ -307,6 +310,71 @@ static void stm32f4_01_57_xx_flash_create_objects(Object *obj) peripheral_new_with_info(obj, NULL, &stm32f4_01_57_xx_flash_info); } +static PeripheralInfo stm32f411xx_flash_info = { + .desc = "Reset and clock control (RCC)", + + .registers = (PeripheralRegisterInfo[] ) { + { + .desc = "Flash access control register (FLASH_ACR)", + .name = "acr", + .offset_bytes = 0x00, + .reset_value = 0x00000030, + .bitfields = (RegisterBitfieldInfo[] ) { + { + .name = "latency", + .first_bit = 0, + .width_bits = 4, }, + { + .name = "prften", + .desc = "Prefetch enable", + .first_bit = 8, }, + { + .name = "icen", + .desc = "Prefetch enable", + .first_bit = 9, }, + { + .name = "dcen", + .desc = "Data cache enable", + .first_bit = 10, }, + { + .name = "icrst", + .desc = "Instruction cache reset", + .first_bit = 11, + .rw_mode = REGISTER_RW_MODE_READ, }, + { + .name = "dcrst", + .desc = "Data cache reset", + .first_bit = 12, }, + { }, /**/ + } , /**/ + }, + /* Very schematic, functional read after write only. */ + { + .name = "keyr", + .offset_bytes = 0x04, }, + { + .name = "optkeyr", + .offset_bytes = 0x08, }, + { + .name = "sr", + .offset_bytes = 0x0C, }, + { + .name = "cr", + .offset_bytes = 0x10, }, + { + .name = "optcr", + .offset_bytes = 0x14, }, + { }, /**/ + } , /**/ +}; + +static void stm32f411xx_flash_create_objects(Object *obj) +{ + //STM32FlashState *state = STM32_FLASH_STATE(obj); + + peripheral_new_with_info(obj, NULL, &stm32f411xx_flash_info); +} + static PeripheralInfo stm32f4_23_xxx_flash_info = { .desc = "Reset and clock control (RCC)", @@ -473,6 +541,8 @@ static void stm32_flash_realize_callback(DeviceState *dev, Error **errp) if (capabilities->f4.is_01_57_xx) { stm32f4_01_57_xx_flash_create_objects(obj); + } else if (capabilities->f4.is11xx) { + stm32f411xx_flash_create_objects(obj); } else if (capabilities->f4.is_23_xxx) { stm32f4_23_xxx_flash_create_objects(obj); } diff --git a/hw/misc/stm32-pwr.c b/hw/misc/stm32-pwr.c index 9ad769960a..3eaed20e4e 100644 --- a/hw/misc/stm32-pwr.c +++ b/hw/misc/stm32-pwr.c @@ -34,6 +34,9 @@ * STM32F405xx/07xx, STM32F415xx/17xx, STM32F42xxx and STM32F43xxx * advanced ARM-based 32-bit MCUs" * + * - Doc ID 026448 Rev 1, "ST RM0383 Reference manual, + * STM32F411xC/E advanced ARM-based 32-bit MCUs" + * * All STM32 reference manuals available from: * http://www.st.com/stonline/stappl/resourceSelector/\ * app?page=fullResourceSelector&doctype=reference_manual&FamilyID=141 @@ -344,6 +347,187 @@ static void stm32f4_01_57_xx_pwr_create_objects(Object *obj) /* ------------------------------------------------------------------------- */ +/* STM32F411_xx */ + +static PeripheralInfo stm32f411xx_pwr_info = + { + .desc = "Power controller (PWR)", + + .registers = + (PeripheralRegisterInfo[] ) { + { + .desc = + "PWR power control register (PWR_CR)", + .name = "cr", + .offset_bytes = 0x00, + .reset_value = 0x00008000, + .bitfields = + (RegisterBitfieldInfo[] ) { + { + .name = "lpds", + .desc = + "Low-power deep sleep", + .first_bit = 0, }, + { + .name = "pdds", + .desc = + "Power-down deepsleep", + .first_bit = 1, }, + { + .name = "cwuf", + .desc = + "Clear wakeup flag", + .first_bit = 2, + .rw_mode = + REGISTER_RW_MODE_WRITE, }, + { + .name = "csbf", + .desc = + "Clear standby flag", + .first_bit = 3, + .rw_mode = + REGISTER_RW_MODE_WRITE, }, + { + .name = "pvde", + .desc = + "Power voltage detector enable", + .first_bit = 4, }, + { + .name = "pls", + .desc = + "PVD level selection", + .first_bit = 5, + .width_bits = 3, }, + { + .name = "dbp", + .desc = + "Disable backup domain write protection", + .first_bit = 8, }, + { + .name = "fpds", + .desc = + "Flash power-down in Stop mode", + .first_bit = 9, }, + { + .name = "vos", + .desc = + "Regulator voltages caling output selection", + .first_bit = 14, }, + { + .name = "fmssr", + .desc = + "Flash Memory Sleep System Run", + .first_bit = 20, }, + { + .name = "fissr", + .desc = + "Flash Interface Stop while System Run", + .first_bit = 21, }, + { }, /**/ + } , /**/}, + { + .desc = + "PWR power control/status register (PWR_CSR)", + .name = "csr", + .offset_bytes = 0x04, + .reset_value = 0x00000000, + .bitfields = + (RegisterBitfieldInfo[] ) { + { + .name = "wuf", + .desc = + "Wakeup flag", + .first_bit = 0, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { + .name = "sbf", + .desc = + "Standby flag", + .first_bit = 1, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { + .name = "pvdo", + .desc = "PVD output", + .first_bit = 2, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { + .name = "brr", + .desc = + "CBackup regulator ready", + .first_bit = 3, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { + .name = "ewup", + .desc = + "Enable WKUP pin", + .first_bit = 8, }, + { + .name = "bre", + .desc = + "Backup regulator enable", + .first_bit = 9, }, + { + .name = "vosrdy", + .desc = + "Regulator voltage scaling output selection ready bit", + .first_bit = 14, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { }, /**/ + } , /**/}, + { }, /**/ + } , /**/ + }; + +static void stm32f411xx_pwr_create_objects(Object *obj) +{ + STM32PWRState *state = STM32_PWR_STATE(obj); + + peripheral_new_with_info(obj, NULL, &stm32f411xx_pwr_info); + + state->f4.reg.cr = cm_object_get_child_by_name(obj, "cr"); + state->f4.reg.csr = cm_object_get_child_by_name(obj, "csr"); + + /* CR bitfields. */ + state->f4.fld.cr.lpds = cm_object_get_child_by_name(state->f4.reg.cr, + "lpds"); + state->f4.fld.cr.pdds = cm_object_get_child_by_name(state->f4.reg.cr, + "pdds"); + state->f4.fld.cr.cwuf = cm_object_get_child_by_name(state->f4.reg.cr, + "cwuf"); + state->f4.fld.cr.csbf = cm_object_get_child_by_name(state->f4.reg.cr, + "csbf"); + state->f4.fld.cr.pvde = cm_object_get_child_by_name(state->f4.reg.cr, + "pvde"); + state->f4.fld.cr.pls = cm_object_get_child_by_name(state->f4.reg.cr, "pls"); + state->f4.fld.cr.dbp = cm_object_get_child_by_name(state->f4.reg.cr, "dbp"); + state->f4.fld.cr.fpds = cm_object_get_child_by_name(state->f4.reg.cr, + "fpds"); + state->f4.fld.cr.vos = cm_object_get_child_by_name(state->f4.reg.cr, "vos"); + + /* CSR bitfields. */ + state->f4.fld.csr.wuf = cm_object_get_child_by_name(state->f4.reg.csr, + "wuf"); + state->f4.fld.csr.sbf = cm_object_get_child_by_name(state->f4.reg.csr, + "sbf"); + state->f4.fld.csr.pvdo = cm_object_get_child_by_name(state->f4.reg.csr, + "pvdo"); + state->f4.fld.csr.brr = cm_object_get_child_by_name(state->f4.reg.csr, + "brr"); + state->f4.fld.csr.ewup = cm_object_get_child_by_name(state->f4.reg.csr, + "ewup"); + state->f4.fld.csr.bre = cm_object_get_child_by_name(state->f4.reg.csr, + "bre"); + state->f4.fld.csr.vosrdy = cm_object_get_child_by_name(state->f4.reg.csr, + "vosrdy"); + +} +/* ------------------------------------------------------------------------- */ + /* STM32F4_23_xxx */ static PeripheralInfo stm32f4_23_xxx_pwr_info = @@ -639,11 +823,16 @@ static void stm32_pwr_realize_callback(DeviceState *dev, Error **errp) /* Auto bits. */ cm_object_property_set_str(state->f4.fld.csr.brr, "bre", "follows"); - } - if (capabilities->f4.is_23_xxx) { + } else if (capabilities->f4.is_23_xxx) { stm32f4_23_xxx_pwr_create_objects(obj); + /* Auto bits. */ + cm_object_property_set_str(state->f4.fld.csr.brr, "bre", "follows"); + } else if (capabilities->f4.is11xx) { + + stm32f411xx_pwr_create_objects(obj); + /* Auto bits. */ cm_object_property_set_str(state->f4.fld.csr.brr, "bre", "follows"); } diff --git a/hw/misc/stm32-rcc.c b/hw/misc/stm32-rcc.c index a937d9eb2a..96506a4a38 100644 --- a/hw/misc/stm32-rcc.c +++ b/hw/misc/stm32-rcc.c @@ -40,6 +40,9 @@ * STM32F405xx/07xx, STM32F415xx/17xx, STM32F42xxx and STM32F43xxx * advanced ARM-based 32-bit MCUs" * + * - Doc ID 026448 Rev 1, "ST RM0383 Reference manual, + * STM32F411xC/E advanced ARM-based 32-bit MCUs" + * * All STM32 reference manuals available from: * http://www.st.com/stonline/stappl/resourceSelector/\ * app?page=fullResourceSelector&doctype=reference_manual&FamilyID=141 @@ -2048,9 +2051,9 @@ static void stm32f4_01_57_xx_rcc_create_objects(Object *obj) /* ------------------------------------------------------------------------- */ -/* STM32F4_23_xxx */ +/* STM32F411xx */ -static PeripheralInfo stm32f4_23_xxx_rcc_info = +static PeripheralInfo stm32f411xx_rcc_info = { .desc = "Reset and clock control (RCC)", @@ -2060,7 +2063,7 @@ static PeripheralInfo stm32f4_23_xxx_rcc_info = .desc = "Clock control register (RCC_CR)", .name = "cr", .offset_bytes = 0x00, - .reset_value = 0x00000083, + .reset_value = 0x00000083, /* not 81 */ .reset_mask = 0xFFFF00FF, .bitfields = (RegisterBitfieldInfo[] ) { @@ -2135,18 +2138,7 @@ static PeripheralInfo stm32f4_23_xxx_rcc_info = .first_bit = 27, .rw_mode = REGISTER_RW_MODE_READ, }, - { - .name = "pllsaion", - .desc = - "PLL SAI enable", - .first_bit = 28, }, - { - .name = "pllsairdy", - .desc = - "PLL SAI clock ready flag", - .first_bit = 29, - .rw_mode = - REGISTER_RW_MODE_READ, }, + { }, /**/ } , /**/}, { @@ -2315,13 +2307,6 @@ static PeripheralInfo stm32f4_23_xxx_rcc_info = .first_bit = 5, .rw_mode = REGISTER_RW_MODE_READ, }, - { - .name = "pllsairdyf", - .desc = - "PLL SAI ready interrupt flag", - .first_bit = 6, - .rw_mode = - REGISTER_RW_MODE_READ, }, { .name = "cssf", .desc = @@ -2360,12 +2345,6 @@ static PeripheralInfo stm32f4_23_xxx_rcc_info = .desc = "PLL I2S ready interrupt enable", .first_bit = 13, }, - { - .name = - "pllsairdyie", - .desc = - "PLL SAI ready interrupt enable", - .first_bit = 14, }, { .name = "lsirdyc", .desc = @@ -2408,13 +2387,6 @@ static PeripheralInfo stm32f4_23_xxx_rcc_info = .first_bit = 21, .rw_mode = REGISTER_RW_MODE_WRITE, }, - { - .name = "pllsairdyc", - .desc = - "PLL SAI ready interrupt clear", - .first_bit = 22, - .rw_mode = - REGISTER_RW_MODE_WRITE, }, { .name = "cssc", .desc = @@ -2431,120 +2403,96 @@ static PeripheralInfo stm32f4_23_xxx_rcc_info = .name = "ahb1rstr", .offset_bytes = 0x10, .reset_value = 0x00000000, - .readable_bits = 0x22E017FF, - .writable_bits = 0x22E017FF, }, + .readable_bits = 0x0060109F, + .writable_bits = 0x0060109F, }, { .desc = "RCC AHB2 peripheral reset register (RCC_AHB2RSTR)", .name = "ahb2rstr", .offset_bytes = 0x14, .reset_value = 0x00000000, - .readable_bits = 0x000000F1, - .writable_bits = 0x000000F1, }, - { - .desc = - "RCC AHB3 peripheral reset register (RCC_AHB3RSTR)", - .name = "ahb3rstr", - .offset_bytes = 0x18, - .reset_value = 0x00000000, - .readable_bits = 0x00000001, - .writable_bits = 0x00000001, }, + .readable_bits = 0x00000080, + .writable_bits = 0x00000080, }, { .desc = "RCC APB1 peripheral reset register (RCC_APB1RSTR)", .name = "apb1rstr", .offset_bytes = 0x20, .reset_value = 0x00000000, - .readable_bits = 0xF6FEC9FF, - .writable_bits = 0xF6FEC9FF, }, + .readable_bits = 0x10E2C80F, + .writable_bits = 0x10E2C80F, }, { .desc = "RCC APB2 peripheral reset register (RCC_APB2RSTR)", .name = "apb2rstr", .offset_bytes = 0x24, .reset_value = 0x00000000, - .readable_bits = 0x04777933, - .writable_bits = 0x04777933, }, + .readable_bits = 0x00177931, + .writable_bits = 0x00177931, }, { .desc = "RCC AHB1 peripheral clock enable register (RCC_AHB1ENR)", .name = "ahb1enr", .offset_bytes = 0x30, - .reset_value = 0x00100000, - .readable_bits = 0x7EFC17FF, - .writable_bits = 0x7EFC17FF, }, + .reset_value = 0x00000000, + .readable_bits = 0x0050101F, + .writable_bits = 0x0050101F, }, { .desc = "RCC AHB2 peripheral clock enable register (RCC_AHB2ENR)", .name = "ahb2enr", .offset_bytes = 0x34, - .reset_value = 0x00100000, - .readable_bits = 0x000000F1, - .writable_bits = 0x000000F1, }, - { - .desc = - "RCC AHB3 peripheral clock enable register (RCC_AHB3ENR)", - .name = "ahb3enr", - .offset_bytes = 0x38, - .reset_value = 0x00100000, - .readable_bits = 0x00000001, - .writable_bits = 0x00000001, }, + .reset_value = 0x00000000, + .readable_bits = 0x00000080, + .writable_bits = 0x00000080, }, { .desc = "APB1 peripheral clock enable register (RCC_APB1ENR)", .name = "apb1enr", .offset_bytes = 0x40, .reset_value = 0x00000000, - .readable_bits = 0xF6FEC9FF, - .writable_bits = 0xF6FEC9FF, }, + .readable_bits = 0x10E2C80F, + .writable_bits = 0x10E2C80F, }, { .desc = "APB2 peripheral clock enable register (RCC_APB2ENR)", .name = "apb2enr", .offset_bytes = 0x44, .reset_value = 0x00000000, - .readable_bits = 0x04777F33, - .writable_bits = 0x04777F33, }, + .readable_bits = 0x00177931, + .writable_bits = 0x00177931, }, { .desc = "RCC AHB1 peripheral clock enable in low power mode register (RCC_AHB1LPENR)", .name = "ahb1lpenr", .offset_bytes = 0x50, - .reset_value = 0x7E6791FF, - .readable_bits = 0x7EEF9EFF, - .writable_bits = 0x7EEF9EFF, }, + .reset_value = 0x0061900F, + .readable_bits = 0x0061909F, + .writable_bits = 0x0061909F, }, { .desc = "RCC AHB2 peripheral clock enable in low power mode register (RCC_AHB2LPENR)", .name = "ahb2lpenr", .offset_bytes = 0x54, - .reset_value = 0x000000F1, - .readable_bits = 0x000000F1, - .writable_bits = 0x000000F1, }, - { - .desc = - "RCC AHB3 peripheral clock enable in low power mode register (RCC_AHB3LPENR)", - .name = "ahb3lpenr", - .offset_bytes = 0x58, - .reset_value = 0x00000001, - .readable_bits = 0x00000001, - .writable_bits = 0x00000001, }, + .reset_value = 0x00000080, + .readable_bits = 0x00000080, + .writable_bits = 0x00000080, }, { .desc = "RCC APB1 peripheral clock enable in low power mode register (RCC_APB1LPENR)", .name = "apb1lpenr", .offset_bytes = 0x60, - .reset_value = 0x36FEC9FF, - .readable_bits = 0xFEFEC9FF, - .writable_bits = 0xFEFEC9FF, }, + .reset_value = 0x10E2C80F, + .readable_bits = 0x10E2C80F, + .writable_bits = 0x10E2C80F, }, { .desc = "RCC APB2 peripheral clock enable in low power mode register (RCC_APB2LPENR)", .name = "apb2lpenr", .offset_bytes = 0x64, - .reset_value = 0x00075F33, - .readable_bits = 0x04777F33, - .writable_bits = 0x04777F33, }, + .reset_value = 0x00077930, + .readable_bits = 0x00179F31, + .writable_bits = 0x00179F31, }, { .desc = "RCC Backup domain control register (RCC_BDCR)", @@ -2570,6 +2518,11 @@ static PeripheralInfo stm32f4_23_xxx_rcc_info = .desc = "External low-speed oscillator bypass", .first_bit = 2, }, + { + .name = "lsemod", + .desc = + "External low-speed oscillator bypass", + .first_bit = 3, }, { .name = "rtcsel", .desc = @@ -2657,41 +2610,33 @@ static PeripheralInfo stm32f4_23_xxx_rcc_info = .name = "sscgr", .offset_bytes = 0x80, .reset_value = 0x00000000, - .readable_bits = 0xCEFFFFFF, - .writable_bits = 0xCEFFFFFF, }, + .readable_bits = 0xE0FFFFFF, + .writable_bits = 0xE0FFFFFF, }, { .desc = "RCC PLLI2S configuration register (RCC_PLLI2SCFGR)", .name = "plli2scfgr", .offset_bytes = 0x84, - .reset_value = 0x20003000, - .readable_bits = 0x7F007FC0, - .writable_bits = 0x7F007FC0, }, - { - .desc = - "RCC PLLSAI configuration register (RCC_PLLI2SCFGR)", - .name = "pllsaicfgr", - .offset_bytes = 0x88, .reset_value = 0x24003000, - .readable_bits = 0x7F007FC0, - .writable_bits = 0x7F007FC0, }, + .readable_bits = 0x70007FFF, + .writable_bits = 0x70007FFF, }, { .desc = - "RCC Dedicated Clock Configuration Register (RCC_DCKCFGR)", - .name = "plldckcfgr", + "RCC Dedicated Clocks Configuration Register (RCC_DCKCFGR)", + .name = "dckcfgr", .offset_bytes = 0x8C, .reset_value = 0x00000000, - .readable_bits = 0x01F31F1F, - .writable_bits = 0x01F31F1F, }, + .readable_bits = 0x01000000, + .writable_bits = 0x01000000, }, { }, /**/ } , /**/ }; -static void stm32f4_23_xxx_rcc_create_objects(Object *obj) +static void stm32f411xx_rcc_create_objects(Object *obj) { STM32RCCState *state = STM32_RCC_STATE(obj); - peripheral_new_with_info(obj, NULL, &stm32f4_23_xxx_rcc_info); + peripheral_new_with_info(obj, NULL, &stm32f411xx_rcc_info); state->f4.reg.cr = cm_object_get_child_by_name(obj, "cr"); state->f4.reg.pllcfgr = cm_object_get_child_by_name(obj, "pllcfgr"); @@ -2699,26 +2644,20 @@ static void stm32f4_23_xxx_rcc_create_objects(Object *obj) state->f4.reg.cir = cm_object_get_child_by_name(obj, "cir"); state->f4.reg.ahb1rstr = cm_object_get_child_by_name(obj, "ahb1rstr"); state->f4.reg.ahb2rstr = cm_object_get_child_by_name(obj, "ahb2rstr"); - state->f4.reg.ahb3rstr = cm_object_get_child_by_name(obj, "ahb3rstr"); state->f4.reg.apb1rstr = cm_object_get_child_by_name(obj, "apb1rstr"); state->f4.reg.apb2rstr = cm_object_get_child_by_name(obj, "apb2rstr"); state->f4.reg.ahb1enr = cm_object_get_child_by_name(obj, "ahb1enr"); state->f4.reg.ahb2enr = cm_object_get_child_by_name(obj, "ahb2enr"); - state->f4.reg.ahb3enr = cm_object_get_child_by_name(obj, "ahb3enr"); state->f4.reg.apb1enr = cm_object_get_child_by_name(obj, "apb1enr"); state->f4.reg.apb2enr = cm_object_get_child_by_name(obj, "apb2enr"); state->f4.reg.ahb1lpenr = cm_object_get_child_by_name(obj, "ahb1lpenr"); state->f4.reg.ahb2lpenr = cm_object_get_child_by_name(obj, "ahb2lpenr"); - state->f4.reg.ahb3lpenr = cm_object_get_child_by_name(obj, "ahb3lpenr"); state->f4.reg.apb1lpenr = cm_object_get_child_by_name(obj, "apb1lpenr"); state->f4.reg.apb2lpenr = cm_object_get_child_by_name(obj, "apb2lpenr"); state->f4.reg.bdcr = cm_object_get_child_by_name(obj, "bdcr"); state->f4.reg.csr = cm_object_get_child_by_name(obj, "csr"); state->f4.reg.bdcr = cm_object_get_child_by_name(obj, "bdcr"); state->f4.reg.sscgr = cm_object_get_child_by_name(obj, "sscgr"); - state->f4.reg.plli2scfgr = cm_object_get_child_by_name(obj, "plli2scfgr"); - state->f4.reg.pllsaicfgr = cm_object_get_child_by_name(obj, "pllsaicfgr"); - state->f4.reg.plldckcfgr = cm_object_get_child_by_name(obj, "plldckcfgr"); /* CR bitfields. */ state->f4.fld.cr.hsion = cm_object_get_child_by_name(state->f4.reg.cr, @@ -2745,10 +2684,6 @@ static void stm32f4_23_xxx_rcc_create_objects(Object *obj) "plli2son"); state->f4.fld.cr.plli2srdy = cm_object_get_child_by_name(state->f4.reg.cr, "plli2srdy"); - state->f4.fld.cr.pllsaion = cm_object_get_child_by_name(state->f4.reg.cr, - "pllsaion"); - state->f4.fld.cr.pllsairdy = cm_object_get_child_by_name(state->f4.reg.cr, - "pllsairdy"); /* PLLCFGR bitfields. */ state->f4.fld.pllcfgr.pllm = cm_object_get_child_by_name( @@ -2799,8 +2734,6 @@ static void stm32f4_23_xxx_rcc_create_objects(Object *obj) "pllrdyf"); state->f4.fld.cir.plli2srdyf = cm_object_get_child_by_name( state->f4.reg.cir, "plli2srdyf"); - state->f4.fld.cir.pllsairdyf = cm_object_get_child_by_name( - state->f4.reg.cir, "pllsairdyf"); state->f4.fld.cir.cssf = cm_object_get_child_by_name(state->f4.reg.cir, "cssf"); @@ -2811,8 +2744,6 @@ static void stm32f4_23_xxx_rcc_create_objects(Object *obj) /* CSR bitfields. */ state->f4.fld.csr.lsirdy = cm_object_get_child_by_name(state->f4.reg.csr, "lsirdy"); - state->f4.fld.csr.borrstf = cm_object_get_child_by_name(state->f4.reg.csr, - "borrstf"); state->f4.fld.csr.pinrstf = cm_object_get_child_by_name(state->f4.reg.csr, "pinrstf"); state->f4.fld.csr.porrstf = cm_object_get_child_by_name(state->f4.reg.csr, @@ -2830,131 +2761,913 @@ static void stm32f4_23_xxx_rcc_create_objects(Object *obj) /* ------------------------------------------------------------------------- */ -static uint8_t AHBPrescTable[16] = { - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 2, - 3, - 4, - 6, - 7, - 8, - 9 }; - -extern int system_clock_scale; - -/* ------------------------------------------------------------------------- */ - -static void stm32_rcc_post_write_callback(Object *reg, Object *periph, - uint32_t addr, uint32_t offset, unsigned size, - peripheral_register_t value) -{ - STM32RCCState *state = STM32_RCC_STATE(periph); - stm32_rcc_update_clocks(state); -} - -/** - * Recompute the system clock, after each change in the RCC registers. - * The code is inspired by CMSIS init sequences. - */ -static void stm32_rcc_update_clocks(STM32RCCState *state) -{ - const STM32Capabilities *capabilities = state->capabilities; - - uint32_t cpu_freq_hz = 0; - uint32_t pre_scaler; - - switch (capabilities->family) { - case STM32_FAMILY_F1: - - /* The following code was copied from the CMSIS system_stm32f10x.c */ - - switch (register_bitfield_read_value(state->f1.cfgr.sws)) { - case 0: - /* HSI used as system clock. */ - cpu_freq_hz = state->hsi_freq_hz; - break; - - case 1: - /* HSE used as system clock. */ - cpu_freq_hz = state->hse_freq_hz; - break; - - case 2: - /* PLL used as system clock. */ - if (!capabilities->f1.is_cl) { - /* Most F1 families, except CL. */ - - /* Get PLL clock source and multiplication factor. */ - uint32_t pllmul = register_bitfield_read_value( - state->f1.cfgr.pllmul) + 2; - if (register_bitfield_is_zero(state->f1.cfgr.pllsrc)) { - /* HSI oscillator clock divided by 2 selected as PLL - * clock entry */ - cpu_freq_hz = (state->hsi_freq_hz >> 1) * pllmul; - } else { - if (capabilities->f1.is_ldvl || capabilities->f1.is_mdvl - || capabilities->f1.is_hdvl) { - /* The value line families use the CFGR2. */ - uint32_t prediv1factor = 0; - prediv1factor = register_bitfield_read_value( - state->f1.cfgr2.prediv1) + 1; - /* - * HSE oscillator clock selected as PREDIV1 - * clock entry. - */ - cpu_freq_hz = (state->hse_freq_hz / prediv1factor) - * pllmul; - } else { - /* HSE selected as PLL clock entry. */ - if (!register_bitfield_is_zero( - state->f1.cfgr.pllxtpre)) { - /* HSE oscillator clock divided by 2. */ - cpu_freq_hz = (state->hse_freq_hz >> 1) * pllmul; - } else { - cpu_freq_hz = state->hse_freq_hz * pllmul; - } - } - } - } else { - /* The F1 CL family. */ - uint32_t pllmul = register_bitfield_read_value( - state->f1.cfgr.pllmul); - - if (pllmul != 13) { - pllmul += 2; - } else { - /* PLL multiplication factor = PLL input clock * 6.5 */ - pllmul = 13 / 2; - } +/* STM32F4_23_xxx */ - if (register_bitfield_is_zero(state->f1.cfgr.pllsrc)) { - /* - * HSI oscillator clock divided by 2 selected as PLL - * clock entry. - */ - cpu_freq_hz = (state->hsi_freq_hz >> 1) * pllmul; - } else { - /* - * PREDIV1 selected as PLL clock entry. - * Get PREDIV1 clock source and division factor. - */ - uint32_t prediv1factor = register_bitfield_read_value( - state->f1.cfgr2.prediv1) + 1; +static PeripheralInfo stm32f4_23_xxx_rcc_info = + { + .desc = "Reset and clock control (RCC)", - if (register_bitfield_is_zero(state->f1.cfgr2.prediv1src)) { - /* - * HSE oscillator clock selected as PREDIV1 - * clock entry. - */ - cpu_freq_hz = (state->hse_freq_hz / prediv1factor) + .registers = + (PeripheralRegisterInfo[] ) { + { + .desc = "Clock control register (RCC_CR)", + .name = "cr", + .offset_bytes = 0x00, + .reset_value = 0x00000083, + .reset_mask = 0xFFFF00FF, + .bitfields = + (RegisterBitfieldInfo[] ) { + { + .name = "hsion", + .desc = + "Internal high-speed clock enable", + .first_bit = 0, }, + { + .name = "hsirdy", + .desc = + "Internal high-speed clock ready flag", + .first_bit = 1, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { + .name = "hsitrim", + .desc = + "Internal high-speed clock trimming", + .first_bit = 3, + .width_bits = 5, }, + { + .name = "hsical", + .desc = + "Internal high-speed clock calibration", + .first_bit = 8, + .width_bits = 8, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { + .name = "hseon", + .desc = + "External clock enable", + .first_bit = 16, }, + { + .name = "hserdy", + .desc = + "External high-speed clock ready flag", + .first_bit = 17, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { + .name = "hsebyp", + .desc = + "External high-speed clock bypass", + .first_bit = 18, }, + { + .name = "csson", + .desc = + "Clock security system enable", + .first_bit = 19, }, + { + .name = "pllon", + .desc = "PLL enable", + .first_bit = 24, }, + { + .name = "pllrdy", + .desc = + "PLL clock ready flag", + .first_bit = 25, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { + .name = "plli2son", + .desc = + "PLL I2S enable", + .first_bit = 26, }, + { + .name = "plli2srdy", + .desc = + "PLL I2S clock ready flag", + .first_bit = 27, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { + .name = "pllsaion", + .desc = + "PLL SAI enable", + .first_bit = 28, }, + { + .name = "pllsairdy", + .desc = + "PLL SAI clock ready flag", + .first_bit = 29, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { }, /**/ + } , /**/}, + { + .desc = + "RCC PLL configuration register (RCC_PLLCFGR)", + .name = "pllcfgr", + .offset_bytes = 0x04, + .reset_value = 0x24003010, + .readable_bits = 0x0F437FFF, + .writable_bits = 0x0F437FFF, + .bitfields = + (RegisterBitfieldInfo[] ) { + { + .name = "pllm", + .desc = + "PLL division factor", + .first_bit = 0, + .width_bits = 6, }, + { + .name = "plln", + .desc = + "PLL multiplication factor", + .first_bit = 6, + .width_bits = 9, }, + { + .name = "pllp", + .desc = + "Main PLL (PLL) division factor", + .first_bit = 16, + .width_bits = 2, }, + { + .name = "pllsrc", + .desc = + "Main PLL (PLL) clock source", + .first_bit = 22, }, + { + .name = "pllq", + .desc = + "Main PLL (PLL) division factor", + .first_bit = 24, + .width_bits = 4, }, + { }, } , }, + { + .desc = + "RCC clock configuration register (RCC_CFGR)", + .name = "cfgr", + .offset_bytes = 0x08, + .reset_value = 0x00000000, + .bitfields = + (RegisterBitfieldInfo[] ) { + { + .name = "sw", + .desc = + "System clock switch", + .first_bit = 0, + .width_bits = 2, }, + { + .name = "sws", + .desc = + "System clock switch status", + .first_bit = 2, + .width_bits = 2, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { + .name = "hpre", + .desc = + "AHB prescaler", + .first_bit = 4, + .width_bits = 4, }, + { + .name = "ppre1", + .desc = + "APB Low speed prescaler (APB1)", + .first_bit = 10, + .width_bits = 3, }, + { + .name = "ppre2", + .desc = + "APB high speed prescaler (APB2)", + .first_bit = 13, + .width_bits = 3, }, + { + .name = "rtcpre", + .desc = + "HSE division factor for RTC clock", + .first_bit = 16, + .width_bits = 5, }, + { + .name = "mco1", + .desc = + "Microcontroller clock output 1", + .first_bit = 21, + .width_bits = 2, }, + { + .name = "i2ssrc", + .desc = + "I2S clock selection", + .first_bit = 23, }, + { + .name = "mco1pre", + .desc = + "MCO1 prescaller", + .first_bit = 24, + .width_bits = 3, }, + { + .name = "mco2pre", + .desc = + "MCO2 prescaller", + .first_bit = 27, + .width_bits = 3, }, + { + .name = "mco2", + .desc = + "Microcontroller clock output 2", + .first_bit = 30, + .width_bits = 2, }, + { }, /**/ + } , /**/}, + { + .desc = "Clock interrupt register (RCC_CIR)", + .name = "cir", + .offset_bytes = 0x0C, + .reset_value = 0x00000000, + .bitfields = + (RegisterBitfieldInfo[] ) { + { + .name = "lsirdyf", + .desc = + "LSI ready interrupt flag", + .first_bit = 0, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { + .name = "lserdyf", + .desc = + "LSE ready interrupt flag", + .first_bit = 1, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { + .name = "hsirdyf", + .desc = + "HSI ready interrupt flag", + .first_bit = 2, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { + .name = "hserdyf", + .desc = + "HSE ready interrupt flag", + .first_bit = 3, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { + .name = "pllrdyf", + .desc = + "PLL ready interrupt flag", + .first_bit = 4, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { + .name = "plli2srdyf", + .desc = + "PLL I2S ready interrupt flag", + .first_bit = 5, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { + .name = "pllsairdyf", + .desc = + "PLL SAI ready interrupt flag", + .first_bit = 6, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { + .name = "cssf", + .desc = + "Clock security system interrupt flag", + .first_bit = 7, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { + .name = "lsirdyie", + .desc = + "LSI ready interrupt enable", + .first_bit = 8, }, + { + .name = "lserdyie", + .desc = + "LSE ready interrupt enable", + .first_bit = 9, }, + { + .name = "hsirdyie", + .desc = + "HSI ready interrupt enable", + .first_bit = 10, }, + { + .name = "hserdyie", + .desc = + "HSE ready interrupt enable", + .first_bit = 11, }, + { + .name = "pllrdyie", + .desc = + "PLL ready interrupt enable", + .first_bit = 12, }, + { + .name = + "plli2srdyie", + .desc = + "PLL I2S ready interrupt enable", + .first_bit = 13, }, + { + .name = + "pllsairdyie", + .desc = + "PLL SAI ready interrupt enable", + .first_bit = 14, }, + { + .name = "lsirdyc", + .desc = + "LSI ready interrupt clear", + .first_bit = 16, + .rw_mode = + REGISTER_RW_MODE_WRITE, }, + { + .name = "lserdyc", + .desc = + "LSE ready interrupt clear", + .first_bit = 17, + .rw_mode = + REGISTER_RW_MODE_WRITE, }, + { + .name = "hsirdyc", + .desc = + "HSI ready interrupt clear", + .first_bit = 18, + .rw_mode = + REGISTER_RW_MODE_WRITE, }, + { + .name = "hserdyc", + .desc = + "HSE ready interrupt clear", + .first_bit = 19, + .rw_mode = + REGISTER_RW_MODE_WRITE, }, + { + .name = "pllrdyc", + .desc = + "PLL ready interrupt clear", + .first_bit = 20, + .rw_mode = + REGISTER_RW_MODE_WRITE, }, + { + .name = "plli2srdyc", + .desc = + "PLL I2S ready interrupt clear", + .first_bit = 21, + .rw_mode = + REGISTER_RW_MODE_WRITE, }, + { + .name = "pllsairdyc", + .desc = + "PLL SAI ready interrupt clear", + .first_bit = 22, + .rw_mode = + REGISTER_RW_MODE_WRITE, }, + { + .name = "cssc", + .desc = + "Clock security system interrupt clear", + .first_bit = 23, + .rw_mode = + REGISTER_RW_MODE_WRITE, }, + { }, /**/ + } , /**/ + }, + { + .desc = + "RCC AHB1 peripheral reset register (RCC_AHB1RSTR)", + .name = "ahb1rstr", + .offset_bytes = 0x10, + .reset_value = 0x00000000, + .readable_bits = 0x22E017FF, + .writable_bits = 0x22E017FF, }, + { + .desc = + "RCC AHB2 peripheral reset register (RCC_AHB2RSTR)", + .name = "ahb2rstr", + .offset_bytes = 0x14, + .reset_value = 0x00000000, + .readable_bits = 0x000000F1, + .writable_bits = 0x000000F1, }, + { + .desc = + "RCC AHB3 peripheral reset register (RCC_AHB3RSTR)", + .name = "ahb3rstr", + .offset_bytes = 0x18, + .reset_value = 0x00000000, + .readable_bits = 0x00000001, + .writable_bits = 0x00000001, }, + { + .desc = + "RCC APB1 peripheral reset register (RCC_APB1RSTR)", + .name = "apb1rstr", + .offset_bytes = 0x20, + .reset_value = 0x00000000, + .readable_bits = 0xF6FEC9FF, + .writable_bits = 0xF6FEC9FF, }, + { + .desc = + "RCC APB2 peripheral reset register (RCC_APB2RSTR)", + .name = "apb2rstr", + .offset_bytes = 0x24, + .reset_value = 0x00000000, + .readable_bits = 0x04777933, + .writable_bits = 0x04777933, }, + { + .desc = + "RCC AHB1 peripheral clock enable register (RCC_AHB1ENR)", + .name = "ahb1enr", + .offset_bytes = 0x30, + .reset_value = 0x00100000, + .readable_bits = 0x7EFC17FF, + .writable_bits = 0x7EFC17FF, }, + { + .desc = + "RCC AHB2 peripheral clock enable register (RCC_AHB2ENR)", + .name = "ahb2enr", + .offset_bytes = 0x34, + .reset_value = 0x00100000, + .readable_bits = 0x000000F1, + .writable_bits = 0x000000F1, }, + { + .desc = + "RCC AHB3 peripheral clock enable register (RCC_AHB3ENR)", + .name = "ahb3enr", + .offset_bytes = 0x38, + .reset_value = 0x00100000, + .readable_bits = 0x00000001, + .writable_bits = 0x00000001, }, + { + .desc = + "APB1 peripheral clock enable register (RCC_APB1ENR)", + .name = "apb1enr", + .offset_bytes = 0x40, + .reset_value = 0x00000000, + .readable_bits = 0xF6FEC9FF, + .writable_bits = 0xF6FEC9FF, }, + { + .desc = + "APB2 peripheral clock enable register (RCC_APB2ENR)", + .name = "apb2enr", + .offset_bytes = 0x44, + .reset_value = 0x00000000, + .readable_bits = 0x04777F33, + .writable_bits = 0x04777F33, }, + { + .desc = + "RCC AHB1 peripheral clock enable in low power mode register (RCC_AHB1LPENR)", + .name = "ahb1lpenr", + .offset_bytes = 0x50, + .reset_value = 0x7E6791FF, + .readable_bits = 0x7EEF9EFF, + .writable_bits = 0x7EEF9EFF, }, + { + .desc = + "RCC AHB2 peripheral clock enable in low power mode register (RCC_AHB2LPENR)", + .name = "ahb2lpenr", + .offset_bytes = 0x54, + .reset_value = 0x000000F1, + .readable_bits = 0x000000F1, + .writable_bits = 0x000000F1, }, + { + .desc = + "RCC AHB3 peripheral clock enable in low power mode register (RCC_AHB3LPENR)", + .name = "ahb3lpenr", + .offset_bytes = 0x58, + .reset_value = 0x00000001, + .readable_bits = 0x00000001, + .writable_bits = 0x00000001, }, + { + .desc = + "RCC APB1 peripheral clock enable in low power mode register (RCC_APB1LPENR)", + .name = "apb1lpenr", + .offset_bytes = 0x60, + .reset_value = 0x36FEC9FF, + .readable_bits = 0xFEFEC9FF, + .writable_bits = 0xFEFEC9FF, }, + { + .desc = + "RCC APB2 peripheral clock enable in low power mode register (RCC_APB2LPENR)", + .name = "apb2lpenr", + .offset_bytes = 0x64, + .reset_value = 0x00075F33, + .readable_bits = 0x04777F33, + .writable_bits = 0x04777F33, }, + { + .desc = + "RCC Backup domain control register (RCC_BDCR)", + .name = "bdcr", + .offset_bytes = 0x70, + .reset_value = 0x00000000, + .bitfields = + (RegisterBitfieldInfo[] ) { + { + .name = "lseon", + .desc = + "External low-speed oscillator enable", + .first_bit = 0, }, + { + .name = "lserdy", + .desc = + "External low-speed oscillator ready", + .first_bit = 1, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { + .name = "lsebyp", + .desc = + "External low-speed oscillator bypass", + .first_bit = 2, }, + { + .name = "rtcsel", + .desc = + "RTC clock source selection", + .first_bit = 8, + .width_bits = 2, }, + { + .name = "rtcen", + .desc = + "RTC clock enable", + .first_bit = 15, }, + { + .name = "bdrst", + .desc = + "Backup domain software reset", + .first_bit = 16, }, + { }, /**/ + } , /**/ + }, + { + .desc = "Control/status register (RCC_CSR)", + .name = "csr", + .offset_bytes = 0x74, + .reset_value = 0x0E000000, + .bitfields = + (RegisterBitfieldInfo[] ) { + { + .name = "lsion", + .desc = + "Internal low-speed oscillator enable", + .first_bit = 0, }, + { + .name = "lsirdy", + .desc = + "Internal low-speed oscillator ready", + .first_bit = 1, + .rw_mode = + REGISTER_RW_MODE_READ, }, + { + .name = "rmvf", + .desc = + "Remove reset flag", + .first_bit = 24, }, + { + .name = "borrstf", + .desc = + "BOR reset flag", + .first_bit = 25, }, + { + .name = "pinrstf", + .desc = + "PIN reset flag", + .first_bit = 26, }, + { + .name = "porrstf", + .desc = + "POR/PDR reset flag", + .first_bit = 27, }, + { + .name = "stfrstf", + .desc = + "Software reset flag", + .first_bit = 28, }, + { + .name = "iwdgrstf", + .desc = + "Independent watchdog reset flag", + .first_bit = 29, }, + { + .name = "wwdgrstf", + .desc = + "Window watchdog reset flag", + .first_bit = 30, }, + { + .name = "lpwrrstf", + .desc = + "Low-power reset flag", + .first_bit = 31, }, + { }, /**/ + } , /**/ + }, + { + .desc = + "RCC spread spectrum clock generation register (RCC_SSCGR)", + .name = "sscgr", + .offset_bytes = 0x80, + .reset_value = 0x00000000, + .readable_bits = 0xCEFFFFFF, + .writable_bits = 0xCEFFFFFF, }, + { + .desc = + "RCC PLLI2S configuration register (RCC_PLLI2SCFGR)", + .name = "plli2scfgr", + .offset_bytes = 0x84, + .reset_value = 0x20003000, + .readable_bits = 0x7F007FC0, + .writable_bits = 0x7F007FC0, }, + { + .desc = + "RCC PLLSAI configuration register (RCC_PLLI2SCFGR)", + .name = "pllsaicfgr", + .offset_bytes = 0x88, + .reset_value = 0x24003000, + .readable_bits = 0x7F007FC0, + .writable_bits = 0x7F007FC0, }, + { + .desc = + "RCC Dedicated Clock Configuration Register (RCC_DCKCFGR)", + .name = "plldckcfgr", + .offset_bytes = 0x8C, + .reset_value = 0x00000000, + .readable_bits = 0x01F31F1F, + .writable_bits = 0x01F31F1F, }, + { }, /**/ + } , /**/ + }; + +static void stm32f4_23_xxx_rcc_create_objects(Object *obj) +{ + STM32RCCState *state = STM32_RCC_STATE(obj); + + peripheral_new_with_info(obj, NULL, &stm32f4_23_xxx_rcc_info); + + state->f4.reg.cr = cm_object_get_child_by_name(obj, "cr"); + state->f4.reg.pllcfgr = cm_object_get_child_by_name(obj, "pllcfgr"); + state->f4.reg.cfgr = cm_object_get_child_by_name(obj, "cfgr"); + state->f4.reg.cir = cm_object_get_child_by_name(obj, "cir"); + state->f4.reg.ahb1rstr = cm_object_get_child_by_name(obj, "ahb1rstr"); + state->f4.reg.ahb2rstr = cm_object_get_child_by_name(obj, "ahb2rstr"); + state->f4.reg.ahb3rstr = cm_object_get_child_by_name(obj, "ahb3rstr"); + state->f4.reg.apb1rstr = cm_object_get_child_by_name(obj, "apb1rstr"); + state->f4.reg.apb2rstr = cm_object_get_child_by_name(obj, "apb2rstr"); + state->f4.reg.ahb1enr = cm_object_get_child_by_name(obj, "ahb1enr"); + state->f4.reg.ahb2enr = cm_object_get_child_by_name(obj, "ahb2enr"); + state->f4.reg.ahb3enr = cm_object_get_child_by_name(obj, "ahb3enr"); + state->f4.reg.apb1enr = cm_object_get_child_by_name(obj, "apb1enr"); + state->f4.reg.apb2enr = cm_object_get_child_by_name(obj, "apb2enr"); + state->f4.reg.ahb1lpenr = cm_object_get_child_by_name(obj, "ahb1lpenr"); + state->f4.reg.ahb2lpenr = cm_object_get_child_by_name(obj, "ahb2lpenr"); + state->f4.reg.ahb3lpenr = cm_object_get_child_by_name(obj, "ahb3lpenr"); + state->f4.reg.apb1lpenr = cm_object_get_child_by_name(obj, "apb1lpenr"); + state->f4.reg.apb2lpenr = cm_object_get_child_by_name(obj, "apb2lpenr"); + state->f4.reg.bdcr = cm_object_get_child_by_name(obj, "bdcr"); + state->f4.reg.csr = cm_object_get_child_by_name(obj, "csr"); + state->f4.reg.bdcr = cm_object_get_child_by_name(obj, "bdcr"); + state->f4.reg.sscgr = cm_object_get_child_by_name(obj, "sscgr"); + state->f4.reg.plli2scfgr = cm_object_get_child_by_name(obj, "plli2scfgr"); + state->f4.reg.pllsaicfgr = cm_object_get_child_by_name(obj, "pllsaicfgr"); + state->f4.reg.plldckcfgr = cm_object_get_child_by_name(obj, "plldckcfgr"); + + /* CR bitfields. */ + state->f4.fld.cr.hsion = cm_object_get_child_by_name(state->f4.reg.cr, + "hsion"); + state->f4.fld.cr.hsirdy = cm_object_get_child_by_name(state->f4.reg.cr, + "hsirdy"); + state->f4.fld.cr.hsitrim = cm_object_get_child_by_name(state->f4.reg.cr, + "hsitrim"); + state->f4.fld.cr.hsical = cm_object_get_child_by_name(state->f4.reg.cr, + "hsical"); + state->f4.fld.cr.hseon = cm_object_get_child_by_name(state->f4.reg.cr, + "hseon"); + state->f4.fld.cr.hserdy = cm_object_get_child_by_name(state->f4.reg.cr, + "hserdy"); + state->f4.fld.cr.hsebyp = cm_object_get_child_by_name(state->f4.reg.cr, + "hsebyp"); + state->f4.fld.cr.csson = cm_object_get_child_by_name(state->f4.reg.cr, + "csson"); + state->f4.fld.cr.pllon = cm_object_get_child_by_name(state->f4.reg.cr, + "pllon"); + state->f4.fld.cr.pllrdy = cm_object_get_child_by_name(state->f4.reg.cr, + "pllrdy"); + state->f4.fld.cr.plli2son = cm_object_get_child_by_name(state->f4.reg.cr, + "plli2son"); + state->f4.fld.cr.plli2srdy = cm_object_get_child_by_name(state->f4.reg.cr, + "plli2srdy"); + state->f4.fld.cr.pllsaion = cm_object_get_child_by_name(state->f4.reg.cr, + "pllsaion"); + state->f4.fld.cr.pllsairdy = cm_object_get_child_by_name(state->f4.reg.cr, + "pllsairdy"); + + /* PLLCFGR bitfields. */ + state->f4.fld.pllcfgr.pllm = cm_object_get_child_by_name( + state->f4.reg.pllcfgr, "pllm"); + state->f4.fld.pllcfgr.plln = cm_object_get_child_by_name( + state->f4.reg.pllcfgr, "plln"); + state->f4.fld.pllcfgr.pllp = cm_object_get_child_by_name( + state->f4.reg.pllcfgr, "pllp"); + state->f4.fld.pllcfgr.pllsrc = cm_object_get_child_by_name( + state->f4.reg.pllcfgr, "pllsrc"); + state->f4.fld.pllcfgr.pllq = cm_object_get_child_by_name( + state->f4.reg.pllcfgr, "pllq"); + + /* CFGR bitfields. */ + state->f4.fld.cfgr.sw = cm_object_get_child_by_name(state->f4.reg.cfgr, + "sw"); + state->f4.fld.cfgr.sws = cm_object_get_child_by_name(state->f4.reg.cfgr, + "sws"); + state->f4.fld.cfgr.hpre = cm_object_get_child_by_name(state->f4.reg.cfgr, + "hpre"); + state->f4.fld.cfgr.ppre1 = cm_object_get_child_by_name(state->f4.reg.cfgr, + "ppre1"); + state->f4.fld.cfgr.ppre2 = cm_object_get_child_by_name(state->f4.reg.cfgr, + "ppre2"); + state->f4.fld.cfgr.rtcpre = cm_object_get_child_by_name(state->f4.reg.cfgr, + "rtcpre"); + state->f4.fld.cfgr.mco1 = cm_object_get_child_by_name(state->f4.reg.cfgr, + "mco1"); + state->f4.fld.cfgr.i2ssrc = cm_object_get_child_by_name(state->f4.reg.cfgr, + "i2ssrc"); + state->f4.fld.cfgr.mco1pre = cm_object_get_child_by_name(state->f4.reg.cfgr, + "mco1pre"); + state->f4.fld.cfgr.mco2pre = cm_object_get_child_by_name(state->f4.reg.cfgr, + "mco2pre"); + state->f4.fld.cfgr.mco2 = cm_object_get_child_by_name(state->f4.reg.cfgr, + "mco2"); + + /* CIR bitfields. */ + state->f4.fld.cir.lsirdyf = cm_object_get_child_by_name(state->f4.reg.cir, + "lsirdyf"); + state->f4.fld.cir.lserdyf = cm_object_get_child_by_name(state->f4.reg.cir, + "lserdyf"); + state->f4.fld.cir.hsirdyf = cm_object_get_child_by_name(state->f4.reg.cir, + "hsirdyf"); + state->f4.fld.cir.hserdyf = cm_object_get_child_by_name(state->f4.reg.cir, + "hserdyf"); + state->f4.fld.cir.pllrdyf = cm_object_get_child_by_name(state->f4.reg.cir, + "pllrdyf"); + state->f4.fld.cir.plli2srdyf = cm_object_get_child_by_name( + state->f4.reg.cir, "plli2srdyf"); + state->f4.fld.cir.pllsairdyf = cm_object_get_child_by_name( + state->f4.reg.cir, "pllsairdyf"); + state->f4.fld.cir.cssf = cm_object_get_child_by_name(state->f4.reg.cir, + "cssf"); + + /* BDCR bitfields. */ + state->f4.fld.bdcr.lserdy = cm_object_get_child_by_name(state->f4.reg.bdcr, + "lserdy"); + + /* CSR bitfields. */ + state->f4.fld.csr.lsirdy = cm_object_get_child_by_name(state->f4.reg.csr, + "lsirdy"); + state->f4.fld.csr.borrstf = cm_object_get_child_by_name(state->f4.reg.csr, + "borrstf"); + state->f4.fld.csr.pinrstf = cm_object_get_child_by_name(state->f4.reg.csr, + "pinrstf"); + state->f4.fld.csr.porrstf = cm_object_get_child_by_name(state->f4.reg.csr, + "porrstf"); + state->f4.fld.csr.stfrstf = cm_object_get_child_by_name(state->f4.reg.csr, + "stfrstf"); + state->f4.fld.csr.iwdgrstf = cm_object_get_child_by_name(state->f4.reg.csr, + "iwdgrstf"); + state->f4.fld.csr.wwdgrstf = cm_object_get_child_by_name(state->f4.reg.csr, + "wwdgrstf"); + state->f4.fld.csr.lpwrrstf = cm_object_get_child_by_name(state->f4.reg.csr, + "lpwrrstf"); + +} + +/* ------------------------------------------------------------------------- */ + +static uint8_t AHBPrescTable[16] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 2, + 3, + 4, + 6, + 7, + 8, + 9 }; + +extern int system_clock_scale; + +/* ------------------------------------------------------------------------- */ + +static void stm32_rcc_post_write_callback(Object *reg, Object *periph, + uint32_t addr, uint32_t offset, unsigned size, + peripheral_register_t value) +{ + STM32RCCState *state = STM32_RCC_STATE(periph); + stm32_rcc_update_clocks(state); +} + +/** + * Recompute the system clock, after each change in the RCC registers. + * The code is inspired by CMSIS init sequences. + */ +static void stm32_rcc_update_clocks(STM32RCCState *state) +{ + const STM32Capabilities *capabilities = state->capabilities; + + uint32_t cpu_freq_hz = 0; + uint32_t pre_scaler; + + switch (capabilities->family) { + case STM32_FAMILY_F1: + + /* The following code was copied from the CMSIS system_stm32f10x.c */ + + switch (register_bitfield_read_value(state->f1.cfgr.sws)) { + case 0: + /* HSI used as system clock. */ + cpu_freq_hz = state->hsi_freq_hz; + break; + + case 1: + /* HSE used as system clock. */ + cpu_freq_hz = state->hse_freq_hz; + break; + + case 2: + /* PLL used as system clock. */ + if (!capabilities->f1.is_cl) { + /* Most F1 families, except CL. */ + + /* Get PLL clock source and multiplication factor. */ + uint32_t pllmul = register_bitfield_read_value( + state->f1.cfgr.pllmul) + 2; + if (register_bitfield_is_zero(state->f1.cfgr.pllsrc)) { + /* HSI oscillator clock divided by 2 selected as PLL + * clock entry */ + cpu_freq_hz = (state->hsi_freq_hz >> 1) * pllmul; + } else { + if (capabilities->f1.is_ldvl || capabilities->f1.is_mdvl + || capabilities->f1.is_hdvl) { + /* The value line families use the CFGR2. */ + uint32_t prediv1factor = 0; + prediv1factor = register_bitfield_read_value( + state->f1.cfgr2.prediv1) + 1; + /* + * HSE oscillator clock selected as PREDIV1 + * clock entry. + */ + cpu_freq_hz = (state->hse_freq_hz / prediv1factor) + * pllmul; + } else { + /* HSE selected as PLL clock entry. */ + if (!register_bitfield_is_zero( + state->f1.cfgr.pllxtpre)) { + /* HSE oscillator clock divided by 2. */ + cpu_freq_hz = (state->hse_freq_hz >> 1) * pllmul; + } else { + cpu_freq_hz = state->hse_freq_hz * pllmul; + } + } + } + } else { + /* The F1 CL family. */ + uint32_t pllmul = register_bitfield_read_value( + state->f1.cfgr.pllmul); + + if (pllmul != 13) { + pllmul += 2; + } else { + /* PLL multiplication factor = PLL input clock * 6.5 */ + pllmul = 13 / 2; + } + + if (register_bitfield_is_zero(state->f1.cfgr.pllsrc)) { + /* + * HSI oscillator clock divided by 2 selected as PLL + * clock entry. + */ + cpu_freq_hz = (state->hsi_freq_hz >> 1) * pllmul; + } else { + /* + * PREDIV1 selected as PLL clock entry. + * Get PREDIV1 clock source and division factor. + */ + uint32_t prediv1factor = register_bitfield_read_value( + state->f1.cfgr2.prediv1) + 1; + + if (register_bitfield_is_zero(state->f1.cfgr2.prediv1src)) { + /* + * HSE oscillator clock selected as PREDIV1 + * clock entry. + */ + cpu_freq_hz = (state->hse_freq_hz / prediv1factor) * pllmul; } else { /* @@ -3073,16 +3786,16 @@ static void stm32_rcc_instance_init_callback(Object *obj) STM32RCCState *state = STM32_RCC_STATE(obj); cm_object_property_add_uint32(obj, "hse-freq-hz", &state->hse_freq_hz); - state->hse_freq_hz = DEFAULT_HSE_FREQ_HZ; + state->hse_freq_hz = 0; /* No HSE */ cm_object_property_add_uint32(obj, "lse-freq-hz", &state->lse_freq_hz); - state->lse_freq_hz = DEFAULT_RTC_FREQ_HZ; + state->lse_freq_hz = 0; /* No LSE */ cm_object_property_add_uint32(obj, "hsi-freq-hz", &state->hsi_freq_hz); - state->hsi_freq_hz = HSI_FREQ_HZ; + state->hsi_freq_hz = 0; cm_object_property_add_uint32(obj, "lsi-freq-hz", &state->lsi_freq_hz); - state->lsi_freq_hz = LSI_FREQ_HZ; + state->lsi_freq_hz = 0; } static void stm32_rcc_realize_callback(DeviceState *dev, Error **errp) @@ -3132,13 +3845,16 @@ static void stm32_rcc_realize_callback(DeviceState *dev, Error **errp) cm_object_property_set_int(obj, addr, "mmio-address"); cm_object_property_set_int(obj, size, "mmio-size-bytes"); + assert(capabilities->hsi_freq_hz); + assert(capabilities->lsi_freq_hz); + /* Set defaults, need to be non-zero */ if (state->hsi_freq_hz == 0) { - state->hsi_freq_hz = HSI_FREQ_HZ; + state->hsi_freq_hz = capabilities->hsi_freq_hz; } if (state->lsi_freq_hz == 0) { - state->lsi_freq_hz = LSI_FREQ_HZ; + state->lsi_freq_hz = capabilities->lsi_freq_hz; } switch (capabilities->family) { @@ -3325,6 +4041,64 @@ static void stm32_rcc_realize_callback(DeviceState *dev, Error **errp) "cleared-by"); cm_object_property_set_str(state->f4.fld.csr.lpwrrstf, "rmvf", "cleared-by"); + + } else if (capabilities->f4.is11xx) { + + stm32f411xx_rcc_create_objects(obj); + + /* Add callbacks. */ + peripheral_register_set_post_write(state->f4.reg.pllcfgr, + &stm32_rcc_post_write_callback); + peripheral_register_set_post_write(state->f4.reg.cfgr, + &stm32_rcc_post_write_callback); + + /* Auto bits. */ + cm_object_property_set_str(state->f4.fld.cr.hsirdy, "hsion", + "follows"); + if (state->hse_freq_hz) { + cm_object_property_set_str(state->f4.fld.cr.hserdy, "hseon", + "follows"); + } + cm_object_property_set_str(state->f4.fld.cr.pllrdy, "pllon", + "follows"); + cm_object_property_set_str(state->f4.fld.cr.plli2srdy, "plli2son", + "follows"); + + cm_object_property_set_str(state->f4.fld.cfgr.sws, "sw", "follows"); + + cm_object_property_set_str(state->f4.fld.cir.lsirdyf, "lsirdyc", + "cleared-by"); + cm_object_property_set_str(state->f4.fld.cir.lserdyf, "lserdyc", + "cleared-by"); + cm_object_property_set_str(state->f4.fld.cir.hsirdyf, "hsirdyc", + "cleared-by"); + cm_object_property_set_str(state->f4.fld.cir.hserdyf, "hserdyc", + "cleared-by"); + cm_object_property_set_str(state->f4.fld.cir.pllrdyf, "pllrdyc", + "cleared-by"); + cm_object_property_set_str(state->f4.fld.cir.plli2srdyf, + "plli2srdyc", "cleared-by"); + cm_object_property_set_str(state->f4.fld.cir.cssf, "cssc", + "cleared-by"); + + cm_object_property_set_str(state->f4.fld.bdcr.lserdy, "lseon", + "follows"); + + cm_object_property_set_str(state->f4.fld.csr.lsirdy, "lsion", + "follows"); + cm_object_property_set_str(state->f4.fld.csr.pinrstf, "rmvf", + "cleared-by"); + cm_object_property_set_str(state->f4.fld.csr.porrstf, "rmvf", + "cleared-by"); + cm_object_property_set_str(state->f4.fld.csr.stfrstf, "rmvf", + "cleared-by"); + cm_object_property_set_str(state->f4.fld.csr.iwdgrstf, "rmvf", + "cleared-by"); + cm_object_property_set_str(state->f4.fld.csr.wwdgrstf, "rmvf", + "cleared-by"); + cm_object_property_set_str(state->f4.fld.csr.lpwrrstf, "rmvf", + "cleared-by"); + } else if (capabilities->f4.is_23_xxx) { stm32f4_23_xxx_rcc_create_objects(obj); diff --git a/include/hw/arm/stm32-capabilities.h b/include/hw/arm/stm32-capabilities.h index e3f581411f..d9f1be10f3 100644 --- a/include/hw/arm/stm32-capabilities.h +++ b/include/hw/arm/stm32-capabilities.h @@ -134,6 +134,8 @@ typedef struct { unsigned int has_spi1 :1; unsigned int has_spi2 :1; unsigned int has_spi3 :1; + unsigned int has_spi4 :1; + unsigned int has_spi5 :1; /* I2S */ unsigned int has_i2s1 :1; @@ -210,6 +212,7 @@ typedef struct { struct { unsigned int is_01_57_xx :1; unsigned int is_23_xxx :1; + unsigned int is11xx :1; } f4; /* TODO: add other families that have sub-families. */ diff --git a/include/hw/misc/stm32-rcc.h b/include/hw/misc/stm32-rcc.h index e16add1563..1db043a33f 100644 --- a/include/hw/misc/stm32-rcc.h +++ b/include/hw/misc/stm32-rcc.h @@ -25,18 +25,6 @@ /* ------------------------------------------------------------------------- */ -/* The high speed internal clock frequency. */ -#define HSI_FREQ_HZ (8000000) -/* The low speed internal clock frequency. */ -#define LSI_FREQ_HZ (40000) - -/* No external oscillator */ -#define DEFAULT_HSE_FREQ_HZ (0) -/* No RTC */ -#define DEFAULT_RTC_FREQ_HZ (0) - -/* ------------------------------------------------------------------------- */ - #define TYPE_STM32_RCC TYPE_STM32_PREFIX "rcc" TYPE_PERIPHERAL_SUFFIX /* ------------------------------------------------------------------------- */