diff --git a/README.md b/README.md index 49f7dbc..f3efa65 100644 --- a/README.md +++ b/README.md @@ -49,9 +49,7 @@ Date: 20240312 - Configure the additional registers for peripherals like USART and I2C on the PY32F072, which has more registers compared to version 1 (F030). -- Set up configurations for cut-down variants such as PY32F003, PY32F002A, and PY32F040. - -- Extend USB `FRAMENUM` and `OUTCOUNT` Fields to 11 bits. +- Set up configurations for cut-down variants such as PY32F003, PY32F002A, PY32F040. ## Contirbute diff --git a/data/af/PY32F030.yaml b/data/af/PY32F030.yaml index b6b1d30..783a352 100644 --- a/data/af/PY32F030.yaml +++ b/data/af/PY32F030.yaml @@ -543,7 +543,7 @@ USART2: - af: 4 pin: PF3 signal: TX -ADC: +ADC1: - pin: PA0 signal: IN0 - pin: PA1 diff --git a/data/af/PY32F07X.yaml b/data/af/PY32F07X.yaml index dd0af0d..2f4479e 100644 --- a/data/af/PY32F07X.yaml +++ b/data/af/PY32F07X.yaml @@ -778,7 +778,7 @@ USART4: - af: 0 pin: PC12 signal: CK -ADC: +ADC1: - pin: PA0 signal: IN0 - pin: PA1 diff --git a/data/chips/PY32F030F16.yaml b/data/chips/PY32F030F16.yaml index 7b33e83..db932f3 100644 --- a/data/chips/PY32F030F16.yaml +++ b/data/chips/PY32F030F16.yaml @@ -50,7 +50,10 @@ cores: include_peripherals: - "../peripherals/F030.yaml" include_afs: "../af/PY32F030.yaml" - dma_channels: + include_dma_channels: + DMA1_CH1: "../dma_channels/PY32F030.yaml" + DMA1_CH2: "../dma_channels/PY32F030.yaml" + DMA1_CH3: "../dma_channels/PY32F030.yaml" _raw: 12bitADCUnitsCHs: 1(2+2) 12bitDACUnitsCHs: '-' diff --git a/data/chips/PY32F030K28.yaml b/data/chips/PY32F030K28.yaml index 6fe66cf..ff5a9c7 100644 --- a/data/chips/PY32F030K28.yaml +++ b/data/chips/PY32F030K28.yaml @@ -51,7 +51,10 @@ cores: include_peripherals: - "../peripherals/F030.yaml" include_afs: "../af/PY32F030.yaml" - dma_channels: + include_dma_channels: + DMA1_CH1: "../dma_channels/PY32F030.yaml" + DMA1_CH2: "../dma_channels/PY32F030.yaml" + DMA1_CH3: "../dma_channels/PY32F030.yaml" _raw: 12bitADCUnitsCHs: 1(10+2) 12bitDACUnitsCHs: '-' diff --git a/data/chips/PY32F072C1B.yaml b/data/chips/PY32F072C1B.yaml index 3455e46..9196330 100644 --- a/data/chips/PY32F072C1B.yaml +++ b/data/chips/PY32F072C1B.yaml @@ -57,7 +57,14 @@ cores: include_peripherals: - "../peripherals/F072.yaml" include_afs: "../af/PY32F07X.yaml" - dma_channels: + include_dma_channels: + DMA1_CH1: "../dma_channels/PY32F072.yaml" + DMA1_CH2: "../dma_channels/PY32F072.yaml" + DMA1_CH3: "../dma_channels/PY32F072.yaml" + DMA1_CH4: "../dma_channels/PY32F072.yaml" + DMA1_CH5: "../dma_channels/PY32F072.yaml" + DMA1_CH6: "../dma_channels/PY32F072.yaml" + DMA1_CH7: "../dma_channels/PY32F072.yaml" _raw: 12bitADCUnitsCHs: 1(13+8) 12bitDACUnitsCHs: 1(2) diff --git a/data/dma_channels/PY32F030.yaml b/data/dma_channels/PY32F030.yaml new file mode 100644 index 0000000..42d17ca --- /dev/null +++ b/data/dma_channels/PY32F030.yaml @@ -0,0 +1,27 @@ +ADC1: 0 +SPI1_TX: 1 +SPI1_RX: 2 +SPI2_TX: 3 +SPI2_RX: 4 +USART1_TX: 5 +USART1_RX: 6 +USART2_TX: 7 +USART2_RX: 8 +I2C1_TX: 9 +I2C1_RX: 10 +TIM1_CH1: 11 +TIM1_CH2: 12 +TIM1_CH3: 13 +TIM1_CH4: 14 +TIM1_COM: 15 +TIM1_UP: 16 +TIM1_TRIG: 17 +TIM3_CH1: 18 +TIM3_CH3: 19 +TIM3_CH4: 20 +TIM3_TRG: 21 +TIM3_UP: 22 +TIM16_CH1: 24 +TIM16_UP: 25 +TIM17_CH1: 26 +TIM17_UP: 27 \ No newline at end of file diff --git a/data/dma_channels/PY32F072.yaml b/data/dma_channels/PY32F072.yaml new file mode 100644 index 0000000..fc93675 --- /dev/null +++ b/data/dma_channels/PY32F072.yaml @@ -0,0 +1,51 @@ +ADC1: 0 +DAC1: 1 +DAC2: 2 +SPI1_RX: 3 +SPI1_TX: 4 +SPI2_RX: 5 +SPI2_TX: 6 +USART1_RX: 7 +USART1_TX: 8 +USART2_RX: 9 +USART2_TX: 10 +USART3_RX: 11 +USART3_TX: 12 +USART4_RX: 13 +USART4_TX: 14 +I2C1_RX: 15 +I2C1_TX: 16 +I2C2_RX: 17 +I2C2_TX: 18 +TIM1_CH1: 19 +TIM1_CH2: 20 +TIM1_CH3: 21 +TIM1_CH4: 22 +TIM1_COM: 23 +TIM1_TRIG: 24 +TIM1_UP: 25 +TIM2_CH1: 26 +TIM2_CH2: 27 +TIM2_CH3: 28 +TIM2_CH4: 29 +TIM2_UP: 30 +TIM2_TRG: 31 +TIM3_CH1: 32 +TIM3_CH2: 33 +TIM3_CH3: 34 +TIM3_CH4: 35 +TIM3_UP: 36 +TIM3_TRIG: 37 +TIM6_UP: 38 +TIM7_UP: 39 +TIM15_CH1: 40 +TIM15_CH2: 41 +TIM15_UP: 42 +TIM15_TRIG: 43 +TIM15_COM: 44 +TIM16_CH1: 45 +TIM16_UP: 46 +TIM17_CH1: 47 +TIM17_UP: 48 +USB: 49 +LCD: 50 \ No newline at end of file diff --git a/data/dma_channels/PY32F403.yaml b/data/dma_channels/PY32F403.yaml new file mode 100644 index 0000000..058d487 --- /dev/null +++ b/data/dma_channels/PY32F403.yaml @@ -0,0 +1,67 @@ +ADC1: 0 +ADC2: 1 +ADC3: 2 +SPI1_RX: 5 +SPI1_TX: 6 +SPI2_RX: 7 +SPI2_TX: 8 +SPI3_RX: 9 +SPI3_TX: 10 +USART1_RX: 11 +USART1_TX: 12 +USART2_RX: 13 +USART2_TX: 14 +USART3_RX: 15 +USART3_TX: 16 +USART4_RX: 17 +USART4_TX: 18 +USART5_RX: 19 +USART5_TX: 20 +I2C1_RX: 21 +I2C1_TX: 22 +I2C2_RX: 23 +I2C2_TX: 24 +TIM1_CH1: 25 +TIM1_CH2: 26 +TIM1_CH3: 27 +TIM1_CH4: 28 +TIM1_COM: 29 +TIM1_TRIG: 30 +TIM1_UP: 31 +TIM2_CH1: 32 +TIM2_CH2: 33 +TIM2_CH3: 34 +TIM2_CH4: 35 +TIM2_UP: 36 +TIM3_CH1: 37 +TIM3_CH3: 38 +TIM3_CH4: 39 +TIM3_UP: 40 +TIM3_TRIG: 41 +TIM4_CH1: 42 +TIM4_CH2: 43 +TIM4_CH3: 44 +TIM4_UP: 45 +TIM5_CH1: 46 +TIM5_CH2: 47 +TIM5_CH3: 48 +TIM5_CH4: 49 +TIM5_UP: 50 +TIM5_TRIG: 51 +TIM6: 52 +TIM7: 53 +TIM8_CH1: 54 +TIM8_CH2: 55 +TIM8_CH3: 56 +TIM8_CH4: 57 +TIM8_COM: 58 +TIM8_TRIG: 59 +TIM8_UP: 60 +TIM2_TRIG: 61 +TIM3_CH2: 62 +TIM4_CH4: 63 +TIM4_TRIG: 64 +ESMC_TX: 65 +ESMC_RX: 66 +SDIO: 67 +USB: 68 \ No newline at end of file diff --git a/data/peripherals/F030.yaml b/data/peripherals/F030.yaml index 6bd94e8..03d5648 100644 --- a/data/peripherals/F030.yaml +++ b/data/peripherals/F030.yaml @@ -1,4 +1,4 @@ -- name: ADC +- name: ADC1 address: 0x40012400 registers: kind: adc @@ -387,25 +387,7 @@ kind: timer version: v1 block: TIM_1CH_CMP - dma_channels: - - signal: CH1 - channel: DMA1_CH1 - request: 7 - - signal: UP - channel: DMA1_CH1 - request: 7 - - signal: CH1 - channel: DMA1_CH2 - request: 7 - - signal: UP - channel: DMA1_CH2 - request: 7 - - signal: CH1 - channel: DMA1_CH7 - request: 7 - - signal: UP - channel: DMA1_CH7 - request: 7 + rcc: bus_clock: PCLK1_TIM kernel_clock: PCLK1_TIM @@ -431,7 +413,7 @@ address: 0x40010000 registers: kind: syscfg - version: common + version: f030 block: SYSCFG rcc: bus_clock: PCLK1 @@ -443,15 +425,15 @@ register: APBRSTR2 field: SYSCFGRST -- name: DMA +- name: DMA1 address: 0x40020000 registers: kind: dma - version: common + version: f030 block: DMA rcc: - bus_clock: PCLK1 - kernel_clock: PCLK1 + bus_clock: HCLK1 + kernel_clock: HCLK1 enable: register: AHBENR field: DMAEN @@ -459,10 +441,12 @@ register: AHBRSTR field: DMARST interrupts: - - signal: GLOBAL - interrupt: DMA_Channel1 - - signal: GLOBAL - interrupt: DMA_Channel2_3 + - signal: CH1 + interrupt: DMA_Channel1 + - signal: CH2 + interrupt: DMA_Channel2_3 + - signal: CH3 + interrupt: DMA_Channel2_3 - name: FLASH address: 0x40022000 diff --git a/data/peripherals/F072.yaml b/data/peripherals/F072.yaml index 8a197a0..4e71552 100644 --- a/data/peripherals/F072.yaml +++ b/data/peripherals/F072.yaml @@ -1,5 +1,5 @@ -- name: ADC +- name: ADC1 address: 0x40012400 registers: kind: adc @@ -374,7 +374,7 @@ address: 0x40010000 registers: kind: syscfg - version: common + version: f072 block: SYSCFG rcc: bus_clock: PCLK1 @@ -744,6 +744,37 @@ - signal: WAKEUP interrupt: USB +- name: DMA1 + address: 0x40020000 + registers: + kind: dma + version: f072 + block: DMA + rcc: + bus_clock: HCLK1 + kernel_clock: HCLK1 + enable: + register: AHBENR + field: DMAEN + reset: + register: AHBRSTR + field: DMARST + interrupts: + - signal: CH1 + interrupt: DMA1_Channel1 + - signal: CH2 + interrupt: DMA1_Channel2_3 + - signal: CH3 + interrupt: DMA1_Channel2_3 + - signal: CH4 + interrupt: DMA1_Channel4_5_6_7 + - signal: CH5 + interrupt: DMA1_Channel4_5_6_7 + - signal: CH6 + interrupt: DMA1_Channel4_5_6_7 + - signal: CH7 + interrupt: DMA1_Channel4_5_6_7 + - name: CONFIGBYTES address: 0x1fff3200 registers: diff --git a/data/registers/adc_v2.yaml b/data/registers/adc_v2.yaml index 7ae25ba..11dc0a4 100644 --- a/data/registers/adc_v2.yaml +++ b/data/registers/adc_v2.yaml @@ -164,7 +164,7 @@ fieldset/CR1: description: desc ADSTP. bit_offset: 27 bit_size: 1 - - name: OVETIE + - name: OVRIE description: Overrun interrupt enable bit_offset: 29 bit_size: 1 diff --git a/data/registers/dma_v1.yaml b/data/registers/dma_f030.yaml similarity index 98% rename from data/registers/dma_v1.yaml rename to data/registers/dma_f030.yaml index 3e66cef..65f857f 100644 --- a/data/registers/dma_v1.yaml +++ b/data/registers/dma_f030.yaml @@ -103,7 +103,7 @@ fieldset/IXR: - 8 - name: TCIF description: Channel x Transfer Complete. flag. - bit_offset: 1 + bit_offset: 0 bit_size: 1 array: offsets: @@ -112,7 +112,7 @@ fieldset/IXR: - 9 - name: HTIF description: Channel x Half Transfer Complete. flag. - bit_offset: 2 + bit_offset: 0 bit_size: 1 array: offsets: @@ -121,7 +121,7 @@ fieldset/IXR: - 10 - name: TEIF description: Channel x Transfer Error. flag. - bit_offset: 3 + bit_offset: 0 bit_size: 1 array: offsets: diff --git a/data/registers/dma_f072.yaml b/data/registers/dma_f072.yaml new file mode 100644 index 0000000..f1de78a --- /dev/null +++ b/data/registers/dma_f072.yaml @@ -0,0 +1,187 @@ +block/DMA: + description: Direct memory access. + items: + - name: ISR + description: DMA interrupt status register (DMA_ISR). + byte_offset: 0 + access: Read + fieldset: IXR + - name: IFCR + description: DMA interrupt flag clear register (DMA_IFCR). + byte_offset: 4 + access: Write + fieldset: IXR + - name: ST + description: 'Stream cluster: S?CR, S?NDTR, S?M0AR, S?PAR and S?MAR registers' + array: + len: 7 + # len: 3 + stride: 20 + byte_offset: 8 + block: ST +block/ST: + description: 'Stream cluster: S?CR, S?NDTR, S?M0AR, S?PAR and S?MAR registers' + items: + - name: CR + description: DMA channel x configuration register (DMA_CCR). + byte_offset: 0 + fieldset: CR + - name: NDTR + description: DMA channel x number of data register. + byte_offset: 4 + - name: PAR + description: DMA channel x peripheral address register. + byte_offset: 8 + - name: MAR + description: DMA channel x memory address register. + byte_offset: 12 +fieldset/CR: + description: DMA channel configuration register (DMA_CCR). + fields: + - name: EN + description: Channel enable. + bit_offset: 0 + bit_size: 1 + - name: TCIE + description: Transfer complete interrupt enable. + bit_offset: 1 + bit_size: 1 + - name: HTIE + description: Half Transfer interrupt enable. + bit_offset: 2 + bit_size: 1 + - name: TEIE + description: Transfer error interrupt enable. + bit_offset: 3 + bit_size: 1 + - name: DIR + description: Data transfer direction. + bit_offset: 4 + bit_size: 1 + enum: DIR + - name: CIRC + description: Circular mode. + bit_offset: 5 + bit_size: 1 + - name: PINC + description: Peripheral increment mode. + bit_offset: 6 + bit_size: 1 + - name: MINC + description: Memory increment mode. + bit_offset: 7 + bit_size: 1 + - name: PSIZE + description: Peripheral size. + bit_offset: 8 + bit_size: 2 + enum: SIZE + - name: MSIZE + description: Memory size. + bit_offset: 10 + bit_size: 2 + enum: SIZE + - name: PL + description: Channel Priority level. + bit_offset: 12 + bit_size: 2 + enum: PL + - name: MEM2MEM + description: Memory to memory mode. + bit_offset: 14 + bit_size: 1 +fieldset/IXR: + description: DMA interrupt register. + fields: + - name: GIF + description: Channel 1 Global interrupt flag. + bit_offset: 0 + bit_size: 1 + array: + offsets: + - 0 + - 4 + - 8 + - 12 + - 16 + - 20 + - 24 + - name: TCIF + description: Channel x Transfer Complete. flag. + bit_offset: 0 + bit_size: 1 + array: + offsets: + - 1 + - 5 + - 9 + - 13 + - 17 + - 21 + - 25 + - name: HTIF + description: Channel x Half Transfer Complete. flag. + bit_offset: 0 + bit_size: 1 + array: + offsets: + - 2 + - 6 + - 10 + - 14 + - 18 + - 22 + - 26 + - name: TEIF + description: Channel x Transfer Error. flag. + bit_offset: 0 + bit_size: 1 + array: + offsets: + - 3 + - 7 + - 11 + - 15 + - 19 + - 23 + - 27 + +enum/PL: + bit_size: 2 + variants: + - name: Low + description: Low + value: 0 + - name: Medium + description: Medium + value: 1 + - name: High + description: High + value: 2 + - name: VeryHigh + description: Very high + value: 3 +enum/SIZE: + bit_size: 2 + variants: + - name: Bits8 + description: Byte (8-bit) + value: 0 + - name: Bits16 + description: Half-word (16-bit) + value: 1 + - name: Bits32 + description: Word (32-bit) + value: 2 +enum/DIR: + bit_size: 1 + variants: + - name: PeripheralToMemory + description: Peripheral-to-memory + value: 0 + - name: MemoryToPeripheral + description: Memory-to-peripheral + value: 1 + # - name: MemoryToMemory + # description: Memory-to-memory + # value: 2 \ No newline at end of file diff --git a/data/registers/syscfg_f030.yaml b/data/registers/syscfg_f030.yaml new file mode 100644 index 0000000..ed3dcd5 --- /dev/null +++ b/data/registers/syscfg_f030.yaml @@ -0,0 +1,123 @@ +block/SYSCFG: + description: System configuration controller. + items: + - name: CFGR1 + description: SYSCFG configuration register. 1. + byte_offset: 0 + fieldset: CFGR1 + - name: CFGR2 + description: SYSCFG configuration register. 2. + byte_offset: 24 + fieldset: CFGR2 + - name: CFGR3 + description: SYSCFG configuration register. 3. + byte_offset: 28 + fieldset: CFGR3 +fieldset/CFGR1: + description: SYSCFG configuration register. 1. + fields: + - name: MEM_MODE + description: Memory mapping selection. bits. + bit_offset: 0 + bit_size: 2 + - name: I2C_PA2_ANF + description: Analog filter enable control driving capability. activation bits PA2. + bit_offset: 18 + bit_size: 1 + - name: I2C_PA3_ANF + description: Analog filter enable control driving capability. activation bits PA3. + bit_offset: 19 + bit_size: 1 + - name: I2C_PA7_ANF + description: Analog filter enable control driving capability. activation bits PA7. + bit_offset: 20 + bit_size: 1 + - name: I2C_PA8_ANF + description: Analog filter enable control driving capability. activation bits PA8. + bit_offset: 21 + bit_size: 1 + - name: I2C_PA9_ANF + description: Analog filter enable control driving capability. activation bits PA9. + bit_offset: 22 + bit_size: 1 + - name: I2C_PA10_ANF + description: Analog filter enable control driving capability. activation bits PA10. + bit_offset: 23 + bit_size: 1 + - name: I2C_PA11_ANF + description: Analog filter enable control driving capability. activation bits PA11. + bit_offset: 24 + bit_size: 1 + - name: I2C_PA12_ANF + description: Analog filter enable control driving capability. activation bits PA12. + bit_offset: 25 + bit_size: 1 + - name: I2C_PB6_ANF + description: Analog filter enable control driving capability. activation bits PB6. + bit_offset: 26 + bit_size: 1 + - name: I2C_PB7_ANF + description: Analog filter enable control driving capability. activation bits PB7. + bit_offset: 27 + bit_size: 1 + - name: I2C_PB8_ANF + description: Analog filter enable control driving capability. activation bits PB8. + bit_offset: 28 + bit_size: 1 + - name: I2C_PF0_ANF + description: Analog filter enable control driving capability. activation bits PF0. + bit_offset: 29 + bit_size: 1 + - name: I2C_PF1_ANF + description: Analog filter enable control driving capability. activation bits PF1. + bit_offset: 30 + bit_size: 1 +fieldset/CFGR2: + description: SYSCFG configuration register. 2. + fields: + - name: LOCKUP_LOCK + description: Cortex-M0+ LOCKUP bit enable. bit. + bit_offset: 0 + bit_size: 1 + - name: PVD_LOCK + description: PVD lock enable bit. + bit_offset: 2 + bit_size: 1 + - name: COMP1_BRK_TIM1 + description: COMP1 is enable to input of TIM1 break. + bit_offset: 3 + bit_size: 1 + - name: COMP2_BRK_TIM1 + description: COMP2 is enable to input of TIM1 break. + bit_offset: 4 + bit_size: 1 + - name: COMP1_BRK_TIM16 + description: COMP1 is enable to input of TIM16 break. + bit_offset: 5 + bit_size: 1 + - name: COMP2_BRK_TIM16 + description: COMP2 is enable to input of TIM16 break. + bit_offset: 6 + bit_size: 1 + - name: COMP1_BRK_TIM17 + description: COMP1 is enable to input of TIM17 break. + bit_offset: 7 + bit_size: 1 + - name: COMP2_BRK_TIM17 + description: COMP2 is enable to input of TIM17 break. + bit_offset: 8 + bit_size: 1 + - name: ETR_SRC_TIM1 + description: TIM1 ETR source selection. + bit_offset: 9 + bit_size: 2 +fieldset/CFGR3: + description: SYSCFG configuration register 3. + fields: + - name: DMA_MAP + description: DMA channel x requeset selection. + array: + len: 3 + stride: 8 + bit_offset: 0 + bit_size: 5 diff --git a/data/registers/syscfg_f072.yaml b/data/registers/syscfg_f072.yaml new file mode 100644 index 0000000..149f98e --- /dev/null +++ b/data/registers/syscfg_f072.yaml @@ -0,0 +1,213 @@ +block/SYSCFG: + description: desc SYSCFG. + items: + - name: CFGR1 + description: desc CFGR1. + byte_offset: 0 + fieldset: CFGR1 + - name: CFGR2 + description: desc CFGR2. + byte_offset: 4 + fieldset: CFGR2 + - name: CFGR3 + description: desc CFGR3. + byte_offset: 8 + fieldset: CFGR3 + - name: CFGR4 + description: desc CFGR4. + byte_offset: 12 + fieldset: CFGR4 + - name: PAENS + description: desc PAENS. + byte_offset: 16 + fieldset: PAENS + - name: PBENS + description: desc PBENS. + byte_offset: 20 + fieldset: PBENS + - name: PCENS + description: desc PCENS. + byte_offset: 24 + fieldset: PCENS + - name: PFENS + description: desc PFENS. + byte_offset: 28 + fieldset: PFENS +fieldset/CFGR1: + description: desc CFGR1. + fields: + - name: MEM_MODE + description: desc MEM_MODE. + bit_offset: 0 + bit_size: 2 + - name: TIM1_IC1_SRC + description: desc TIM1_IC1_SRC. + bit_offset: 2 + bit_size: 2 + - name: TIM2_IC4_SRC + description: desc TIM2_IC4_SRC. + bit_offset: 4 + bit_size: 2 + - name: TIM3_IC1_SRC + description: desc TIM3_IC1_SRC. + bit_offset: 6 + bit_size: 2 + - name: ETR_SRC_TIM1 + description: desc ETR_SRC_TIM1. + bit_offset: 8 + bit_size: 3 + - name: ETR_SRC_TIM2 + description: desc ETR_SRC_TIM2. + bit_offset: 12 + bit_size: 3 + - name: ETR_SRC_TIM3 + description: desc ETR_SRC_TIM3. + bit_offset: 16 + bit_size: 3 + - name: GPIO_AHB_SEL + description: desc GPIO_AHB_SEL. + bit_offset: 24 + bit_size: 1 +fieldset/CFGR2: + description: desc CFGR2. + fields: + - name: LOCKUP_LOCK + description: desc LOCKUP_LOCK. + bit_offset: 0 + bit_size: 1 + - name: PVD_LOCK + description: desc PVD_LOCK. + bit_offset: 2 + bit_size: 1 + - name: COMP1_BRK_TIM1 + description: desc COMP1_BRK_TIM1. + bit_offset: 3 + bit_size: 1 + - name: COMP2_BRK_TIM1 + description: desc COMP2_BRK_TIM1. + bit_offset: 4 + bit_size: 1 + - name: COMP3_BRK_TIM1 + description: desc COMP3_BRK_TIM1. + bit_offset: 5 + bit_size: 1 + - name: COMP1_BRK_TIM15 + description: desc COMP1_BRK_TIM15. + bit_offset: 6 + bit_size: 1 + - name: COMP2_BRK_TIM15 + description: desc COMP2_BRK_TIM15. + bit_offset: 7 + bit_size: 1 + - name: COMP3_BRK_TIM15 + description: desc COMP3_BRK_TIM15. + bit_offset: 8 + bit_size: 1 + - name: COMP1_BRK_TIM16 + description: desc COMP1_BRK_TIM16. + bit_offset: 9 + bit_size: 1 + - name: COMP2_BRK_TIM16 + description: desc COMP2_BRK_TIM16. + bit_offset: 10 + bit_size: 1 + - name: COMP3_BRK_TIM16 + description: desc COMP3_BRK_TIM16. + bit_offset: 11 + bit_size: 1 + - name: COMP1_BRK_TIM17 + description: desc COMP1_BRK_TIM17. + bit_offset: 12 + bit_size: 1 + - name: COMP2_BRK_TIM17 + description: desc COMP2_BRK_TIM17. + bit_offset: 13 + bit_size: 1 + - name: COMP3_BRK_TIM17 + description: desc COMP3_BRK_TIM17. + bit_offset: 14 + bit_size: 1 + - name: COMP1_OCREF_CLR_TIM1 + description: desc COMP1_OCREF_CLR_TIM1. + bit_offset: 15 + bit_size: 1 + - name: COMP1_OCREF_CLR_TIM2 + description: desc COMP1_OCREF_CLR_TIM2. + bit_offset: 16 + bit_size: 1 + - name: COMP1_OCREF_CLR_TIM3 + description: desc COMP1_OCREF_CLR_TIM3. + bit_offset: 17 + bit_size: 1 + - name: COMP2_OCREF_CLR_TIM1 + description: desc COMP2_OCREF_CLR_TIM1. + bit_offset: 18 + bit_size: 1 + - name: COMP2_OCREF_CLR_TIM2 + description: desc COMP2_OCREF_CLR_TIM2. + bit_offset: 19 + bit_size: 1 + - name: COMP2_OCREF_CLR_TIM3 + description: desc COMP2_OCREF_CLR_TIM3. + bit_offset: 20 + bit_size: 1 + - name: COMP3_OCREF_CLR_TIM1 + description: desc COMP3_OCREF_CLR_TIM1. + bit_offset: 21 + bit_size: 1 + - name: COMP3_OCREF_CLR_TIM2 + description: desc COMP3_OCREF_CLR_TIM2. + bit_offset: 22 + bit_size: 1 + - name: COMP3_OCREF_CLR_TIM3 + description: desc COMP3_OCREF_CLR_TIM3. + bit_offset: 23 + bit_size: 1 +fieldset/CFGR3: + description: desc CFGR3. + fields: + - name: DMA_MAP + description: DMA channel 1-4 requeset selection. + array: + len: 4 + stride: 8 + bit_offset: 0 + bit_size: 6 +fieldset/CFGR4: + description: desc CFGR4. + fields: + - name: DMA_MAP + description: DMA channel 5-7 requeset selection. + array: + len: 3 + stride: 8 + bit_offset: 0 + bit_size: 6 +fieldset/PAENS: + description: desc PAENS. + fields: + - name: PA_ENS + description: desc PA_ENS. + bit_offset: 0 + bit_size: 16 +fieldset/PBENS: + description: desc PBENS. + fields: + - name: PB_ENS + description: desc PB_ENS. + bit_offset: 0 + bit_size: 16 +fieldset/PCENS: + description: desc PCENS. + fields: + - name: PC_ENS + description: desc PC_ENS. + bit_offset: 0 + bit_size: 16 +fieldset/PFENS: + description: desc PFENS. + fields: + - name: PF_ENS + description: desc PF_ENS. + bit_offset: 0 + bit_size: 16 diff --git a/peripheral_version.md b/peripheral_version.md index 0324d85..3d7c4fa 100644 --- a/peripheral_version.md +++ b/peripheral_version.md @@ -1,28 +1,24 @@ # Peripheral Version -| Chip\Peripheral | RCC | GPIO | TIMER | DMA | I2C | ADC | EXTI | USART | -| --------------- | ---- | ---- | ----- | --- | --- | --- | ---- | ----- | -| F002B | | v1 | v1 | | v1 | v1 | v1 | | -| F030/F003/F002A | f030 | v1 | v1 | v1 | v1 | v1 | v1 | v1 | -| F040/F07x/MD410 | f072 | v1 | v1 | v1 | v1 | v2 | v1 | v1 | -| F403 | | v1 | v1 | | | v2 | v2? | | +| Chip\Peripheral | RCC | GPIO | TIMER | DMA | I2C | ADC | EXTI | USART | SYSCFG | USB | SPI | +| --------------- | ----- | ---- | ----- | ---- | ---- | ---- | ---- | ----- | ------ | -------- | ---- | +| F002B | | v1 | v1 | | v1 | v1? | v1 | | | | | +| F030/F003/F002A | f030 | v1 | v1 | f030 | v1 | v1 | v1 | v1 | f030 | | v1 | +| F040/F07x/MD410 | f072 | v1 | v1 | f072 | v1 | v2 | v1 | v1 | f072 | py32f07x | | +| F403 | f403? | v1 | v1 | | | v2 | v2? | | | py32f403 | | -Degree of similarity to embassy-stm32 +Degree of IP Core similarity -| Peripheral | py32-hal | embassy-stm32 | similarity | -| ---------- | -------- | ------------- | ---------- | -| GPIO | v1 | v2 | A | -| RCC | f030 | f0 | B | -| TIMER | v1 | v1 | A | -| DMA | v1 | v1/v2 | C | -| ADC | v1 | v1 | C | -| ADC | v2 | v2 | C | -| I2C | v1 | v1 | B | -| EXTI | v1 | g0+u5 | A | -| USART | v1 | v2 | B | -| | | | | -| | | | | -| | | | | -| | | | | -| | | | | -| | | | | +| Peripheral | py32-hal | | similarity | +| ---------- | --------- | ------------------------------------------------------------ | ---------- | +| GPIO | v1 | embassy-stm32::gpio_v2 | A | +| RCC | f030/f072 | embassy-stm32::rcc_f0 | C | +| RCC | f403 | embassy-stm32::rcc_f1 | B | +| TIMER | v1 | embassy-stm32::timer_v1 | A | +| ADC | v1 | embassy-stm32::adc_v1 | C | +| ADC | v2 | embassy-stm32::adc_v2 | C | +| I2C | v1 | embassy-stm32::i2c_v1 | B | +| EXTI | v1 | embassy-stm32::exti_g0+u5 | A | +| USART | v1 | embassy-stm32::usart_v2 | B | +| USB | v1 | [musb](https://github.com/decaday/musb)::builtin-py32f07x/py32f403 | musb IP | +| | | | | diff --git a/py32-data-gen/src/chips.rs b/py32-data-gen/src/chips.rs deleted file mode 100644 index 7b620d7..0000000 --- a/py32-data-gen/src/chips.rs +++ /dev/null @@ -1,1556 +0,0 @@ -use std::collections::hash_map::Entry; -use std::collections::{HashMap, HashSet}; - -use py32_data_serde::chip::core::peripheral::Pin; - -use super::*; - -mod xml { - use serde::Deserialize; - - #[derive(Clone, Debug, Deserialize, PartialEq)] - pub struct Mcu { - #[serde(rename = "Family")] - pub family: String, - #[serde(rename = "Line")] - pub line: String, - #[serde(rename = "Die")] - pub die: String, - #[serde(rename = "RefName")] - pub ref_name: String, - #[serde(rename = "Package")] - pub package: String, - #[serde(rename = "Core")] - pub cores: Vec, - #[serde(rename = "Ram")] - pub rams: Vec, - #[serde(rename = "Flash")] - pub flashs: Vec, - #[serde(rename = "IP")] - pub ips: Vec, - #[serde(rename = "Pin")] - pub pins: Vec, - } - - #[derive(Clone, Debug, Deserialize, PartialEq)] - pub struct Pin { - #[serde(rename = "Name")] - pub name: String, - #[serde(rename = "Signal", default)] - pub signals: Vec, - } - - #[derive(Clone, Debug, Deserialize, PartialEq)] - pub struct PinSignal { - #[serde(rename = "Name")] - pub name: String, - } - - #[derive(Clone, Debug, Deserialize, PartialEq)] - pub struct Ip { - #[serde(rename = "InstanceName")] - pub instance_name: String, - #[serde(rename = "Name")] - pub name: String, - #[serde(rename = "Version")] - pub version: String, - } -} - -pub struct Chip { - flash: u32, - ram: u32, - group_idx: usize, - packages: Vec, -} - -pub struct ChipGroup { - chip_names: Vec, - xml: xml::Mcu, - pub ips: HashMap, - pins: HashMap, - family: Option, - line: Option, - die: Option, -} - -fn chip_name_from_package_name(x: &str) -> String { - let regexes = [ - (regex!("^(STM32L1....).x([AX])$"), "$1-$2"), - (regex!("^(STM32G0....).xN$"), "$1"), - (regex!("^(STM32F412..).xP$"), "$1"), - (regex!("^(STM32L4....).x[PS]$"), "$1"), - (regex!("^(STM32WB....).x[AE]$"), "$1"), - (regex!("^(STM32G0....).xN$"), "$1"), - (regex!("^(STM32L5....).x[PQ]$"), "$1"), - (regex!("^(STM32L0....).xS$"), "$1"), - (regex!("^(STM32H7....).xQ$"), "$1"), - (regex!("^(STM32U5....).xQ$"), "$1"), - (regex!("^(STM32H5....).xQ$"), "$1"), - (regex!("^(STM32WBA....).x$"), "$1"), - (regex!("^(STM32......).x$"), "$1"), - ]; - - regexes - .iter() - .find_map(|(a, b)| { - a.captures(x).map(|cap| { - let mut res = String::new(); - cap.expand(b, &mut res); - res - }) - }) - .unwrap_or_else(|| panic!("bad name: {x}")) -} - -struct PeriMatcher { - regexes: Vec<(regex::Regex, (&'static str, &'static str, &'static str))>, - cached: HashMap>, -} - -impl PeriMatcher { - fn new() -> Self { - const PERIMAP: &[(&str, (&str, &str, &str))] = &[ - (".*:USART:sci2_v1_1", ("usart", "v1", "USART")), - (".*:USART:sci2_v1_2_F1", ("usart", "v1", "USART")), - (".*:USART:sci2_v1_2", ("usart", "v2", "USART")), - (".*:USART:sci2_v2_0", ("usart", "v3", "USART")), - (".*:USART:sci2_v2_1", ("usart", "v3", "USART")), - (".*:USART:sci2_v2_2", ("usart", "v3", "USART")), - (".*:USART:sci3_v1_0", ("usart", "v3", "USART")), - (".*:USART:sci3_v1_1", ("usart", "v3", "USART")), - (".*:USART:sci3_v1_2", ("usart", "v4", "USART")), - (".*:USART:sci3_v2_0", ("usart", "v4", "USART")), - (".*:USART:sci3_v2_1", ("usart", "v4", "USART")), - (".*:UART:sci2_v1_1", ("usart", "v1", "USART")), - (".*:UART:sci2_v1_2_F4", ("usart", "v2", "USART")), - (".*:UART:sci2_v2_1", ("usart", "v3", "USART")), - (".*:UART:sci2_v3_0", ("usart", "v4", "USART")), - (".*:UART:sci2_v3_1", ("usart", "v4", "USART")), - (".*:LPUART:sci3_v1_1", ("usart", "v3", "LPUART")), - (".*:LPUART:sci3_v1_2", ("usart", "v4", "LPUART")), - (".*:LPUART:sci3_v1_3", ("usart", "v4", "LPUART")), - (".*:LPUART:sci3_v1_4", ("usart", "v4", "LPUART")), - ("STM32[HU]5.*:RNG:.*", ("rng", "v3", "RNG")), - ("STM32L5.*:RNG:.*", ("rng", "v2", "RNG")), - ("STM32L4[PQ]5.*:RNG:.*", ("rng", "v2", "RNG")), - ("STM32WL.*:RNG:.*", ("rng", "v2", "RNG")), - ("STM32F2.*:RNG:.*", ("rng", "v1", "RNG")), - ("STM32F4.*:RNG:.*", ("rng", "v1", "RNG")), - ("STM32F7.*:RNG:.*", ("rng", "v1", "RNG")), - ("STM32L0.*:RNG:.*", ("rng", "v1", "RNG")), - ("STM32L4.*:RNG:.*", ("rng", "v1", "RNG")), - ("STM32H7.*:RNG:.*", ("rng", "v1", "RNG")), - ("STM32G0.*:RNG:.*", ("rng", "v1", "RNG")), - ("STM32G4.*:RNG:.*", ("rng", "v1", "RNG")), - ("STM32WB.*:RNG:.*", ("rng", "v1", "RNG")), - ("STM32F7.*:AES:.*", ("aes", "f7", "AES")), - ("STM32F4.*:AES:.*", ("aes", "v1", "AES")), - ("STM32G0.*:AES:.*", ("aes", "v2", "AES")), - ("STM32G4.*:AES:.*", ("aes", "v2", "AES")), - ("STM32L0.*:AES:.*", ("aes", "v1", "AES")), - ("STM32L1.*:AES:.*", ("aes", "v1", "AES")), - ("STM32L4.*:AES:.*", ("aes", "v1", "AES")), - ("STM32L5.*:AES:.*", ("aes", "v2", "AES")), - ("STM32WL5.*:AES:.*", ("aes", "v2", "AES")), - ("STM32WLE.*:AES:.*", ("aes", "v2", "AES")), - ("STM32U5.*:AES:.*", ("aes", "v3a", "AES")), - ("STM32(H5|WBA).*:AES:.*", ("aes", "v3b", "AES")), - ("STM32(H5|WBA).*:SAES:.*", ("saes", "v1a", "SAES")), - ("STM32U5.*:SAES:.*", ("saes", "v1b", "SAES")), - (".*:SPI:spi2_v1_4", ("spi", "f1", "SPI")), - (".*:SPI:spi2s1_v2_1", ("spi", "v1", "SPI")), - (".*:SPI:spi2s1_v2_2", ("spi", "v1", "SPI")), - (".*:SPI:spi2s1_v2_3", ("spi", "v1", "SPI")), - (".*:SPI:spi2s1_v2_4", ("spi", "v1", "SPI")), - (".*:SPI:spi2s1_v3_0", ("spi", "v2", "SPI")), - (".*:SPI:spi2s1_v3_2", ("spi", "v2", "SPI")), - (".*:SPI:spi2s1_v3_3", ("spi", "v2", "SPI")), - (".*:SPI:spi2s1_v3_5", ("spi", "v2", "SPI")), - (".*:SUBGHZSPI:.*", ("spi", "v2", "SPI")), - (".*:SPI:spi2s1_v3_1", ("spi", "v2", "SPI")), - (".*:SPI:spi2s2_v1_1", ("spi", "v3", "SPI")), - (".*:SPI:spi2s2_v1_0", ("spi", "v3", "SPI")), - (".*:SPI:spi2s3_v2_1", ("spi", "v4", "SPI")), - (".*:SPI:spi2s3_v1_1", ("spi", "v5", "SPI")), - (".*:SPI:spi2s3_v2_0", ("spi", "v5", "SPI")), - (".*:FMAC:matrix1_v1_0", ("fmac", "v1", "FMAC")), - (".*:I2C:i2c1_v1_5", ("i2c", "v1", "I2C")), - (".*:I2C:i2c2_v1_1", ("i2c", "v2", "I2C")), - (".*:I2C:F0-i2c2_v1_1", ("i2c", "v2", "I2C")), - (".*:I2C:i2c2_v1_1F7", ("i2c", "v2", "I2C")), - (".*:I2C:i2c2_v1_1U5", ("i2c", "v2", "I2C")), - ("STM32F10[1357].*:DAC:dacif_v1_1F1", ("dac", "v1", "DAC")), // Original F1 are v1 - (".*:DAC:dacif_v1_1F1", ("dac", "v2", "DAC")), - (".*:DAC:F0dacif_v1_1", ("dac", "v2", "DAC")), - (".*:DAC:F3_dacif_v1_1", ("dac", "v2", "DAC")), - (".*:DAC:dacif_v1_1", ("dac", "v2", "DAC")), - (".*:DAC:dacif_v1_2", ("dac", "v2", "DAC")), - ("STM32L4[1-9A].*:DAC:dacif_v2_0", ("dac", "v3", "DAC")), // L4 non-plus are v3 - (".*:DAC:dacif_v2_0", ("dac", "v5", "DAC")), - (".*:DAC:dacif_v2_0_U5", ("dac", "v6", "DAC")), - (".*:DAC:dacif_v3_0", ("dac", "v4", "DAC")), - (".*:DAC:WL_dacif_v3_0", ("dac", "v4", "DAC")), - (".*:DAC:G4_dacif_v4_0", ("dac", "v7", "DAC")), - (".*:DAC:dacif_v5_0", ("dac", "v6", "DAC")), - (".*:ADC:aditf_v2_5F1", ("adc", "f1", "ADC")), - (".*:ADC:aditf5_v1_1", ("adc", "f3", "ADC")), - (".*:ADC:aditf_v2_5", ("adc", "f3_v2", "ADC")), - (".*:ADC:aditf3_v1_1", ("adc", "f3_v1_1", "ADC")), - (".*:ADC:aditf4_v1_1", ("adc", "v1", "ADC")), - (".*:ADC:aditf4_v2_0", ("adc", "l0", "ADC")), - (".*:ADC:aditf2_v1_1", ("adc", "v2", "ADC")), - (".*:ADC:aditf5_v2_0", ("adc", "v3", "ADC")), - (".*:ADC:aditf5_v2_2", ("adc", "v3", "ADC")), - (".*:ADC:aditf5_v3_0", ("adc", "v4", "ADC")), - (".*:ADC:aditf5_v3_0_H5", ("adc", "h5", "ADC")), - (".*:ADC:aditf5_v3_1", ("adc", "v4", "ADC")), - ("STM32WL5.*:ADC:.*", ("adc", "g0", "ADC")), - ("STM32WLE.*:ADC:.*", ("adc", "g0", "ADC")), - ("STM32G0.*:ADC:.*", ("adc", "g0", "ADC")), - ("STM32G0.*:ADC_COMMON:.*", ("adccommon", "v3", "ADC_COMMON")), - ("STM32G4.*:ADC:.*", ("adc", "v4", "ADC")), - ("STM32G4.*:ADC_COMMON:.*", ("adccommon", "v4", "ADC_COMMON")), - (".*:ADC_COMMON:aditf2_v1_1", ("adccommon", "v2", "ADC_COMMON")), - (".*:ADC_COMMON:aditf5_v2_0", ("adccommon", "v3", "ADC_COMMON")), - (".*:ADC_COMMON:aditf5_v2_2", ("adccommon", "v3", "ADC_COMMON")), - (".*:ADC_COMMON:aditf4_v3_0_WL", ("adccommon", "v3", "ADC_COMMON")), - (".*:ADC_COMMON:aditf5_v1_1", ("adccommon", "f3", "ADC_COMMON")), - (".*:ADC3_COMMON:aditf5_v1_1", ("adccommon", "f3", "ADC_COMMON")), - ( - "STM32H50.*:ADC_COMMON:aditf5_v3_0_H5", - ("adccommon", "h50", "ADC_COMMON"), - ), - ("STM32H5.*:ADC_COMMON:aditf5_v3_0_H5", ("adccommon", "h5", "ADC_COMMON")), - ("STM32H7.*:ADC_COMMON:.*", ("adccommon", "v4", "ADC_COMMON")), - ("STM32H7.*:ADC3_COMMON:.*", ("adccommon", "v4", "ADC_COMMON")), - ("STM32G4.*:OPAMP:G4_tsmc90_fastOpamp", ("opamp", "g4", "OPAMP")), - ("STM32F3.*:OPAMP:tsmc018_ull_opamp_v1_0", ("opamp", "f3", "OPAMP")), - (".*:DCMI:.*", ("dcmi", "v1", "DCMI")), - ("STM32C0.*:SYSCFG:.*", ("syscfg", "c0", "SYSCFG")), - ("STM32F0.*:SYSCFG:.*", ("syscfg", "f0", "SYSCFG")), - ("STM32F2.*:SYSCFG:.*", ("syscfg", "f2", "SYSCFG")), - ("STM32F3.*:SYSCFG:.*", ("syscfg", "f3", "SYSCFG")), - ("STM32F4.*:SYSCFG:.*", ("syscfg", "f4", "SYSCFG")), - ("STM32F7.*:SYSCFG:.*", ("syscfg", "f7", "SYSCFG")), - ("STM32L0.*:SYSCFG:.*", ("syscfg", "l0", "SYSCFG")), - ("STM32L1.*:SYSCFG:.*", ("syscfg", "l1", "SYSCFG")), - ("STM32L4.*:SYSCFG:.*", ("syscfg", "l4", "SYSCFG")), - ("STM32L5.*:SYSCFG:.*", ("syscfg", "l5", "SYSCFG")), - ("STM32G0.*:SYSCFG:.*", ("syscfg", "g0", "SYSCFG")), - ("STM32G4.*:SYSCFG:.*", ("syscfg", "g4", "SYSCFG")), - ( - "STM32H7(45|47|55|57|42|43|53|50).*:SYSCFG:.*", - ("syscfg", "h7od", "SYSCFG"), - ), - ("STM32H7.*:SYSCFG:.*", ("syscfg", "h7", "SYSCFG")), - ("STM32U5.*:SYSCFG:.*", ("syscfg", "u5", "SYSCFG")), - ("STM32WBA.*:SYSCFG:.*", ("syscfg", "wba", "SYSCFG")), - ("STM32WB.*:SYSCFG:.*", ("syscfg", "wb", "SYSCFG")), - ("STM32WL5.*:SYSCFG:.*", ("syscfg", "wl5", "SYSCFG")), - ("STM32WLE.*:SYSCFG:.*", ("syscfg", "wle", "SYSCFG")), - ("STM32H50.*:SBS:.*", ("syscfg", "h50", "SYSCFG")), - ("STM32H5.*:SBS:.*", ("syscfg", "h5", "SYSCFG")), - (".*:IWDG:iwdg1_v1_1", ("iwdg", "v1", "IWDG")), - (".*:IWDG:iwdg1_v2_0", ("iwdg", "v2", "IWDG")), - (".*:IWDG:iwdg1_v3_0", ("iwdg", "v3", "IWDG")), - (".*:WWDG:wwdg1_v1_0", ("wwdg", "v1", "WWDG")), - (".*:WWDG:wwdg1_v2_0", ("wwdg", "v2", "WWDG")), - (".*:JPEG:jpeg1_v1_0", ("jpeg", "v1", "JPEG")), - (".*:LTDC:lcdtft1_v1_1", ("ltdc", "v1", "LTDC")), - (".*:MDIOS:mdios1_v1_0", ("mdios", "v1", "MDIOS")), - (".*:QUADSPI:.*", ("quadspi", "v1", "QUADSPI")), - ("STM32F1.*:BKP.*", ("bkp", "v1", "BKP")), - (".*:RTC:rtc1_v1_1", ("rtc", "v1", "RTC")), - ("STM32F0.*:RTC:rtc2_.*", ("rtc", "v2f0", "RTC")), - ("STM32F2.*:RTC:rtc2_.*", ("rtc", "v2f2", "RTC")), - ("STM32F3.*:RTC:rtc2_.*", ("rtc", "v2f3", "RTC")), - ("STM32F4.*:RTC:rtc2_.*", ("rtc", "v2f4", "RTC")), - ("STM32F7.*:RTC:rtc2_.*", ("rtc", "v2f7", "RTC")), - ("STM32H7.*:RTC:rtc2_.*", ("rtc", "v2h7", "RTC")), - ("STM32L0.*:RTC:rtc2_.*", ("rtc", "v2l0", "RTC")), - ("STM32L1.*:RTC:rtc2_.*", ("rtc", "v2l1", "RTC")), - ("STM32L4.*:RTC:rtc2_.*", ("rtc", "v2l4", "RTC")), - ("STM32L5.*:RTC:rtc2_.*", ("rtc", "v3l5", "RTC")), - ("STM32WBA.*:RTC:rtc2_.*", ("rtc", "v3u5", "RTC")), - ("STM32WB.*:RTC:rtc2_.*", ("rtc", "v2wb", "RTC")), - ("STM32H5.*:RTC:rtc2_.*", ("rtc", "v3u5", "RTC")), - ("STM32U5.*:RTC:rtc2_.*", ("rtc", "v3u5", "RTC")), // Cube says v2, but it's v3 with security stuff - (".*:RTC:rtc3_v1_0", ("rtc", "v3", "RTC")), - (".*:RTC:rtc3_v1_1", ("rtc", "v3", "RTC")), - (".*:RTC:rtc3_v2_0", ("rtc", "v3", "RTC")), - (".*:RTC:rtc3_v3_0", ("rtc", "v3", "RTC")), - (".*:SAI:sai1_v1_0", ("sai", "v1", "SAI")), - (".*:SAI:sai1_v1_1", ("sai", "v2", "SAI")), - (".*:SAI:sai1_v1_2", ("sai", "v2", "SAI")), - (".*:SAI:sai1_v2_0", ("sai", "v1", "SAI")), - (".*:SAI:sai1_H7", ("sai", "v3_4pdm", "SAI")), - (".*:SAI:sai1_v2_1", ("sai", "v4_4pdm", "SAI")), - (r"STM32[HU]5.*:SAI\d?:.*", ("sai", "v4_2pdm", "SAI")), - (r"STM32L5.*:SAI\d?:.*", ("sai", "v3_2pdm", "SAI")), - (".*:SDIO:sdmmc_v1_2", ("sdmmc", "v1", "SDMMC")), - (".*:SDMMC:sdmmc_v1_3", ("sdmmc", "v1", "SDMMC")), - (".*:SPDIFRX:spdifrx1_v1_0", ("spdifrx", "v1", "SPDIFRX")), - // # USB - ("STM32(F1|L1).*:USB:.*", ("usb", "v1", "USB")), - ("STM32(F1|L1).*:USBRAM:.*", ("usbram", "16x1_512", "USBRAM")), - ("STM32F30[23].[BC].*:USB:.*", ("usb", "v1", "USB")), - ("STM32F30[23].[BC].*:USBRAM:.*", ("usbram", "16x1_512", "USBRAM")), - ("STM32F30[23].[68DE].*:USB:.*", ("usb", "v2", "USB")), - ("STM32F30[23].[68DE].*:USBRAM:.*", ("usbram", "16x2_1024", "USBRAM")), - ("STM32F373.*:USB:.*", ("usb", "v1", "USB")), - ("STM32F373.*:USBRAM:.*", ("usbram", "16x2_512", "USBRAM")), - ("STM32(F0|L[045]|G4|WB).*:USB:.*", ("usb", "v3", "USB")), - ("STM32(F0|L[045]|G4|WB).*:USBRAM:.*", ("usbram", "16x2_1024", "USBRAM")), - ("STM32(G0|H5|U5).*:USB:.*", ("usb", "v4", "USB")), - ("STM32(G0|H5|U5).*:USBRAM:.*", ("usbram", "32_2048", "USBRAM")), - // # USB OTG - (".*:USB_OTG_FS:otgfs1_.*", ("otg", "v1", "OTG")), - (".*:USB_OTG_HS:otghs1_.*", ("otg", "v1", "OTG")), - ("STM32C0.*:RCC:.*", ("rcc", "c0", "RCC")), - ("STM32F030.[46].*:RCC:.*", ("rcc", "f0v1", "RCC")), - ("STM32F05[128].*:RCC:.*", ("rcc", "f0v1", "RCC")), - ("STM32F030.8.*:RCC:.*", ("rcc", "f0v2", "RCC")), - ("STM32F03[128].*:RCC:.*", ("rcc", "f0v2", "RCC")), - ("STM32F030.C.*:RCC:.*", ("rcc", "f0v3", "RCC")), - ("STM32F070.[6B].*:RCC:.*", ("rcc", "f0v3", "RCC")), - ("STM32F0[479][128].*:RCC:.*", ("rcc", "f0v4", "RCC")), - ("STM32F100.*:RCC:.*", ("rcc", "f100", "RCC")), - ("STM32F10[123].*:RCC:.*", ("rcc", "f1", "RCC")), - ("STM32F10[57].*:RCC:.*", ("rcc", "f1cl", "RCC")), - ("STM32F2.*:RCC:.*", ("rcc", "f2", "RCC")), - ("STM32F37.*:RCC:.*", ("rcc", "f37", "RCC")), - ("STM32F30[23].[BC].*:RCC:.*", ("rcc", "f3v1", "RCC")), - ("STM32F358.C.*:RCC:.*", ("rcc", "f3v1", "RCC")), - ("STM32F30[23].[DE].*:RCC:.*", ("rcc", "f3v3", "RCC")), - ("STM32F398.E.*:RCC:.*", ("rcc", "f3v3", "RCC")), - ("STM32F3.*:RCC:.*", ("rcc", "f3v2", "RCC")), - ("STM32F410.*:RCC:.*", ("rcc", "f410", "RCC")), - ("STM32F4.*:RCC:.*", ("rcc", "f4", "RCC")), - ("STM32F7.*:RCC:.*", ("rcc", "f7", "RCC")), - ("STM32G0.*:RCC:.*", ("rcc", "g0", "RCC")), - ("STM32G4.*:RCC:.*", ("rcc", "g4", "RCC")), - ("STM32H7[AB].*:RCC:.*", ("rcc", "h7ab", "RCC")), - ("STM32H7(42|43|53|50).*:RCC:.*", ("rcc", "h7rm0433", "RCC")), - ("STM32H7.*:RCC:.*", ("rcc", "h7", "RCC")), - ("STM32L0.[23].*:RCC:.*", ("rcc", "l0_v2", "RCC")), - ("STM32L0.*:RCC:.*", ("rcc", "l0", "RCC")), - ("STM32L1.*:RCC:.*", ("rcc", "l1", "RCC")), - ("STM32L4[PQRS].*:RCC:.*", ("rcc", "l4plus", "RCC")), - ("STM32L4.*:RCC:.*", ("rcc", "l4", "RCC")), - ("STM32L5.*:RCC:.*", ("rcc", "l5", "RCC")), - ("STM32U5.*:RCC:.*", ("rcc", "u5", "RCC")), - ("STM32H50.*:RCC:.*", ("rcc", "h50", "RCC")), - ("STM32H5.*:RCC:.*", ("rcc", "h5", "RCC")), - ("STM32WBA.*:RCC:.*", ("rcc", "wba", "RCC")), - ("STM32WB.*:RCC:.*", ("rcc", "wb", "RCC")), - ("STM32WL5.*:RCC:.*", ("rcc", "wl5", "RCC")), - ("STM32WLE.*:RCC:.*", ("rcc", "wle", "RCC")), - ("STM32F1.*:SPI[1234]:.*", ("spi", "f1", "SPI")), - ("STM32F3.*:SPI[1234]:.*", ("spi", "v2", "SPI")), - ("STM32F1.*:AFIO:.*", ("afio", "f1", "AFIO")), - ("STM32WBA.*:EXTI:.*", ("exti", "l5", "EXTI")), - ("STM32L5.*:EXTI:.*", ("exti", "l5", "EXTI")), - ("STM32C0.*:EXTI:.*", ("exti", "c0", "EXTI")), - ("STM32G0.*:EXTI:.*", ("exti", "g0", "EXTI")), - ("STM32H7.*:EXTI:.*", ("exti", "h7", "EXTI")), - ("STM32U5.*:EXTI:.*", ("exti", "u5", "EXTI")), - ("STM32WB.*:EXTI:.*", ("exti", "w", "EXTI")), - ("STM32WL5.*:EXTI:.*", ("exti", "w", "EXTI")), - ("STM32WLE.*:EXTI:.*", ("exti", "wle", "EXTI")), - ("STM32H50.*:EXTI:.*", ("exti", "h50", "EXTI")), - ("STM32H5.*:EXTI:.*", ("exti", "h5", "EXTI")), - (".*:EXTI:.*", ("exti", "v1", "EXTI")), - ("STM32F0.*:CRS:.*", ("crs", "v1", "CRS")), - ("STM32L0.*:CRS:.*", ("crs", "v1", "CRS")), - ("STM32L4.*:CRS:.*", ("crs", "v1", "CRS")), - ("STM32L5.*:CRS:.*", ("crs", "v1", "CRS")), - ("STM32G0.*:CRS:.*", ("crs", "v1", "CRS")), - ("STM32G4.*:CRS:.*", ("crs", "v1", "CRS")), - ("STM32U5.*:CRS:.*", ("crs", "v1", "CRS")), - ("STM32H5.*:CRS:.*", ("crs", "v1", "CRS")), - ("STM32H7.*:CRS:.*", ("crs", "v1", "CRS")), - ("STM32WB.*:CRS:.*", ("crs", "v1", "CRS")), - (".*SDMMC:sdmmc2_v1_0", ("sdmmc", "v2", "SDMMC")), - (".*SDMMC:sdmmc2_v2_1", ("sdmmc", "v2", "SDMMC")), - ("STM32C0.*:PWR:.*", ("pwr", "c0", "PWR")), - ("STM32G0.*:PWR:.*", ("pwr", "g0", "PWR")), - ("STM32G4.*:PWR:.*", ("pwr", "g4", "PWR")), - ("STM32H7(45|47|55|57).*:PWR:.*", ("pwr", "h7rm0399", "PWR")), - ("STM32H7(42|43|53|50).*:PWR:.*", ("pwr", "h7rm0433", "PWR")), - ("STM32H7(23|25|33|35|30).*:PWR:.*", ("pwr", "h7rm0468", "PWR")), - ("STM32H7(A3|B0|B3).*:PWR:.*", ("pwr", "h7rm0455", "PWR")), - ("STM32F0.0.*:PWR:.*", ("pwr", "f0x0", "PWR")), - ("STM32F0.*:PWR:.*", ("pwr", "f0", "PWR")), - ("STM32F1.*:PWR:.*", ("pwr", "f1", "PWR")), - ("STM32F2.*:PWR:.*", ("pwr", "f2", "PWR")), - ("STM32F3.*:PWR:.*", ("pwr", "f3", "PWR")), - ("STM32F4.*:PWR:.*", ("pwr", "f4", "PWR")), - ("STM32F7.*:PWR:.*", ("pwr", "f7", "PWR")), - ("STM32L0.*:PWR:.*", ("pwr", "l0", "PWR")), - ("STM32L1.*:PWR:.*", ("pwr", "l1", "PWR")), - ("STM32L4.*:PWR:.*", ("pwr", "l4", "PWR")), - ("STM32L5.*:PWR:.*", ("pwr", "l5", "PWR")), - ("STM32U5.*:PWR:.*", ("pwr", "u5", "PWR")), - ("STM32WL.*:PWR:.*", ("pwr", "wl5", "PWR")), - ("STM32WBA.*:PWR:.*", ("pwr", "wba", "PWR")), - ("STM32WB[35]5.*:PWR:.*", ("pwr", "wb55", "PWR")), - ("STM32WB.*:PWR:.*", ("pwr", "wb", "PWR")), - ("STM32H50.*:PWR:.*", ("pwr", "h50", "PWR")), - ("STM32H5.*:PWR:.*", ("pwr", "h5", "PWR")), - ("STM32H7(A3|B3|B0).*:FLASH:.*", ("flash", "h7ab", "FLASH")), - ("STM32H7.*:FLASH:.*", ("flash", "h7", "FLASH")), - ("STM32F0.*:FLASH:.*", ("flash", "f0", "FLASH")), - ("STM32F1.*:FLASH:.*", ("flash", "f1", "FLASH")), - ("STM32F2.*:FLASH:.*", ("flash", "f2", "FLASH")), - ("STM32F3.*:FLASH:.*", ("flash", "f3", "FLASH")), - ("STM32F4.*:FLASH:.*", ("flash", "f4", "FLASH")), - ("STM32F7.*:FLASH:.*", ("flash", "f7", "FLASH")), - ("STM32L0.*:FLASH:.*", ("flash", "l0", "FLASH")), - ("STM32L1.*:FLASH:.*", ("flash", "l1", "FLASH")), - ("STM32L4.*:FLASH:.*", ("flash", "l4", "FLASH")), - ("STM32L5.*:FLASH:.*", ("flash", "l5", "FLASH")), - ("STM32U5.*:FLASH:.*", ("flash", "u5", "FLASH")), - ("STM32WBA.*:FLASH:.*", ("flash", "wba", "FLASH")), - ("STM32WB.*:FLASH:.*", ("flash", "wb", "FLASH")), - ("STM32WL.*:FLASH:.*", ("flash", "wl", "FLASH")), - ("STM32C0.*:FLASH:.*", ("flash", "c0", "FLASH")), - ("STM32G0.*:FLASH:.*", ("flash", "g0", "FLASH")), - ("STM32G4.*:FLASH:.*", ("flash", "g4", "FLASH")), - ("STM32H50.*:FLASH:.*", ("flash", "h50", "FLASH")), - ("STM32H5.*:FLASH:.*", ("flash", "h5", "FLASH")), - ("STM32F107.*:ETH:.*", ("eth", "v1a", "ETH")), - ("STM32F[24].*:ETH:.*", ("eth", "v1b", "ETH")), - ("STM32F7.*:ETH:.*", ("eth", "v1c", "ETH")), - ("STM32H.*:ETH:.*", ("eth", "v2", "ETH")), - ("STM32F4[23][79].*:FMC:.*", ("fmc", "v1x3", "FMC")), - ("STM32F446.*:FMC:.*", ("fmc", "v2x1", "FMC")), - ("STM32F469.*:FMC:.*", ("fmc", "v2x1", "FMC")), - ("STM32F7.*:FMC:.*", ("fmc", "v2x1", "FMC")), - ("STM32H7.*:FMC:.*", ("fmc", "v3x1", "FMC")), - ("STM32H5.*:FMC:.*", ("fmc", "v4", "FMC")), - ("STM32F100.*:FSMC:.*", ("fsmc", "v1x0", "FSMC")), - ("STM32F10[12357].*:FSMC:.*", ("fsmc", "v1x3", "FSMC")), - ("STM32F2.*:FSMC:.*", ("fsmc", "v1x3", "FSMC")), - ("STM32F3.*:FSMC:.*", ("fsmc", "v2x3", "FSMC")), - ("STM32F412.*:FSMC:.*", ("fsmc", "v1x0", "FSMC")), - ("STM32F4[12]3.*:FSMC:.*", ("fsmc", "v1x0", "FSMC")), - ("STM32F4[01]5.*:FSMC:.*", ("fsmc", "v1x3", "FSMC")), - ("STM32F4[01]7.*:FSMC:.*", ("fsmc", "v1x3", "FSMC")), - ("STM32L1.*:FSMC:.*", ("fsmc", "v1x0", "FSMC")), - ("STM32L4.*:FSMC:.*", ("fsmc", "v3x1", "FSMC")), - ("STM32G4.*:FSMC:.*", ("fsmc", "v4x1", "FSMC")), - ("STM32L5.*:FSMC:.*", ("fsmc", "v4x1", "FSMC")), - ("STM32U5.*:FSMC:.*", ("fsmc", "v5x1", "FSMC")), - //// TIM mapping starts here //// - // - // Note: - // AN4013 for the full tables of TIMs - // AN4013 Rev: 10, Date: 12-Jan-2023 - // - // - // AN4013 Table 2: STM32Fx serials - // Override for STM32Fx serials - ("STM32F1.*:TIM(2|5):.*", ("timer", "v1", "TIM_GP16")), - // Normal STM32Fx serials - ("STM32F.*:TIM(1|8|20):.*", ("timer", "v1", "TIM_ADV")), - ("STM32F.*:TIM(2|5):.*", ("timer", "v1", "TIM_GP32")), - ("STM32F.*:TIM(3|4|19):.*", ("timer", "v1", "TIM_GP16")), - ("STM32F.*:TIM(6|7|18):.*", ("timer", "v1", "TIM_BASIC")), - ("STM32F.*:TIM(10|11|13|14):.*", ("timer", "v1", "TIM_1CH")), - ("STM32F.*:TIM(9|12):.*", ("timer", "v1", "TIM_2CH")), - ("STM32F.*:TIM15:.*", ("timer", "v1", "TIM_2CH_CMP")), - ("STM32F.*:TIM(16|17):.*", ("timer", "v1", "TIM_1CH_CMP")), - ("STM32F.*:LPTIM1:.*", ("lptim", "v1", "LPTIM")), - ("STM32F.*:HRTIM:.*", ("hrtim", "v1", "HRTIM")), - // AN4013 Table 3: STM32Lx serials - // Override for STM32L0 serial - ("STM32L0.*:TIM(2|3):.*", ("timer", "l0", "TIM_GP16")), - ("STM32L0.*:TIM(6|7):.*", ("timer", "l0", "TIM_BASIC")), - ("STM32L0.*:TIM(21|22):.*", ("timer", "l0", "TIM_2CH")), - // Override for STM32L1 serials - ("STM32L1.*:TIM2:.*", ("timer", "v1", "TIM_GP16")), - // Normal STM32Lx serials - ("STM32L.*:TIM(1|8):.*", ("timer", "v1", "TIM_ADV")), - ("STM32L.*:TIM(2|5):.*", ("timer", "v1", "TIM_GP32")), - ("STM32L.*:TIM(3|4):.*", ("timer", "v1", "TIM_GP16")), - ("STM32L.*:TIM(6|7):.*", ("timer", "v1", "TIM_BASIC")), - ("STM32L.*:TIM(10|11):.*", ("timer", "v1", "TIM_1CH")), - ("STM32L.*:TIM(9|21|22):.*", ("timer", "v1", "TIM_2CH")), - ("STM32L.*:TIM15:.*", ("timer", "v1", "TIM_2CH_CMP")), - ("STM32L.*:TIM(16|17):.*", ("timer", "v1", "TIM_1CH_CMP")), - ("STM32L.*:LPTIM(1|2|3):.*", ("lptim", "v1", "LPTIM")), - // AN4013 Table 4: STM32Gx/Hx/Ux/Wx (and Cx) serials - // timer_v2 for STM32Gx/Hx/Ux/Wx (and Cx) serials - ("STM32U5.*:TIM(3|4):.*", ("timer", "v2", "TIM_GP32")), - ("STM32(G4|H5|U5|WBA).*:TIM(1|8|20):.*", ("timer", "v2", "TIM_ADV")), - ("STM32(G4|H5|U5|WBA).*:TIM(2|5|23|24):.*", ("timer", "v2", "TIM_GP32")), - ("STM32(G4|H5|U5|WBA).*:TIM(3|4):.*", ("timer", "v2", "TIM_GP16")), - ("STM32(G4|H5|U5|WBA).*:TIM(6|7):.*", ("timer", "v2", "TIM_BASIC")), - ("STM32(G4|H5|U5|WBA).*:TIM(13|14):.*", ("timer", "v2", "TIM_1CH")), - ("STM32(G4|H5|U5|WBA).*:TIM12:.*", ("timer", "v2", "TIM_2CH")), - ("STM32(G4|H5|U5|WBA).*:TIM15:.*", ("timer", "v2", "TIM_2CH_CMP")), - ("STM32(G4|H5|U5|WBA).*:TIM(16|17):.*", ("timer", "v2", "TIM_1CH_CMP")), - ("STM32G4.*:HRTIM1:.*", ("hrtim", "v2", "HRTIM")), - // timer_v1 for STM32Gx/Hx/Ux/Wx (and Cx) serials - ("STM32(C|G0|H7|WB|WL).*:TIM(1|8|20):.*", ("timer", "v1", "TIM_ADV")), - ("STM32(C|G0|H7|WB|WL).*:TIM(2|5|23|24):.*", ("timer", "v1", "TIM_GP32")), - ("STM32(C|G0|H7|WB|WL).*:TIM(3|4):.*", ("timer", "v1", "TIM_GP16")), - ("STM32(C|G0|H7|WB|WL).*:TIM(6|7):.*", ("timer", "v1", "TIM_BASIC")), - ("STM32(C|G0|H7|WB|WL).*:TIM(13|14):.*", ("timer", "v1", "TIM_1CH")), - ("STM32(C|G0|H7|WB|WL).*:TIM12:.*", ("timer", "v1", "TIM_2CH")), - ("STM32(C|G0|H7|WB|WL).*:TIM15:.*", ("timer", "v1", "TIM_2CH_CMP")), - ("STM32(C|G0|H7|WB|WL).*:TIM(16|17):.*", ("timer", "v1", "TIM_1CH_CMP")), - ("STM32[CGHUW].*:LPTIM[1-6]:.*", ("lptim", "v1", "LPTIM")), - ("STM32[CGHUW].*:HRTIM1?:.*", ("hrtim", "v1", "HRTIM")), - // - //// TIM mapping ends here //// - ("STM32F0.*:DBGMCU:.*", ("dbgmcu", "f0", "DBGMCU")), - ("STM32F1.*:DBGMCU:.*", ("dbgmcu", "f1", "DBGMCU")), - ("STM32F2.*:DBGMCU:.*", ("dbgmcu", "f2", "DBGMCU")), - ("STM32F3.*:DBGMCU:.*", ("dbgmcu", "f3", "DBGMCU")), - ("STM32F4.*:DBGMCU:.*", ("dbgmcu", "f4", "DBGMCU")), - ("STM32F7.*:DBGMCU:.*", ("dbgmcu", "f7", "DBGMCU")), - ("STM32C0.*:DBGMCU:.*", ("dbgmcu", "c0", "DBGMCU")), - ("STM32G0.*:DBGMCU:.*", ("dbgmcu", "g0", "DBGMCU")), - ("STM32G4.*:DBGMCU:.*", ("dbgmcu", "g4", "DBGMCU")), - ("STM32H5.*:DBGMCU:.*", ("dbgmcu", "h5", "DBGMCU")), - ("STM32H7.*:DBGMCU:.*", ("dbgmcu", "h7", "DBGMCU")), - ("STM32L0.*:DBGMCU:.*", ("dbgmcu", "l0", "DBGMCU")), - ("STM32L1.*:DBGMCU:.*", ("dbgmcu", "l1", "DBGMCU")), - ("STM32L4.*:DBGMCU:.*", ("dbgmcu", "l4", "DBGMCU")), - ("STM32L5.*:DBGMCU:.*", ("dbgmcu", "l5", "DBGMCU")), - ("STM32U5.*:DBGMCU:.*", ("dbgmcu", "u5", "DBGMCU")), - ("STM32WBA.*:DBGMCU:.*", ("dbgmcu", "wba", "DBGMCU")), - ("STM32WB.*:DBGMCU:.*", ("dbgmcu", "wb", "DBGMCU")), - ("STM32WL.*:DBGMCU:.*", ("dbgmcu", "wl", "DBGMCU")), - ("STM32F1.*:GPIO.*", ("gpio", "v1", "GPIO")), - (".*:GPIO.*", ("gpio", "v2", "GPIO")), - (".*:IPCC:v1_0", ("ipcc", "v1", "IPCC")), - (".*:DMAMUX.*", ("dmamux", "v1", "DMAMUX")), - (r".*:GPDMA\d?:.*", ("gpdma", "v1", "GPDMA")), - (r".*:BDMA\d?:.*", ("bdma", "v1", "DMA")), - ("STM32H7.*:DMA2D:DMA2D:dma2d1_v1_0", ("dma2d", "v2", "DMA2D")), - (".*:DMA2D:dma2d1_v1_0", ("dma2d", "v1", "DMA2D")), - ("STM32L4[PQRS].*:DMA.*", ("bdma", "v1", "DMA")), // L4+ - ("STM32L[04].*:DMA.*", ("bdma", "v2", "DMA")), // L0, L4 non-plus (since plus is handled above) - ("STM32F030.C.*:DMA.*", ("bdma", "v2", "DMA")), // Weird F0 - ("STM32F09.*:DMA.*", ("bdma", "v2", "DMA")), // Weird F0 - ("STM32F[247].*:DMA.*", ("dma", "v2", "DMA")), - ("STM32H7.*:DMA.*", ("dma", "v1", "DMA")), - (".*:DMA.*", ("bdma", "v1", "DMA")), - (".*:CAN:bxcan1_v1_1.*", ("can", "bxcan", "CAN")), - ("STM32H7.*:FDCAN:fdcan1_v1_[01].*", ("can", "fdcan_h7", "FDCAN")), - (".*:FDCAN:fdcan1_v1_[01].*", ("can", "fdcan_v1", "FDCAN")), - ("STM32H7.*:FDCANRAM.*", ("fdcanram", "h7", "FDCANRAM")), - (".*:FDCANRAM.*", ("fdcanram", "v1", "FDCANRAM")), - ("STM32F[124].*:CRC:.*", ("crc", "v1", "CRC")), - ("STM32L1.*:CRC:.*", ("crc", "v1", "CRC")), - ("STM32F0.*:CRC:.*", ("crc", "v2", "CRC")), - ("STM32F[37].*:CRC:.*", ("crc", "v3", "CRC")), - ("STM32G[04].*:CRC:.*", ("crc", "v3", "CRC")), - ("STM32H[57].*:CRC:.*", ("crc", "v3", "CRC")), - ("STM32L[045].*:CRC:.*", ("crc", "v3", "CRC")), - ("STM32W[BL].*:CRC:.*", ("crc", "v3", "CRC")), - ("STM32C[0].*:CRC:.*", ("crc", "v3", "CRC")), - ("STM32U[5].*:CRC:.*", ("crc", "v3", "CRC")), - (".*:LCD:lcdc1_v1.0.*", ("lcd", "v1", "LCD")), - (".*:LCD:lcdc1_v1.2.*", ("lcd", "v2", "LCD")), - (".*:LCD:lcdc1_v1.3.*", ("lcd", "v2", "LCD")), - (".*:UID:.*", ("uid", "v1", "UID")), - (".*:UCPD:.*", ("ucpd", "v1", "UCPD")), - ("STM32G0.*:TAMP:.*", ("tamp", "g0", "TAMP")), - ("STM32G4.*:TAMP:.*", ("tamp", "g4", "TAMP")), - ("STM32H5.*:TAMP:.*", ("tamp", "h5", "TAMP")), - ("STM32L5.*:TAMP:.*", ("tamp", "l5", "TAMP")), - ("STM32U5.*:TAMP:.*", ("tamp", "u5", "TAMP")), - ("STM32WL.*:TAMP:.*", ("tamp", "wl", "TAMP")), - (".*:OCTOSPIM:OCTOSPIM:.*", ("octospim", "v1", "OCTOSPIM")), - // it's actually STM32L4+, not STM32L4 - ( - "STM32L4.*:OCTOSPI[12]:OCTOSPI:octospi_v1_0.*", - ("octospi", "v1", "OCTOSPI"), - ), - ( - "STM32H7.*:OCTOSPI[12]:OCTOSPI:octospi_v2_1H7AB.*", - ("octospi", "v1", "OCTOSPI"), - ), - ( - "STM32U5[34].*:OCTOSPI[12]:OCTOSPI:octospi_v1_0L5.*", - ("octospi", "v1", "OCTOSPI"), - ), - ( - "STM32U5[AFG789].*:OCTOSPI[12]:OCTOSPI:octospi1_v3_0.*", - ("octospi", "v1", "OCTOSPI"), - ), - ( - "STM32L5.*:OCTOSPI[12]:OCTOSPI:octospi_v1_0L5.*", - ("octospi", "v2", "OCTOSPI"), - ), - ( - "STM32H5.*:OCTOSPI[12]:OCTOSPI:octospi1_v5_1.*", - ("octospi", "v2", "OCTOSPI"), - ), - ("STM32L4.*:GFXMMU:.*", ("gfxmmu", "v1", "GFXMMU")), - ("STM32U5.*:GFXMMU:.*", ("gfxmmu", "v2", "GFXMMU")), - ("STM32U5.*:ICACHE:.*", ("icache", "v1_3crr", "ICACHE")), - ("STM32H50.*:ICACHE:.*", ("icache", "v1_0crr", "ICACHE")), - ("STM32(L5|H5[67]|WBA).*:ICACHE:.*", ("icache", "v1_4crr", "ICACHE")), - (".*:CORDIC:.*", ("cordic", "v1", "CORDIC")), - ("STM32F0x[128].*:TSC:.*", ("tsc", "v1", "TSC")), - ("STM32F3[07][123].*:TSC:.*", ("tsc", "v1", "TSC")), - ("STM32WB55.*:TSC:.*", ("tsc", "v2", "TSC")), - ("STM32L[045].*:TSC:.*", ("tsc", "v3", "TSC")), - ("STM32U5.*:TSC:.*", ("tsc", "v3", "TSC")), - ("*:VREFINTCAL:.*", ("vrefintcal", "v1", "VREFINTCAL")), - ("STM32U5.*:ADF[12]:.*", ("adf", "v1", "ADF")), - (".*:HASH:hash1_v1_0", ("hash", "v1", "HASH")), - (".*:HASH:hash1_v2_0", ("hash", "v2", "HASH")), - ("STM32U5.*:HASH:.*", ("hash", "v4", "HASH")), - ("STM32WBA.*:HASH:.*", ("hash", "v4", "HASH")), - (".*:HASH:hash1_v2_2", ("hash", "v2", "HASH")), - (".*:HASH:hash1_v4_0", ("hash", "v3", "HASH")), - (".*:CRYP:cryp1_v1_0.*", ("cryp", "v1", "CRYP")), - (".*:CRYP:cryp1_v2_0.*", ("cryp", "v2", "CRYP")), - (".*:CRYP:cryp1_v2_2.*", ("cryp", "v3", "CRYP")), - ("STM32G0.1.*:.*:COMP:.*", ("comp", "v1", "COMP")), - ("STM32G4.*:.*:COMP:.*", ("comp", "v2", "COMP")), - ("STM32WL.*:.*:COMP:.*", ("comp", "v3", "COMP")), - (r".*:.*:DCACHE:.*", ("dcache", "v1", "DCACHE")), - (".*:.*:PSSI:.*", ("pssi", "v1", "PSSI")), - (".*:.*:DTS:.*", ("dts", "v1", "DTS")), - // HDMI_CEC for F1 - (".*:HDMI_CEC:hdmi_cec_v1_1", ("cec", "v1", "CEC")), - // HDMI_CEC for others - (".*:HDMI_CEC:hdmi_cec_v2_0", ("cec", "v2", "CEC")), - ("STM32(L5|L4|G0|WB|WL).*:VREFBUF:.*", ("vrefbuf", "v1", "VREFBUF")), - ("STM32(H7|U5).*:VREFBUF:.*", ("vrefbuf", "v2a1", "VREFBUF")), - ("STM32H5.*:VREFBUF:.*", ("vrefbuf", "v2a2", "VREFBUF")), - ("STM32G4.*:VREFBUF:.*", ("vrefbuf", "v2b", "VREFBUF")), - ("STM32H5.*:I3C:.*", ("i3c", "v1", "I3C")), - ("STM32(H5|WBA).*:PKA:.*", ("pka", "v1a", "PKA")), - ("STM32U5.*:PKA:.*", ("pka", "v1b", "PKA")), - ("STM32(L5|WL|WB).*:PKA:.*", ("pka", "v1c", "PKA")), - ("STM32(L4Q|L5|WL|WB).*:PKA:.*", ("pka", "v1c", "PKA")), - (".*:OTFDEC:.*", ("otfdec", "v1", "OTFDEC")), - ]; - - Self { - regexes: PERIMAP - .iter() - .map(|(a, b)| (regex::Regex::new(&format!("^{a}$")).unwrap(), *b)) - .collect(), - cached: HashMap::new(), - } - } - - fn match_peri(&mut self, peri: &str) -> Option<(&'static str, &'static str, &'static str)> { - *self - .cached - .entry(peri.to_string()) - .or_insert_with(|| self.regexes.iter().find(|(r, _block)| r.is_match(peri)).map(|x| x.1)) - } -} - -fn corename(d: &str) -> String { - let m = regex!(r".*Cortex-M(\d+)(\+?)\s*(.*)").captures(d).unwrap(); - let cm = m.get(1).unwrap().as_str(); - let p = if m.get(2).unwrap().as_str() == "+" { "p" } else { "" }; - let s = if m.get(3).unwrap().as_str() == "secure" { - "s" - } else { - "" - }; - format!("cm{cm}{p}{s}") -} - -fn merge_periph_pins_info( - chip_name: &str, - periph_name: &str, - core_pins: &mut [py32_data_serde::chip::core::peripheral::Pin], - af_pins: &[py32_data_serde::chip::core::peripheral::Pin], -) { - if chip_name.contains("STM32F1") { - // TODO: actually handle the F1 AFIO information when it will be extracted - return; - } - - // covert to hashmap - let af_pins: HashMap<(&str, &str), Option> = af_pins - .iter() - .map(|v| ((v.pin.as_str(), v.signal.as_str()), v.af)) - .collect(); - - for pin in &mut core_pins[..] { - let af = af_pins.get(&(&pin.pin, &pin.signal)).copied().flatten(); - - // try to look for a signal with another name - let af = af.or_else(|| { - if pin.signal == "CTS" { - // for some godforsaken reason UART4's and UART5's CTS are called CTS_NSS in the GPIO xml - // so try to match with these - af_pins.get(&(pin.pin.as_str(), "CTS_NSS")).copied().flatten() - } else if chip_name.starts_with("STM32F0") && periph_name == "I2C1" { - // it appears that for __some__ STM32 MCUs there is no AFIO specified in GPIO file - // (notably - STM32F030C6 with it's I2C1 on PF6 and PF7) - // but the peripheral can actually be mapped to different pins - // this breaks embassy's model, so we pretend that it's AF 0 - // Reference Manual states that there's no GPIOF_AFR register - // but according to Cube-generated core it's OK to write to AFIO reg, it seems to be ignored - // TODO: are there any more signals that have this "feature" - Some(0) - } else { - None - } - }); - - if let Some(af) = af { - pin.af = Some(af); - } - } - - // apply some renames - if chip_name.starts_with("STM32C0") || chip_name.starts_with("STM32G0") { - for pin in &mut core_pins[..] { - if pin.signal == "MCO" { - pin.signal = "MCO_1".to_string() - } - } - } -} - -pub fn parse_groups() -> Result<(HashMap, Vec), anyhow::Error> { - // XMLs group together chips that are identical except flash/ram size. - // For example STM32L471Z(E-G)Jx.xml is STM32L471ZEJx, STM32L471ZGJx. - // However they do NOT group together identical chips with different package. - - // We want exactly the opposite: group all packages of a chip together, but - // NOT group equal-except-memory-size chips together. Yay. - - // We first read all XMLs, and fold together all packages. We don't expand - // flash/ram sizes yet, we want to do it as late as possible to avoid duplicate - // work so that generation is faster. - - let mut chips = HashMap::::new(); - let mut chip_groups = Vec::new(); - - let mut files: Vec<_> = glob::glob("sources/cubedb/mcu/STM32*.xml")? - .map(Result::unwrap) - .collect(); - files.sort(); - - for f in files { - parse_group(f, &mut chips, &mut chip_groups)?; - } - - for (chip_name, chip) in &chips { - chip_groups[chip.group_idx].chip_names.push(chip_name.clone()); - } - Ok((chips, chip_groups)) -} - -static NOPELIST: &[&str] = &[ - // Not supported, not planned unless someone wants to do it. - "STM32MP", - // Does not exist in ST website. No datasheet, no RM. - "STM32GBK", - "STM32L485", - "STM32U5F", - "STM32U5G", - // STM32WxM modules. These are based on a chip that's supported on its own, - // not sure why we want a separate target for it. - "STM32WL5M", - "STM32WB1M", - "STM32WB3M", - "STM32WB5M", -]; - -fn parse_group( - f: std::path::PathBuf, - chips: &mut HashMap, - chip_groups: &mut Vec, -) -> anyhow::Result<()> { - let ff = f.file_name().unwrap().to_string_lossy(); - - for nope in NOPELIST { - if ff.contains(nope) { - return Ok(()); - } - } - - let parsed: xml::Mcu = quick_xml::de::from_str(&std::fs::read_to_string(f)?)?; - - let package_names = { - let name = &parsed.ref_name; - if !name.contains('(') { - vec![name.to_string()] - } else { - let (prefix, suffix) = name.split_once('(').unwrap(); - let (letters, suffix) = suffix.split_once(')').unwrap(); - letters.split('-').map(|x| format!("{prefix}{x}{suffix}")).collect() - } - }; - - let package_rams = { - if parsed.rams.len() == 1 { - vec![parsed.rams[0]; package_names.len()] - } else { - parsed.rams.clone() - } - }; - let package_flashes = { - if parsed.flashs.len() == 1 { - vec![parsed.flashs[0]; package_names.len()] - } else { - parsed.flashs.clone() - } - }; - - let group_idx = package_names.iter().find_map(|package_name| { - let chip_name = chip_name_from_package_name(package_name); - chips.get(&chip_name).map(|chip| chip.group_idx) - }); - - let group_idx = group_idx.unwrap_or_else(|| { - let group_idx = chip_groups.len(); - chip_groups.push(ChipGroup { - chip_names: Vec::new(), - xml: parsed.clone(), - ips: HashMap::new(), - pins: HashMap::new(), - family: None, - line: None, - die: None, - }); - group_idx - }); - - for (package_i, package_name) in package_names.iter().enumerate() { - let chip_name = chip_name_from_package_name(package_name); - if !chips.contains_key(&chip_name) { - chips.insert( - chip_name.clone(), - Chip { - flash: package_flashes[package_i], - ram: package_rams[package_i], - group_idx, - packages: Vec::new(), - }, - ); - } - chips - .get_mut(&chip_name) - .unwrap() - .packages - .push(py32_data_serde::chip::Package { - name: package_name.clone(), - package: parsed.package.clone(), - }); - } - - // Some packages have some peripehrals removed because the package had to - // remove GPIOs useful for that peripheral. So we merge all peripherals from all packages. - let group = &mut chip_groups[group_idx]; - for ip in parsed.ips { - group.ips.insert(ip.instance_name.clone(), ip); - } - for pin in parsed.pins { - if let Some(pin_name) = gpio_af::clean_pin(&pin.name) { - group - .pins - .entry(pin_name) - .and_modify(|p| { - // merge signals. - p.signals.extend_from_slice(&pin.signals); - p.signals.dedup(); - }) - .or_insert(pin); - } - } - - Ok(()) -} - -#[allow(clippy::too_many_arguments)] -fn process_group( - mut group: ChipGroup, - peri_matcher: &mut PeriMatcher, - headers: &header::Headers, - af: &gpio_af::Af, - chip_interrupts: &interrupts::ChipInterrupts, - peripheral_to_clock: &rcc::ParsedRccs, - dma_channels: &dma::DmaChannels, - chips: &HashMap, - memories: &memory::Memories, - docs: &docs::Docs, -) -> Result<(), anyhow::Error> { - let chip_name = group.chip_names[0].clone(); - group.family = Some(group.xml.family.clone()); - group.line = Some(group.xml.line.clone()); - group.die = Some(group.xml.die.clone()); - let rcc_kind = group.ips.values().find(|x| x.name == "RCC").unwrap().version.clone(); - let rcc_block = peri_matcher - .match_peri(&format!("{chip_name}:RCC:{rcc_kind}")) - .unwrap_or_else(|| panic!("could not get rcc for {}", &chip_name)); - let h = headers - .get_for_chip(&chip_name) - .unwrap_or_else(|| panic!("could not get header for {}", &chip_name)); - let chip_af = &group.ips.values().find(|x| x.name == "GPIO").unwrap().version; - let chip_af = chip_af.strip_suffix("_gpio_v1_0").unwrap(); - let chip_af = af.0.get(chip_af); - let cores: Vec<_> = group - .xml - .cores - .iter() - .map(|core_xml| { - process_core( - core_xml, - h, - &chip_name, - &group, - chip_interrupts, - peri_matcher, - peripheral_to_clock, - rcc_block, - chip_af, - dma_channels, - ) - }) - .collect(); - - for chip_name in &group.chip_names { - process_chip(chips, chip_name, h, memories, docs, &group, &cores)?; - } - - Ok(()) -} - -#[allow(clippy::too_many_arguments)] -fn process_core( - core_xml: &str, - h: &header::ParsedHeader, - chip_name: &str, - group: &ChipGroup, - chip_interrupts: &interrupts::ChipInterrupts, - peri_matcher: &mut PeriMatcher, - peripheral_to_clock: &rcc::ParsedRccs, - rcc_block: (&str, &str, &str), - chip_af: Option<&HashMap>>, - dma_channels: &dma::DmaChannels, -) -> py32_data_serde::chip::Core { - let core_name = corename(core_xml); - let defines = h.get_defines(&core_name); - - let mut peri_kinds = HashMap::new(); - peri_kinds.insert("UID".to_string(), "UID".to_string()); - for ip in group.ips.values() { - let pname = ip.instance_name.clone(); - let pkind = format!("{}:{}", ip.name, ip.version); - let pkind = pkind.strip_suffix("_Cube").unwrap_or(&pkind); - - const FAKE_PERIPHERALS: &[&str] = &[ - // These are real peripherals but with special handling - "NVIC", - "GPIO", - "DMA", - // IRTIM is just TIM16+TIM17 - "IRTIM", - // We add this as ghost peri - "SYS", - // These are software libraries - "FREERTOS", - "PDM2PCM", - "FATFS", - "LIBJPEG", - "MBEDTLS", - "LWIP", - "USB_HOST", - "USB_DEVICE", - "GUI_INTERFACE", - "TRACER_EMB", - "TOUCHSENSING", - ]; - - if FAKE_PERIPHERALS.contains(&pname.as_str()) { - continue; - } - - let pname = match pname.as_str() { - "HDMI_CEC" => "CEC".to_string(), - "SUBGHZ" => "SUBGHZSPI".to_string(), - // remove when https://github.com/stm32-rs/stm32-rs/pull/789 merges - "USB_DRD_FS" => "USB".to_string(), - _ => pname, - }; - - if pname.starts_with("ADC") { - if let Entry::Vacant(entry) = peri_kinds.entry("ADC_COMMON".to_string()) { - entry.insert(format!("ADC_COMMON:{}", ip.version.strip_suffix("_Cube").unwrap())); - } - } - if pname.starts_with("ADC3") && (chip_name.starts_with("STM32H7") || chip_name.starts_with("STM32F3")) { - if let Entry::Vacant(entry) = peri_kinds.entry("ADC3_COMMON".to_string()) { - entry.insert(format!("ADC3_COMMON:{}", ip.version.strip_suffix("_Cube").unwrap())); - } - } - peri_kinds.insert(pname, pkind.to_string()); - } - const GHOST_PERIS: &[&str] = &[ - "GPIOA", - "GPIOB", - "GPIOC", - "GPIOD", - "GPIOE", - "GPIOF", - "GPIOG", - "GPIOH", - "GPIOI", - "GPIOJ", - "GPIOK", - "GPIOL", - "GPIOM", - "GPION", - "GPIOO", - "GPIOP", - "GPIOQ", - "GPIOR", - "GPIOS", - "GPIOT", - "DMA1", - "DMA2", - "BDMA", - "DMAMUX", - "DMAMUX1", - "DMAMUX2", - "SBS", - "SYSCFG", - "EXTI", - "FLASH", - "DBGMCU", - "CRS", - "PWR", - "AFIO", - "BKP", - "USBRAM", - "VREFINTCAL", - ]; - for pname in GHOST_PERIS { - if let Entry::Vacant(entry) = peri_kinds.entry(pname.to_string()) { - if defines.get_peri_addr(pname).is_some() { - entry.insert("unknown".to_string()); - } - } - } - if peri_kinds.contains_key("BDMA1") { - peri_kinds.remove("BDMA"); - } - let fdcans = peri_kinds - .keys() - .filter_map(|pname| { - regex!(r"^FDCAN(?P[0-9]+)$") - .captures(pname) - .map(|cap| cap["idx"].to_string()) - }) - .collect::>(); - if !fdcans.is_empty() { - if chip_name.starts_with("STM32H7") { - // H7 has one message RAM shared between FDCANs - peri_kinds - .entry("FDCANRAM".to_string()) - .or_insert("unknown".to_string()); - } else { - // Other chips with FDCANs have separate message RAM per module - for fdcan in fdcans { - peri_kinds - .entry(format!("FDCANRAM{}", fdcan)) - .or_insert("unknown".to_string()); - } - } - } - // get possible used GPIOs for each peripheral from the chip xml - // it's not the full info we would want (stuff like AFIO info which comes from GPIO xml), - // but we actually need to use it because of F1 line - // which doesn't include non-remappable peripherals in GPIO xml - // and some weird edge cases like STM32F030C6 (see merge_periph_pins_info) - let mut periph_pins = HashMap::<_, Vec<_>>::new(); - for (pin_name, pin) in &group.pins { - for signal in &pin.signals { - let mut signal = signal.name.clone(); - if signal.starts_with("DEBUG_SUBGHZSPI-") { - signal = format!("SUBGHZSPI_{}", &signal[16..(signal.len() - 3)]); - } - // TODO: What are those signals (well, GPIO is clear) Which peripheral do they belong to? - if !["GPIO", "CEC", "AUDIOCLK", "VDDTCXO"].contains(&signal.as_str()) && !signal.contains("EXTI") { - // both peripherals and signals can have underscores in their names so there is no easy way to split - // check if signal name starts with one of the peripheral names - for periph in peri_kinds.keys() { - if let Some(signal) = signal.strip_prefix(&format!("{periph}_")) { - periph_pins.entry(periph.to_string()).or_default().push( - py32_data_serde::chip::core::peripheral::Pin { - pin: pin_name.clone(), - signal: signal.to_string(), - af: None, - }, - ); - break; - } - } - } - } - } - for pins in periph_pins.values_mut() { - pins.sort(); - pins.dedup(); - } - let mut peripherals = HashMap::new(); - for (pname, pkind) in peri_kinds { - // We cannot add this to FAKE peripherals because we need the pins - if pname.starts_with("I2S") { - continue; - } - - let addr = if (chip_name.starts_with("STM32F0") - || chip_name.starts_with("STM32L1") - || chip_name.starts_with("STM32L0")) - && pname == "ADC" - { - defines.get_peri_addr("ADC1") - } else if chip_name.starts_with("STM32H7") && pname == "HRTIM" { - defines.get_peri_addr("HRTIM1") - } else if let Some(cap) = regex!(r"^FDCANRAM(?P[0-9]+)$").captures(&pname) { - defines.get_peri_addr("FDCANRAM").map(|addr| { - if chip_name.starts_with("STM32H7") { - addr - } else { - let idx = cap["idx"].parse::().unwrap(); - // FIXME: this offset should not be hardcoded, but I think - // it appears in no data sources (only in RMs) - addr + (idx - 1) * 0x350 - } - }) - } else { - defines.get_peri_addr(&pname) - }; - - let addr = match addr { - Some(addr) => addr, - None => continue, - }; - - let mut p = py32_data_serde::chip::core::Peripheral { - name: if pname == "SBS" { - "SYSCFG".to_string() - } else { - pname.clone() - }, - address: addr, - registers: None, - rcc: None, - interrupts: None, - dma_channels: Vec::new(), - pins: Vec::new(), - }; - - if let Some(block) = peri_matcher.match_peri(&format!("{chip_name}:{pname}:{pkind}")) { - p.registers = Some(py32_data_serde::chip::core::peripheral::Registers { - kind: block.0.to_string(), - version: block.1.to_string(), - block: block.2.to_string(), - }); - } - - if let Some(rcc_info) = peripheral_to_clock.match_peri_clock(rcc_block.1, &pname) { - p.rcc = Some(rcc_info); - } - if let Some(pins) = periph_pins.get_mut(&pname) { - // merge the core xml info with GPIO xml info to hopefully get the full picture - // if the peripheral does not exist in the GPIO xml (one of the notable one is ADC) - // it probably doesn't need any AFIO writes to work - if let Some(af_pins) = chip_af.and_then(|x| x.get(&pname)) { - merge_periph_pins_info(chip_name, &pname, pins, af_pins.as_slice()); - } - p.pins = pins.clone(); - } - - let i2s_name = if pname.starts_with("SPI") { - "I2S".to_owned() + pname.trim_start_matches("SPI") - } else { - "".to_owned() - }; - - if let Some(i2s_pins) = periph_pins.get_mut(&i2s_name) { - // merge the core xml info with GPIO xml info to hopefully get the full picture - // if the peripheral does not exist in the GPIO xml (one of the notable one is ADC) - // it probably doesn't need any AFIO writes to work - if let Some(af_pins) = chip_af.and_then(|x| x.get(&i2s_name)) { - merge_periph_pins_info(chip_name, &i2s_name, i2s_pins, af_pins.as_slice()); - } - - p.pins.extend(i2s_pins.iter().map(|p| Pin { - pin: p.pin.clone(), - signal: "I2S_".to_owned() + &p.signal, - af: p.af, - })); - } - - // H7 has some _C pin variants (e.g. PC2 and PC2_C). Digital stuff should always be in the non-C pin. - // cubedb puts it either in both, or in the -C pin only! (in chips where the package has only the -C pin) - // so we fix that up here. - if !pname.starts_with("ADC") && !pname.starts_with("DAC") && !pname.starts_with("COMP") { - for pin in &mut p.pins { - if let Some(p) = pin.pin.strip_suffix("_C") { - pin.pin = p.to_string(); - } - } - } - - // sort pins to avoid diff for c pins - // put the ones with AF number first, so we keep them. - p.pins - .sort_by_key(|x| (x.pin.clone(), x.signal.clone(), x.af.is_none())); - p.pins.dedup_by_key(|x| (x.pin.clone(), x.signal.clone())); - - peripherals.insert(p.name.clone(), p); - } - if let Ok(extra_f) = std::fs::read(format!("data/extra/family/{}.yaml", group.family.as_ref().unwrap())) { - #[derive(serde::Deserialize)] - struct Extra { - peripherals: Vec, - } - - let extra: Extra = serde_yaml::from_slice(&extra_f).unwrap(); - for mut p in extra.peripherals { - if let Some(peripheral) = peripherals.get_mut(&p.name) { - // Modify the generated peripheral - peripheral.pins.append(&mut p.pins); - } else if p.address != 0 { - // Only insert the peripheral if the address is not the default - peripherals.insert(p.name.clone(), p); - } - } - } - - let have_peris: HashSet<_> = peripherals.keys().cloned().collect(); - let mut peripherals: Vec<_> = peripherals.into_values().collect(); - peripherals.sort_by_key(|x| x.name.clone()); - // Collect DMA versions in the chip - let mut chip_dmas: Vec<_> = group - .ips - .values() - .filter_map(|ip| { - let version = &ip.version; - let sort = match ip.name.as_str() { - "DMA" => 1, - "BDMA" => 2, - "BDMA1" => 3, - "BDMA2" => 4, - "GPDMA" => 5, - _ => 0, - }; - if sort > 0 && dma_channels.0.contains_key(version) { - Some((sort, version.clone())) - } else { - None - } - }) - .collect(); - chip_dmas.sort(); - chip_dmas.dedup(); - let chip_dmas: Vec<_> = chip_dmas.into_iter().map(|(_sort, version)| version).collect(); - // Process DMA channels - let chs = chip_dmas - .iter() - .flat_map(|dma| dma_channels.0.get(dma).unwrap().channels.clone()); - // The dma_channels[xx] is generic for multiple chips. The current chip may have less DMAs, - // so we have to filter it. - let chs: Vec<_> = chs.filter(|ch| have_peris.contains(&ch.dma)).collect(); - let core_dma_channels = chs.clone(); - let have_chs: HashSet<_> = chs.into_iter().collect(); - // Process peripheral - DMA channel associations - for p in &mut peripherals { - let mut chs = Vec::new(); - for dma in &chip_dmas { - let mut peri_chs = dma_channels.0.get(dma).unwrap().peripherals.get(&p.name); - - // DAC1 is sometimes interchanged with DAC - if peri_chs.is_none() && p.name == "DAC1" { - peri_chs = dma_channels.0.get(dma).unwrap().peripherals.get("DAC"); - } - - if let Some(peri_chs) = peri_chs { - chs.extend( - peri_chs - .iter() - .filter(|ch| { - if let Some(ch_channel) = &ch.channel { - have_chs.iter().any(|x| &x.name == ch_channel) - } else { - true - } - }) - .cloned(), - ); - } - } - if !chs.is_empty() { - chs.sort_by_key(|ch| (ch.channel.clone(), ch.dmamux.clone(), ch.request)); - p.dma_channels = chs; - } - } - - let mut core = py32_data_serde::chip::Core { - name: core_name.clone(), - peripherals, - nvic_priority_bits: None, - interrupts: vec![], - dma_channels: core_dma_channels, - }; - - chip_interrupts.process(&mut core, chip_name, h, group); - - core -} - -fn process_chip( - chips: &HashMap, - chip_name: &str, - h: &header::ParsedHeader, - memories: &memory::Memories, - docs: &docs::Docs, - group: &ChipGroup, - cores: &[py32_data_serde::chip::Core], -) -> Result<(), anyhow::Error> { - let chip = chips.get(chip_name).unwrap(); - let flash_size = chip.flash * 1024; - let ram_total = chip.ram * 1024; - let memory = memories.get(group.die.as_ref().unwrap()); - let mut flash_remaining = flash_size; - let mut memory_regions = Vec::new(); - let mut found = HashSet::<&str>::new(); - for each in [ - // We test FLASH_BANKx _before_ FLASH as we prefer their definition over the legacy one - "FLASH_BANK1", - "FLASH_BANK2", - "FLASH", - "FLASH_OTP", - "D1_AXIFLASH", - "D1_AXIICP", - ] { - if let Some(address) = h.defines.get("all").unwrap().0.get(&format!("{each}_BASE")) { - let (key, banks) = match each { - "FLASH" => ( - "BANK_1", - Some([memory::FlashBank::Bank1, memory::FlashBank::Bank2].as_ref()), - ), - "FLASH_BANK1" => ("BANK_1", Some([memory::FlashBank::Bank1].as_ref())), - "FLASH_BANK2" => ("BANK_2", Some([memory::FlashBank::Bank2].as_ref())), - "FLASH_OTP" => ("OTP", Some([memory::FlashBank::Otp].as_ref())), - each => (each, None), - }; - - if found.contains(key) { - continue; - } - found.insert(key); - - if let Some(banks) = banks { - for bank in banks { - let bank_name = match bank { - memory::FlashBank::Bank1 => "BANK_1", - memory::FlashBank::Bank2 => "BANK_2", - memory::FlashBank::Otp => "OTP", - }; - let regions: Vec<_> = memory - .flash_regions - .iter() - .filter(|region| region.bank == *bank) - .enumerate() - .map_while(|(index, region)| { - let size = if *bank == memory::FlashBank::Bank1 || *bank == memory::FlashBank::Bank2 { - // Truncate region to the total amount of remaining chip flash - let size = std::cmp::min(region.bytes, flash_remaining); - flash_remaining -= size; - if size == 0 { - // No more regions are present on this chip - return None; - } - size - } else { - region.bytes - }; - - Some((index, region.address, size, region.settings.clone())) - }) - .collect(); - let has_multiple_regions = regions.len() > 1; - for (index, address, size, settings) in regions { - let name = if has_multiple_regions { - format!("{}_REGION_{}", bank_name, index + 1) - } else { - bank_name.to_string() - }; - - memory_regions.push(py32_data_serde::chip::Memory { - name, - kind: py32_data_serde::chip::memory::Kind::Flash, - address, - size, - settings: Some(settings.clone()), - }); - } - } - } else { - memory_regions.push(py32_data_serde::chip::Memory { - name: key.to_string(), - kind: py32_data_serde::chip::memory::Kind::Flash, - address: u32::try_from(*address).unwrap(), - size: 0, - settings: None, - }) - } - } - } - let mut found = HashSet::new(); - for each in [ - "SRAM", - "SRAM1", - "SRAM2", - "D1_AXISRAM", - "D1_ITCMRAM", - "D1_DTCMRAM", - "D1_AHBSRAM", - "D2_AXISRAM", - "D3_BKPSRAM", - "D3_SRAM", - ] { - if let Some(address) = h.defines.get("all").unwrap().0.get(&format!("{each}_BASE")) { - let key = match each { - "D1_AXISRAM" => "SRAM", - "SRAM1" => "SRAM", - each => each, - }; - - if found.contains(key) { - continue; - } - found.insert(key); - - let size = if key == "SRAM" { - // if memory.ram.bytes != ram_total { - // println!( - // "SRAM mismatch for chip {} with die {}: Expected {} was {}", - // chip_name, - // group.die.as_ref().unwrap(), - // ram_total, - // memory.ram.bytes, - // ); - // } - std::cmp::min(memory.ram.bytes, ram_total) - } else { - 0 - }; - - memory_regions.push(py32_data_serde::chip::Memory { - name: key.to_string(), - kind: py32_data_serde::chip::memory::Kind::Ram, - address: u32::try_from(*address).unwrap(), - size, - settings: None, - }) - } - } - let docs = docs.documents_for(chip_name); - let chip = py32_data_serde::Chip { - name: chip_name.to_string(), - family: group.family.clone().unwrap(), - line: group.line.clone().unwrap(), - die: group.die.clone().unwrap(), - device_id: memory.device_id, - packages: chip.packages.clone(), - memory: memory_regions, - docs, - cores: cores.to_vec(), - }; - let dump = serde_json::to_string_pretty(&chip)?; - - // TODO: delete this. - // This makes the formating match the output of the original python script, to prevent unnecessary churn - let dump = { - let mut cleaned = String::new(); - for line in dump.lines() { - let spaces = line.bytes().take_while(|b| *b == b' ').count(); - for _ in 0..spaces { - // add an extra space for every existing space - // this converts two-space indents to four-space indents - cleaned.push(' '); - } - // escape non-ascii symbols - let line = line.replace('\u{00ae}', r"\u00ae"); - let line = line.replace('\u{2122}', r"\u2122"); - cleaned.push_str(&line); - cleaned.push('\n'); - } - // remove trailing newline - cleaned.pop(); - cleaned - }; - - std::fs::write(format!("build/data/chips/{chip_name}.json"), dump)?; - Ok(()) -} - -#[allow(clippy::too_many_arguments)] -pub fn dump_all_chips( - chip_groups: Vec, - headers: header::Headers, - af: gpio_af::Af, - chip_interrupts: interrupts::ChipInterrupts, - peripheral_to_clock: rcc::ParsedRccs, - dma_channels: dma::DmaChannels, - chips: std::collections::HashMap, - memories: memory::Memories, - docs: docs::Docs, -) -> Result<(), anyhow::Error> { - std::fs::create_dir_all("build/data/chips")?; - - #[cfg(feature = "rayon")] - { - use rayon::prelude::*; - - chip_groups - .into_par_iter() - .try_for_each_init(PeriMatcher::new, |peri_matcher, group| { - process_group( - group, - peri_matcher, - &headers, - &af, - &chip_interrupts, - &peripheral_to_clock, - &dma_channels, - &chips, - &memories, - &docs, - ) - }) - } - #[cfg(not(feature = "rayon"))] - { - let mut peri_matcher = PeriMatcher::new(); - - chip_groups.into_iter().try_for_each(|group| { - process_group( - group, - &mut peri_matcher, - &headers, - &af, - &chip_interrupts, - &peripheral_to_clock, - &dma_channels, - &chips, - &memories, - &docs, - ) - }) - } -} diff --git a/py32-data-gen/src/dma.rs b/py32-data-gen/src/dma.rs deleted file mode 100644 index 3ca6a5a..0000000 --- a/py32-data-gen/src/dma.rs +++ /dev/null @@ -1,350 +0,0 @@ -use std::collections::HashMap; - -use anyhow::Context; - -mod xml { - use serde::Deserialize; - - #[derive(Debug, Deserialize, PartialEq)] - pub struct Ip { - #[serde(rename = "Name")] - pub name: String, - #[serde(rename = "Version")] - pub version: String, - #[serde(rename = "RefParameter")] - pub ref_parameters: Vec, - #[serde(rename = "RefMode")] - pub ref_modes: Vec, - #[serde(rename = "ModeLogicOperator")] - pub mode_logic_operator: ModeLogicOperator, - } - - #[derive(Debug, Deserialize, PartialEq)] - pub struct RefMode { - #[serde(rename = "Name")] - pub name: String, - #[serde(rename = "BaseMode")] - pub base_mode: Option, - #[serde(rename = "Parameter")] - pub parameters: Vec, - } - - #[derive(Debug, Deserialize, PartialEq)] - pub struct Parameter { - #[serde(rename = "Name")] - pub name: String, - #[serde(rename = "PossibleValue", default)] - pub possible_values: Vec, - } - - #[derive(Debug, Deserialize, PartialEq)] - pub struct RefParameter { - #[serde(rename = "Name")] - pub name: String, - #[serde(rename = "PossibleValue", default)] - pub possible_values: Vec, - } - - #[derive(Debug, Deserialize, PartialEq)] - pub struct PossibleValue { - #[serde(rename = "Comment")] - pub comment: String, - #[serde(rename = "Value")] - pub value: String, - } - - #[derive(Debug, Deserialize, PartialEq)] - pub struct ModeLogicOperator { - #[serde(rename = "Name")] - pub name: String, - #[serde(rename = "Mode")] - pub modes: Vec, - } - - #[derive(Debug, Deserialize, PartialEq)] - pub struct Mode { - #[serde(rename = "Name")] - pub name: String, - #[serde(rename = "ModeLogicOperator", default)] - pub mode_logic_operator: Option, - } -} - -#[derive(Debug, PartialEq)] -pub struct ChipDma { - pub peripherals: HashMap>, - pub channels: Vec, -} - -#[derive(Debug)] -pub struct DmaChannels(pub HashMap); - -impl DmaChannels { - pub fn parse() -> anyhow::Result { - let mut dma_channels = HashMap::new(); - for f in glob::glob("sources/cubedb/mcu/IP/DMA*Modes.xml")? - .chain(glob::glob("sources/cubedb/mcu/IP/BDMA*Modes.xml")?) - { - let f = f?; - if f.to_string_lossy().contains("DMAMUX") { - continue; - } - let parsed: xml::Ip = quick_xml::de::from_str(&std::fs::read_to_string(&f)?).context(format!("{:?}", f))?; - - let ff = parsed.version.clone(); - let is_explicitly_bdma = match parsed.name.as_str() { - "DMA" | "DMA2D" => false, - "BDMA" | "BDMA1" | "BDMA2" => true, - name => panic!("Unrecognized DMA name: {name}"), - }; - - let mut chip_dma = ChipDma { - peripherals: HashMap::new(), - channels: Vec::new(), - }; - - for dma in parsed.mode_logic_operator.modes { - let dma_peri_name = dma.name.clone(); - if dma_peri_name.contains(" Context") { - continue; - } - let channels = dma.mode_logic_operator.unwrap().modes; - if channels.len() == 1 { - // ========== CHIP WITH DMAMUX - - let dmamux_file = { - if ff.starts_with("STM32L4P") { - "L4PQ" - } else if ff.starts_with("STM32L4S") { - "L4RS" - } else { - &ff[5..7] - } - }; - - let dmamux = match is_explicitly_bdma { - true => "DMAMUX2", - false => "DMAMUX1", - }; - - let mut mfs: Vec<_> = glob::glob(&format!("data/dmamux/{dmamux_file}_*.yaml"))? - .map(Result::unwrap) - .collect(); - mfs.sort(); - for mf in mfs { - let y: HashMap = serde_yaml::from_str(&std::fs::read_to_string(&mf)?)?; - - let mf = mf.file_name().unwrap().to_string_lossy(); - let (_, req_dmamux) = mf.strip_suffix(".yaml").unwrap().split_once('_').unwrap(); // DMAMUX1 or DMAMUX2 - - if req_dmamux == dmamux { - for (request_name, request_num) in y { - let parts: Vec<_> = request_name.split('_').collect(); - let target_peri_name = parts[0]; - let request = { - if parts.len() < 2 { - target_peri_name - } else { - parts[1] - } - }; - chip_dma - .peripherals - .entry(target_peri_name.to_string()) - .or_default() - .push(py32_data_serde::chip::core::peripheral::DmaChannel { - signal: request.to_string(), - channel: None, - dmamux: Some(req_dmamux.to_string()), - request: Some(request_num), - dma: None, - }) - } - } - } - - let mut dmamux_channel = 0; - for n in dma_peri_name.split(',') { - let n = n.trim(); - let re = regex::Regex::new(&format!(".*{n}{}", r"_(Channel|Stream)\[(\d+)-(\d+)\]")).unwrap(); - if let Some(result) = re.captures(&channels[0].name) { - let low: u8 = result.get(2).unwrap().as_str().parse()?; - let high: u8 = result.get(3).unwrap().as_str().parse()?; - for i in low..=high { - chip_dma.channels.push(py32_data_serde::chip::core::DmaChannels { - name: format!("{n}_CH{i}"), - dma: n.to_string(), - // Make sure all channels numbers start at 0 - channel: i - low, - dmamux: Some(dmamux.to_string()), - dmamux_channel: Some(dmamux_channel), - supports_2d: None, - }); - dmamux_channel += 1; - } - } - } - } else { - // ========== CHIP WITHOUT DMAMUX - - // see if we can scrape out requests - let mut requests = HashMap::::new(); - for block in parsed - .ref_modes - .iter() - .filter(|x| x.base_mode == Some("DMA_Request".to_string())) - { - let name = block.name.clone(); - // Depending on the chip, the naming is "Channel" or "Request"... - if let Some(request_num) = block - .parameters - .iter() - .find(|x| x.name == "Channel" || x.name == "Request") - { - assert_eq!(request_num.possible_values.len(), 1); - let request_num = request_num.possible_values[0].clone(); - if request_num.starts_with("BDMA1_REQUEST_") { - continue; - } - let request_num = request_num - .strip_prefix("DMA_CHANNEL_") - .or_else(|| request_num.strip_prefix("DMA_REQUEST_")) - .unwrap(); - requests.insert(name, request_num.parse().unwrap()); - } - } - - let mut channel_names: Vec = Vec::new(); - - for channel in channels { - let channel_name = channel.name; - let (_, channel_name) = channel_name.split_once('_').unwrap(); - let channel_name = channel_name - .strip_prefix("Channel") - .or_else(|| channel_name.strip_prefix("Stream")) - .unwrap(); - - channel_names.push(channel_name.parse().unwrap()); - chip_dma.channels.push(py32_data_serde::chip::core::DmaChannels { - name: format!("{dma_peri_name}_CH{channel_name}"), - dma: dma_peri_name.clone(), - channel: channel_name.parse().unwrap(), - dmamux: None, - dmamux_channel: None, - supports_2d: None, - }); - for target in channel.mode_logic_operator.unwrap().modes { - let original_target_name = target.name; - let parts: Vec<_> = original_target_name.split(':').collect(); - let target_name = parts[0]; - - // Chips with single DAC refer to channels by DAC1/DAC2 - let target_name = match target_name { - "DAC1" => "DAC_CH1", - "DAC2" => "DAC_CH2", - x => x, - }; - - let parts: Vec<_> = target_name.split('_').collect(); - let target_peri_name = parts[0]; - let target_requests = { - if parts.len() < 2 { - vec![target_peri_name] - } else { - target_name.split('_').nth(1).unwrap().split('/').collect() - } - }; - if target_name != "MEMTOMEM" { - let target_peri_name = match target_peri_name { - "LPUART" => "LPUART1", - x => x, - }; - for request in target_requests { - assert!(!request.contains(':')); - let entry = py32_data_serde::chip::core::peripheral::DmaChannel { - signal: request.to_string(), - channel: Some(format!("{dma_peri_name}_CH{channel_name}")), - dmamux: None, - request: requests.get(&original_target_name).copied(), - dma: None, - }; - chip_dma - .peripherals - .entry(target_peri_name.to_string()) - .or_default() - .push(entry); - } - } - } - } - - // Make sure all channels numbers start at 0 - if channel_names.iter().min().unwrap() != &0 { - for ch in &mut chip_dma.channels { - if ch.dma == dma_peri_name { - ch.channel -= 1; - } - } - } - } - } - - dma_channels.insert(ff, chip_dma); - } - - // GPDMA - - for (file, gpdmax, instance, count, count_2d) in [ - ("H5_GPDMA.yaml", "GPDMA1", "STM32H5_dma3_Cube", 8, 2), - ("H5_GPDMA.yaml", "GPDMA2", "Instance2_STM32H5_dma3_Cube", 8, 2), - ("U5_GPDMA1.yaml", "GPDMA1", "STM32U5_dma3_Cube", 16, 4), - ("WBA_GPDMA1.yaml", "GPDMA1", "STM32WBA_dma3_Cube", 8, 0), - ] { - let mut chip_dma = ChipDma { - peripherals: HashMap::new(), - channels: Vec::new(), - }; - - let parsed: HashMap = - serde_yaml::from_str(&std::fs::read_to_string(format!("data/dmamux/{file}"))?)?; - - for (request_name, request_num) in parsed { - let parts: Vec<_> = request_name.split('_').collect(); - let target_peri_name = parts[0]; - let request = { - if parts.len() < 2 { - target_peri_name - } else { - parts[1] - } - }; - chip_dma - .peripherals - .entry(target_peri_name.to_string()) - .or_default() - .push(py32_data_serde::chip::core::peripheral::DmaChannel { - signal: request.to_string(), - dma: Some(gpdmax.to_string()), - channel: None, - dmamux: None, - request: Some(request_num), - }); - } - - for i in 0..count { - chip_dma.channels.push(py32_data_serde::chip::core::DmaChannels { - name: format!("{gpdmax}_CH{i}"), - dma: gpdmax.to_string(), - channel: i, - dmamux: None, - dmamux_channel: None, - supports_2d: Some(i >= count - count_2d), - }); - } - - dma_channels.insert(instance.to_string(), chip_dma); - } - - Ok(Self(dma_channels)) - } -} diff --git a/py32-data-gen/src/docs.rs b/py32-data-gen/src/docs.rs deleted file mode 100644 index b64ae8a..0000000 --- a/py32-data-gen/src/docs.rs +++ /dev/null @@ -1,152 +0,0 @@ -use std::collections::HashMap; - -mod mcufinder { - use serde::{Deserialize, Serialize}; - - #[derive(Debug, Serialize, Deserialize, PartialEq)] - pub struct Files { - #[serde(rename = "Files")] - pub files: Vec, - } - - #[derive(Debug, Serialize, Deserialize, PartialEq)] - pub struct File { - #[serde(rename = "URL")] - pub url: String, - // #[serde(rename = "displayName")] - // pub display_name: String, - pub id_file: String, - pub name: String, - // #[serde(rename = "related_MCU_count")] - // pub related_mcu_count: String, - pub title: String, - pub r#type: String, - // #[serde(rename = "versionNumber")] - // pub version_number: String, - } - - #[derive(Debug, Serialize, Deserialize, PartialEq)] - pub struct Mcus { - #[serde(rename = "MCUs")] - pub mcus: Vec, - } - - #[derive(Debug, Serialize, Deserialize, PartialEq)] - pub struct Mcu { - #[serde(rename = "RPN")] - pub rpn: String, - pub files: Vec, - } - - #[derive(Debug, Serialize, Deserialize, PartialEq)] - pub struct McuFile { - pub file_id: String, - } -} - -impl From for py32_data_serde::chip::Doc { - fn from(file: mcufinder::File) -> Self { - Self { - name: file.name, - title: file.title, - url: file.url, - r#type: parse_document_type(&file.r#type).to_string(), - } - } -} - -#[derive(Debug, PartialEq)] -pub struct AllMcuFiles(HashMap); - -impl AllMcuFiles { - pub fn parse() -> anyhow::Result { - let j = std::fs::read_to_string("sources/mcufinder/files.json")?; - let parsed: mcufinder::Files = serde_json::from_str(&j)?; - let all_mcu_files = parsed - .files - .into_iter() - .map(|file| (file.id_file.clone(), file.into())) - .collect(); - Ok(Self(all_mcu_files)) - } -} - -#[derive(Debug, PartialEq)] -pub struct PerMcuFiles(HashMap>); - -impl PerMcuFiles { - pub fn parse() -> anyhow::Result { - let j = std::fs::read_to_string("sources/mcufinder/mcus.json")?; - let parsed: mcufinder::Mcus = serde_json::from_str(&j)?; - - let mut per_mcu_files = HashMap::>::new(); - - for mcu in parsed.mcus { - let rpn = mcu.rpn; - let files = mcu.files.into_iter().map(|file| file.file_id); - per_mcu_files.entry(rpn.to_string()).or_default().extend(files); - } - - Ok(Self(per_mcu_files)) - } -} - -pub struct Docs { - pub all_mcu_files: AllMcuFiles, - pub per_mcu_files: PerMcuFiles, -} - -impl Docs { - pub fn parse() -> anyhow::Result { - Ok(Self { - all_mcu_files: AllMcuFiles::parse()?, - per_mcu_files: PerMcuFiles::parse()?, - }) - } - - pub fn documents_for(&self, chip_name: &str) -> Vec { - let mut docs: Vec<_> = self - .per_mcu_files - .0 - .get(chip_name) - .into_iter() - .flatten() - .flat_map(|id| { - if let Some(file) = self.all_mcu_files.0.get(id) { - let order = order_doc_type(&file.r#type); - Some((order, file)) - } else { - None - } - }) - .collect(); - docs.sort_by_key(|(order, file)| (*order, file.name.clone())); - - docs.into_iter().map(|(_order, file)| file.clone()).collect() - } -} - -fn parse_document_type(t: &str) -> &'static str { - match t { - "Reference manual" => "reference_manual", - "Programming manual" => "programming_manual", - "Datasheet" => "datahseet", // TODO: fix me - "Errata sheet" => "errata_sheet", - "Application note" => "application_note", - "User manual" => "user_manual", - "Data brief" => "data_brief", - _ => panic!("Unknown doc type {t}"), - } -} - -fn order_doc_type(t: &str) -> u8 { - match t { - "reference_manual" => 0, - "programming_manual" => 1, - "datahseet" => 2, // TODO: fix me - "errata_sheet" => 3, - "application_note" => 4, - "data_brief" => 5, - _ => panic!("Unknown doc type {t}"), - } -} diff --git a/py32-data-gen/src/header.rs b/py32-data-gen/src/header.rs deleted file mode 100644 index b6dfb44..0000000 --- a/py32-data-gen/src/header.rs +++ /dev/null @@ -1,328 +0,0 @@ -use std::collections::HashMap; - -use crate::regex; - -pub struct Headers { - map: HeaderMap, - parsed: HeadersParsed, - regexes: Vec<(regex::Regex, String)>, -} - -impl Headers { - pub fn parse() -> anyhow::Result { - let map = HeaderMap::parse()?; - let parsed = HeadersParsed::parse()?; - let regexes = parsed - .0 - .keys() - .map(|h| { - let pattern = h.replace('x', "."); - let regex = regex::Regex::new(&format!("^{pattern}$")).unwrap(); - (regex, h.clone()) - }) - .collect(); - Ok(Self { map, parsed, regexes }) - } - - pub fn get_for_chip(&self, model: &str) -> Option<&ParsedHeader> { - let model = model.to_ascii_lowercase(); - match self.map.0.get(&model) { - // if it's in the map, just go - Some(name) => Some(self.parsed.0.get(name).unwrap()), - // if not, find it by regex, taking `x` meaning `anything` - None => { - let mut results = self - .regexes - .iter() - .filter_map(|(r, name)| if r.is_match(&model) { Some(name) } else { None }); - let res = results.next(); - assert_eq!(results.next(), None, "found more than one match"); - res.map(|name| self.parsed.0.get(name).unwrap()) - } - } - } -} - -#[derive(Debug, PartialEq, Eq)] -pub struct HeaderMap(pub HashMap); - -impl HeaderMap { - pub fn parse() -> anyhow::Result { - let mut res = HashMap::new(); - for (mut header, chips) in - serde_yaml::from_str::>(&std::fs::read_to_string("data/header_map.yaml")?)? - { - header.make_ascii_lowercase(); - for chip in chips.split(',') { - let chip = chip.trim().to_ascii_lowercase(); - if let Some(old) = res.insert(chip.clone(), header.clone()) { - panic!("Duplicate {chip} found! Overwriting {old} with {header}"); - } - } - } - - Ok(Self(res)) - } -} - -#[derive(Debug, PartialEq, Eq)] -pub struct HeadersParsed(pub HashMap); - -impl HeadersParsed { - pub fn parse() -> anyhow::Result { - let files = glob::glob("sources/headers/*.h").unwrap().map(Result::unwrap); - - let for_each_file = |f: std::path::PathBuf| { - let ff = f.file_name().unwrap().to_string_lossy(); - let ff = ff.strip_suffix(".h").unwrap(); - let parsed_header = ParsedHeader::parse(&f).unwrap(); - (ff.to_string(), parsed_header) - }; - - #[cfg(feature = "rayon")] - { - use rayon::prelude::*; - Ok(Self(files.par_bridge().map(for_each_file).collect())) - } - #[cfg(not(feature = "rayon"))] - { - Ok(Self(files.map(for_each_file).collect())) - } - } -} - -fn parens_ok(val: &str) -> bool { - let mut n: i32 = 0; - for c in val.chars() { - match c { - '(' => n += 1, - ')' => { - n -= 1; - if n < 0 { - return false; - } - } - _ => {} - } - } - n == 0 -} - -#[derive(Clone, Debug, Default, PartialEq, Eq)] -pub struct Defines(pub HashMap); - -impl Defines { - // warning: horrible abomination ahead - fn parse_value(&self, val: &str) -> i64 { - let val = val.trim(); - if val.is_empty() { - 0 - } else if let Some(m) = regex!(r"^(0([1-9][0-9]*)(U))").captures(val) { - m.get(2).unwrap().as_str().parse().unwrap() - } else if let Some(m) = regex!(r"^((0x[0-9a-fA-F]+|\d+))(|u|ul|U|UL)$").captures(val) { - let x = m.get(1).unwrap().as_str(); - match x.strip_prefix("0x") { - Some(x) => i64::from_str_radix(x, 16), - None => x.parse(), - } - .unwrap() - } else if let Some(m) = regex!(r"^([0-9A-Za-z_]+)$").captures(val) { - self.0.get(m.get(1).unwrap().as_str()).copied().unwrap_or(0) - } else if let Some(x) = regex!(r"^\((.*)\)$") - .captures(val) - .map(|m| m.get(1).unwrap().as_str()) - .filter(|x| parens_ok(x)) - { - self.parse_value(x) - } else if let Some(m) = regex!(r"^\*?\([0-9A-Za-z_]+ *\*?\)(.*)$").captures(val) { - self.parse_value(m.get(1).unwrap().as_str()) - } else if let Some(m) = regex!(r"^(.*)/(.*)$").captures(val) { - self.parse_value(m.get(1).unwrap().as_str()) / self.parse_value(m.get(2).unwrap().as_str()) - } else if let Some(m) = regex!(r"^(.*)<<(.*)$").captures(val) { - self.parse_value(m.get(1).unwrap().as_str()) << self.parse_value(m.get(2).unwrap().as_str()) & 0xFFFFFFFF - } else if let Some(m) = regex!(r"^(.*)>>(.*)$").captures(val) { - self.parse_value(m.get(1).unwrap().as_str()) >> self.parse_value(m.get(2).unwrap().as_str()) - } else if let Some(m) = regex!(r"^(.*)\|(.*)$").captures(val) { - self.parse_value(m.get(1).unwrap().as_str()) | self.parse_value(m.get(2).unwrap().as_str()) - } else if let Some(m) = regex!(r"^(.*)&(.*)$").captures(val) { - self.parse_value(m.get(1).unwrap().as_str()) & self.parse_value(m.get(2).unwrap().as_str()) - } else if let Some(m) = regex!(r"^~(.*)$").captures(val) { - !self.parse_value(m.get(1).unwrap().as_str()) & 0xFFFFFFFF - } else if let Some(m) = regex!(r"^(.*)\+(.*)$").captures(val) { - self.parse_value(m.get(1).unwrap().as_str()) + self.parse_value(m.get(2).unwrap().as_str()) - } else if let Some(m) = regex!(r"^(.*)-(.*)$").captures(val) { - self.parse_value(m.get(1).unwrap().as_str()) - self.parse_value(m.get(2).unwrap().as_str()) - } else { - panic!("can't parse: {val:?}") - } - } - - pub fn get_peri_addr(&self, pname: &str) -> Option { - const ALT_PERI_DEFINES: &[(&str, &[&str])] = &[ - ("DBGMCU", &["DBGMCU_BASE", "DBG_BASE"]), - ("QUADSPI", &["QUADSPI_BASE", "QSPI_R", "QSPI_R_BASE", "QSPI_REG_BASE"]), - ("QUADSPI1", &["QUADSPI1_BASE", "QSPI_R", "QSPI_R_BASE", "QSPI_REG_BASE"]), - ( - "OCTOSPI", - &["OSPI_R", "OCTOSPI_R_BASE", "OCTOSPI_R_BASE_NS", "OCTOSPI_REG_BASE"], - ), - ( - "OCTOSPI1", - &["OSPI_R", "OCTOSPI1_R_BASE", "OCTOSPI1_R_BASE_NS", "OCTOSPI1_REG_BASE"], - ), - ( - "OCTOSPI2", - &["OCTOSPI2_R_BASE", "OCTOSPI2_R_BASE_NS", "OCTOSPI2_REG_BASE"], - ), - ("FLASH", &["FLASH_R_BASE", "FLASH_REG_BASE"]), - ( - "ADC_COMMON", - &["ADC_COMMON", "ADC1_COMMON", "ADC12_COMMON", "ADC123_COMMON"], - ), - ("ADC3_COMMON", &["ADC3_COMMON", "ADC4_COMMON", "ADC34_COMMON"]), - ("CAN", &["CAN_BASE", "CAN1_BASE"]), - ("FMC", &["FMC_BASE", "FMC_R_BASE"]), - ("FSMC", &["FSMC_R_BASE"]), - ("USB", &["USB_BASE", "USB_DRD_BASE", "USB_BASE_NS", "USB_DRD_BASE_NS"]), - ( - "USBRAM", - &["USB_PMAADDR", "USB_DRD_PMAADDR", "USB_PMAADDR_NS", "USB_DRD_PMAADDR_NS"], - ), - ("FDCANRAM", &["SRAMCAN_BASE", "SRAMCAN_BASE_NS"]), - ("VREFINTCAL", &["VREFINT_CAL_ADDR_CMSIS"]), - ]; - let alt_peri_defines: HashMap<_, _> = ALT_PERI_DEFINES.iter().copied().collect(); - - let possible_defines: Vec = alt_peri_defines - .get(pname) - .map(|x| x.iter().map(ToString::to_string).collect()) - .unwrap_or_else(|| vec![format!("{pname}_BASE"), pname.to_string()]); - possible_defines - .into_iter() - .find_map(|d| self.0.get(&d).filter(|&&addr| addr != 0)) - .map(|x| u32::try_from(*x).unwrap()) - } -} - -#[derive(Debug, PartialEq, Eq)] -pub struct ParsedHeader { - pub cores: Vec, - pub interrupts: HashMap>, - pub defines: HashMap, -} - -impl ParsedHeader { - /// Get C header defines for this core. - pub fn get_defines(&self, core_name: &str) -> &Defines { - let core_name = if !self.interrupts.contains_key(core_name) || !self.defines.contains_key(core_name) { - "all" - } else { - core_name - }; - self.defines.get(core_name).unwrap() - } - - /// Get interrupts for this core. - pub fn get_interrupts(&self, core_name: &str) -> &HashMap { - let core_name = if !self.interrupts.contains_key(core_name) || !self.defines.contains_key(core_name) { - "all" - } else { - core_name - }; - self.interrupts.get(core_name).unwrap() - } - - fn parse(f: impl AsRef) -> anyhow::Result { - let mut irqs = HashMap::>::new(); - let mut defines = HashMap::::new(); - let mut cores = Vec::::new(); - let mut cur_core = "all".to_string(); - - let mut accum = String::new(); - let f = std::fs::read(f)?; - for l in f.split(|b| b == &b'\n') { - let l = String::from_utf8_lossy(l); - let l = l.trim(); - let l = accum.clone() + l; - if l.ends_with('\\') { - accum = l.strip_suffix('\\').unwrap().to_string(); - continue; - } - accum = String::new(); - - // Scoped by a single core - if let Some(m) = regex!(r".*if defined.*CORE_CM(\d+)(PLUS)?.*").captures(&l) { - cur_core = format!("cm{}", m.get(1).unwrap().as_str()); - if m.get(2).is_some() { - cur_core += "p"; - } - if !cores.contains(&cur_core) { - cores.push(cur_core.clone()) - } - } else if regex!(r".*else.*").is_match(&l) { - cur_core = "all".to_string(); - if let Some(m) = regex!(".*else.*CORE_CM(\\d+)(PLUS)?.*").captures(&l) { - cur_core = format!("cm{}", m.get(1).unwrap().as_str()); - if m.get(2).is_some() { - cur_core += "p"; - } - } else if cores.len() > 1 { - // Pick the second core assuming we've already parsed one - cur_core = cores[1].clone(); - } - - if !cores.contains(&cur_core) { - cores.push(cur_core.clone()); - } - } else if regex!(r".*endif.*").is_match(&l) { - cur_core = "all".to_string(); - } - - let irq_entry = irqs.entry(cur_core.clone()).or_default(); - let defines_entry = defines.entry(cur_core.clone()).or_default(); - - if let Some(m) = regex!(r"^([a-zA-Z0-9_]+)_IRQn *= *(\d+),? +/\*!<(.*)\*/").captures(&l) { - irq_entry.insert( - m.get(1).unwrap().as_str().to_string(), - m.get(2).unwrap().as_str().parse().unwrap(), - ); - } - - if let Some(m) = regex!(r"^#define +([0-9A-Za-z_]+)\(").captures(&l) { - defines_entry.0.insert(m.get(1).unwrap().as_str().to_string(), -1); - } - - if let Some(m) = regex!(r"^#define +([0-9A-Za-z_]+) +(.*)").captures(&l) { - let name = m.get(1).unwrap().as_str().trim(); - if name == "FLASH_SIZE" { - continue; - } - let val = m.get(2).unwrap().as_str(); - let val = val.split("/*").next().unwrap().trim(); - let val = defines_entry.parse_value(val); - - defines_entry.0.insert(name.to_string(), val); - } - } - - if cores.is_empty() { - cores = vec!["all".to_string()]; - } - - for core in &mut cores { - if core != "all" { - let all_irqs = irqs.get("all").unwrap().clone(); - irqs.get_mut(core).unwrap().extend(all_irqs); - - let all_defines = defines.get("all").unwrap().clone(); - defines.get_mut(core).unwrap().0.extend(all_defines.0); - } - } - - Ok(Self { - cores, - interrupts: irqs, - defines, - }) - } -} diff --git a/py32-data-gen/src/main.rs b/py32-data-gen/src/main.rs index 856f0d4..066155d 100644 --- a/py32-data-gen/src/main.rs +++ b/py32-data-gen/src/main.rs @@ -1,7 +1,9 @@ -use std::{collections::{HashMap, BTreeMap}, path::Path}; +use std::collections::HashMap; +use std::path::Path; + +use py32_data_serde::chip::core; // mod chips; -// mod dma; // mod docs; // mod header; // mod interrupts; @@ -91,6 +93,9 @@ fn main() -> anyhow::Result<()> { for core in &mut chip.cores { let mut peripheral_afs = None; + // peripheral name: Vec<(signal, remap)> + let mut peripheral_dma_channels = None; + if let Some(inc_path) = core.include_interrupts.take() { let interrupts_yaml_path = meta_yaml_path.parent().unwrap().join(&inc_path); let content = std::fs::read_to_string(&interrupts_yaml_path)?; @@ -110,12 +115,55 @@ fn main() -> anyhow::Result<()> { if let Some(inc_path) = &mut core.include_afs.take() { let afs_yaml_path = meta_yaml_path.parent().unwrap().join(&inc_path); let content = std::fs::read_to_string(&afs_yaml_path)?; - let afs: BTreeMap> = + let afs: HashMap> = serde_yaml::from_str(&content)?; peripheral_afs = Some(afs); } + // append DMA channels from includes + if let Some(dma_channels_inc) = &mut core.include_dma_channels.take() { + let mut dma_channels = HashMap::new(); + for (channel_name, inc_path) in dma_channels_inc { + let dma_channels_yaml_path = meta_yaml_path.parent().unwrap().join(&inc_path); + let content = std::fs::read_to_string(&dma_channels_yaml_path)?; + let dma_channel_map: HashMap = serde_yaml::from_str(&content)?; + + for (signal, &remap) in &dma_channel_map { + let parts: Vec<&str> = signal.split('_').collect(); + + // e.g USART1_TX, ADC1 + let (peripheral, signal) = if parts.len() == 1 { + (parts[0].to_string(), parts[0].to_string()) + } else if parts.len() == 2 { + (parts[0].to_string(), parts[1].to_string()) + } else { + panic!("Invalid DMA signal: {}", signal); + }; + + let dma_channel = core::peripheral::DmaChannel { + signal: signal.clone(), + dma: Some(channel_name.split('_').next().unwrap().to_string()), + channel: Some(channel_name.clone()), + request: Some(remap), + }; + dma_channels + .entry(peripheral) + .or_insert_with(Vec::new) + .push(dma_channel); + } + + let core_dma_channels = core::DmaChannels { + name: channel_name.clone(), + dma: channel_name.split('_').next().unwrap().to_string(), + channel: channel_name.split('_').nth(1).unwrap().strip_prefix("CH").unwrap().parse::().unwrap() - 1u8, + }; + + core.dma_channels.push(core_dma_channels); + } + peripheral_dma_channels = Some(dma_channels); + } + // append peripherals from includes if let Some(inc_paths) = &mut core.include_peripherals.take() { for inc_path in inc_paths { @@ -146,6 +194,15 @@ fn main() -> anyhow::Result<()> { } } + if let Some(peripheral_dma_channels) = peripheral_dma_channels.as_ref() { + for peripheral in &mut peripherals { + if let Some(dma_channels) = peripheral_dma_channels.get(&peripheral.name) { + println!("successufully matched DMA with peri: {:#?}", &peripheral.name); + peripheral.dma_channels = dma_channels.clone(); + } + } + } + core.peripherals.extend(peripherals); } } diff --git a/py32-data-gen/src/memory.rs b/py32-data-gen/src/memory.rs deleted file mode 100644 index e4f21bf..0000000 --- a/py32-data-gen/src/memory.rs +++ /dev/null @@ -1,288 +0,0 @@ -use std::cmp::Ordering; -use std::collections::HashMap; -use std::fs; - -#[derive(Debug, PartialEq)] -pub struct Memory { - pub device_id: u16, - pub ram: Ram, - pub flash_size: u32, - pub flash_regions: Vec, -} - -#[derive(Clone, Copy, Debug, PartialEq)] -pub struct Ram { - pub address: u32, - pub bytes: u32, -} - -#[derive(Clone, Debug, PartialEq)] -pub struct FlashRegion { - pub bank: FlashBank, - pub address: u32, - pub bytes: u32, - pub settings: py32_data_serde::chip::memory::Settings, -} - -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum FlashBank { - Bank1, - Bank2, - Otp, -} - -mod xml { - use serde::Deserialize; - - pub fn from_hex<'de, T, D>(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - T: num::Num, - T::FromStrRadixErr: std::fmt::Display, - { - use serde::de::Error; - let s: &str = Deserialize::deserialize(deserializer)?; - let s = s.trim(); - let (prefix, num) = s.split_at(2); - if prefix != "0x" && prefix != "0X" { - panic!("no hex prefix"); - } - T::from_str_radix(num, 16).map_err(D::Error::custom) - } - - pub fn opt_from_hex<'de, T, D>(deserializer: D) -> Result, D::Error> - where - D: serde::Deserializer<'de>, - T: num::Num, - T::FromStrRadixErr: std::fmt::Display, - { - Ok(Some(from_hex(deserializer)?)) - } - - #[derive(Debug, Deserialize, PartialEq)] - pub struct Root { - #[serde(rename = "Device")] - pub device: root::Device, - } - - mod root { - use serde::Deserialize; - - use super::from_hex; - - #[derive(Debug, Deserialize, PartialEq)] - pub struct Device { - #[serde(rename = "DeviceID", deserialize_with = "from_hex")] - pub device_id: u16, - #[serde(rename = "Name")] - pub name: String, - #[serde(rename = "Peripherals")] - pub peripherals: device::Peripherals, - } - - mod device { - use serde::Deserialize; - - #[derive(Debug, Deserialize, PartialEq)] - pub struct Peripherals { - #[serde(rename = "Peripheral")] - pub peripharal: Vec, - } - - mod peripherals { - use serde::Deserialize; - - use super::super::super::opt_from_hex; - - #[derive(Debug, Deserialize, PartialEq)] - pub struct Peripheral { - #[serde(rename = "Name")] - // pub name: peripheral::Name, - pub name: String, - #[serde(rename = "ErasedValue", deserialize_with = "opt_from_hex", default)] - pub erased_value: Option, - #[serde(rename = "Configuration", default)] - pub configuration: Vec, - } - - mod peripheral { - use serde::Deserialize; - - use super::super::super::super::opt_from_hex; - - #[derive(Debug, Deserialize, PartialEq)] - pub struct Configuration { - #[serde(rename = "Parameters", default)] - pub parameters: Option, - #[serde(rename = "Organization", default)] - pub organization: Option, - #[serde(rename = "Allignement", deserialize_with = "opt_from_hex", default)] - pub allignement: Option, - #[serde(rename = "Bank")] - pub bank: Vec, - } - - mod configuration { - use serde::Deserialize; - - use super::super::super::super::super::{from_hex, opt_from_hex}; - - #[derive(Debug, Deserialize, PartialEq)] - pub struct Parameters { - #[serde(deserialize_with = "from_hex")] - pub address: u32, - #[serde(deserialize_with = "from_hex")] - pub size: u32, - #[serde(deserialize_with = "opt_from_hex", default)] - pub occurence: Option, - } - - #[derive(Debug, Deserialize, PartialEq)] - pub struct Bank { - #[serde(default)] - pub name: Option, - #[serde(rename = "Field", default)] - pub field: Vec, - } - - mod bank { - use serde::Deserialize; - - #[derive(Debug, Deserialize, PartialEq)] - pub struct Field { - #[serde(rename = "Parameters")] - pub parameters: super::Parameters, - } - } - } - } - } - } - } -} -pub struct Memories(HashMap); - -impl Memories { - pub fn parse() -> anyhow::Result { - let mut paths: Vec<_> = glob::glob("sources/cubeprogdb/db/*.xml") - .unwrap() - .map(Result::unwrap) - .collect(); - paths.sort(); - - let mut memories = HashMap::new(); - - for f in paths { - // println!("Parsing {f:?}"); - let file = fs::read_to_string(f)?; - let parsed: xml::Root = quick_xml::de::from_str(&file)?; - // dbg!(&parsed); - - let device_id = parsed.device.device_id; - - let mut ram = None; - let mut flash_size = None; - let mut flash_regions = vec![]; - - for mut peripheral in parsed.device.peripherals.peripharal { - if peripheral.name == "Embedded SRAM" && ram.is_none() { - let config = peripheral.configuration.first().unwrap(); - let parameters = config.parameters.as_ref().unwrap(); - ram = Some(Ram { - address: parameters.address, - bytes: parameters.size, - }); - } - - enum BlockKind { - Main, - Otp, - } - let kind = match peripheral.name.as_str() { - "Embedded Flash" => Some(BlockKind::Main), - "OTP" => Some(BlockKind::Otp), - _ => None, - }; - - if let Some(kind) = kind { - peripheral.configuration.sort_by(|a, b| { - // Prefer largest size - let ordering = b - .parameters - .as_ref() - .unwrap() - .size - .partial_cmp(&a.parameters.as_ref().unwrap().size) - .unwrap(); - - // ... then prefer single ordering over dual - if ordering == Ordering::Equal { - // Possible values are Single and Dual - b.organization.partial_cmp(&a.organization).unwrap() - } else { - ordering - } - }); - let config = peripheral.configuration.first().unwrap(); - - if flash_size.is_none() { - let parameters = config.parameters.as_ref().unwrap(); - - flash_size = Some(parameters.size); - } - - for bank in config.bank.iter() { - let flash_bank = match kind { - BlockKind::Main => match bank.name.as_deref() { - Some("Bank 1") => Some(FlashBank::Bank1), - Some("Bank 2") => Some(FlashBank::Bank2), - Some("EEPROM1") => None, - Some("EEPROM2") => None, - None => { - assert_eq!(1, config.bank.len()); - Some(FlashBank::Bank1) - } - Some(other) => unimplemented!("Unsupported flash bank {}", other), - }, - BlockKind::Otp => Some(FlashBank::Otp), - }; - - if let Some(flash_bank) = flash_bank { - let erase_value = peripheral.erased_value.unwrap(); - let write_size = config.allignement.unwrap(); - flash_regions.extend(bank.field.iter().map(|field| FlashRegion { - bank: flash_bank, - address: field.parameters.address, - bytes: field.parameters.occurence.unwrap() * field.parameters.size, - settings: py32_data_serde::chip::memory::Settings { - erase_value, - write_size, - erase_size: field.parameters.size, - }, - })); - } - } - } - } - - memories.insert( - device_id, - Memory { - device_id, - ram: ram.unwrap(), - flash_size: flash_size.unwrap_or_default(), - flash_regions, - }, - ); - } - - Ok(Self(memories)) - } - - pub fn get(&self, die: &str) -> &Memory { - assert!(die.starts_with("DIE")); - let device_id = u16::from_str_radix(&die[3..], 16).unwrap(); - - self.0.get(&device_id).unwrap() - } -} diff --git a/py32-data-gen/src/rcc.rs b/py32-data-gen/src/rcc.rs deleted file mode 100644 index 469f841..0000000 --- a/py32-data-gen/src/rcc.rs +++ /dev/null @@ -1,351 +0,0 @@ -use std::collections::{HashMap, HashSet}; - -use anyhow::{anyhow, bail, Ok}; -use chiptool::ir::IR; -use py32_data_serde::chip::core::peripheral::rcc::{Field, StopMode}; -use py32_data_serde::chip::core::peripheral::{self, rcc}; - -use crate::regex; -use crate::registers::Registers; - -#[derive(Debug)] -pub struct ParsedRccs { - /// RCC version -> parsed info - rccs: HashMap, -} - -#[derive(Debug)] -struct ParsedRcc { - /// name -> en/rst bit info - en_rst: HashMap, - /// name -> mux info - mux: HashMap, -} - -#[derive(Debug)] -struct MuxInfo { - mux: Field, - variants: Vec, -} - -#[derive(Debug)] -struct EnRst { - enable: rcc::Field, - reset: Option, - bus_clock: String, - stop_mode: StopMode, -} - -impl ParsedRccs { - pub fn parse(registers: &Registers) -> anyhow::Result { - let mut rccs = HashMap::new(); - - for (rcc_name, ir) in ®isters.registers { - if let Some(rcc_name) = rcc_name.strip_prefix("rcc_") { - rccs.insert(rcc_name.to_string(), Self::parse_rcc(rcc_name, ir)?); - } - } - - Ok(Self { rccs }) - } - - fn parse_rcc(rcc_version: &str, ir: &IR) -> anyhow::Result { - let allowed_variants = HashSet::from([ - "DISABLE", - "SYS", - "PCLK1", - "PCLK1_TIM", - "PCLK2", - "PCLK2_TIM", - "PCLK3", - "PCLK4", - "PCLK5", - "PCLK6", - "PCLK7", - "HCLK1", - "HCLK2", - "HCLK3", - "HCLK4", - "HCLK5", - "HCLK6", - "HCLK7", - "PLLI2S1_P", - "PLLI2S1_Q", - "PLLI2S1_R", - "PLLI2S2_P", - "PLLI2S2_Q", - "PLLI2S2_R", - "PLLSAI1_P", - "PLLSAI1_Q", - "PLLSAI1_R", - "PLLSAI2_P", - "PLLSAI2_Q", - "PLLSAI2_R", - "PLL1_P", - "PLL1_P_MUL_2", - "PLL1_Q", - "PLL1_R", - "PLL1_VCO", // used for L0 USB - "PLL2_P", - "PLL2_Q", - "PLL2_R", - "PLL3_P", - "PLL3_Q", - "PLL3_R", - "HSI", - "SHSI", - "HSI48", - "LSI", - "CSI", - "MSI", - "MSIS", - "MSIK", - "HSE", - "LSE", - "AUDIOCLK", - "PER", - "CLK48", - // TODO: variants to cleanup - "AFIF", - "HSI_HSE", - "DSI_PHY", - "HSI_Div488", - "SAI1_EXTCLK", - "SAI2_EXTCLK", - "B_0x0", - "B_0x1", - "I2S_CKIN", - "DAC_HOLD", - "DAC_HOLD_2", - "RTCCLK", - "RTC_WKUP", - "DSIPHY", - "ICLK", - "DCLK", - "I2S1", - "I2S2", - "SAI1", - "SAI2", - "HSI256_MSIS1024_MSIS4", - "HSI256_MSIS1024_MSIK4", - "HSI256_MSIK1024_MSIS4", - "HSI256_MSIK1024_MSIK4", - ]); - - let mux_regexes = &[ - regex!(r"^DCKCFGR\d?/(.+)SEL$"), - regex!(r"^CCIPR\d?/(.+)SEL$"), - regex!(r"^D\dCCIP\d?R/(.+)SEL$"), - regex!(r"^CFGR\d/(.+)SW$"), - ]; - - let mut mux = HashMap::new(); - for (reg, body) in &ir.fieldsets { - for field in &body.fields { - let key = format!("{}/{}", reg, field.name); - if let Some(capture) = mux_regexes.iter().find_map(|r| r.captures(&key)) { - let peri = capture.get(1).unwrap().as_str(); - - // TODO: these bits are duplicated on F4, we need to split the F4 RCCs more. - if rcc_version.starts_with("f4") && reg == "DCKCFGR2" && (peri == "CLK48" || peri == "SDIO") { - continue; - } - - // ignore switches with missing enum. - let Some(enum_name) = field.enumm.as_deref() else { - continue; - }; - - let enumm = ir.enums.get(enum_name).unwrap(); - for v in &enumm.variants { - let mut vname = v.name.as_str(); - if let Some(captures) = regex!(r"^([A-Z0-9_]+)_DIV_\d+?$").captures(v.name.as_str()) { - vname = captures.get(1).unwrap().as_str(); - } - - if !allowed_variants.contains(vname) { - return Err(anyhow!( - "rcc: prohibited variant name {} in enum {} for rcc_{}", - v.name.as_str(), - enum_name, - rcc_version - )); - } - } - - let val = MuxInfo { - mux: Field { - register: reg.clone(), - field: field.name.clone(), - }, - variants: enumm.variants.iter().map(|v| v.name.clone()).collect(), - }; - - if mux.insert(peri.to_string(), val).is_some() { - bail!("rcc: duplicate mux for {} for rcc_{}", peri, rcc_version); - } - } - } - } - - // Parse xxEN/xxRST bits. - let mut en_rst = HashMap::new(); - for (reg, body) in &ir.fieldsets { - if let Some(m) = regex!(r"^((A[PH]B\d?)|GPIO)[LH]?ENR\d?$").captures(reg) { - let clock = m.get(1).unwrap().as_str(); - let clock = match clock { - "AHB" => "AHB1", - "APB" => "APB1", - clock => clock, - }; - - for field in &body.fields { - if let Some(peri) = field.name.strip_suffix("EN") { - let peri = if peri == "RTCAPB" { "RTC" } else { peri }; - - let mut reset = None; - if let Some(rstr) = ir.fieldsets.get(®.replace("ENR", "RSTR")) { - if let Some(_field) = rstr.fields.iter().find(|field| field.name == format!("{peri}RST")) { - reset = Some(rcc::Field { - register: reg.replace("ENR", "RSTR"), - field: format!("{peri}RST"), - }); - } - } - - let stop_mode = if peri == "RTC" { - StopMode::Standby - } else if peri.starts_with("LP") { - StopMode::Stop2 - } else { - StopMode::Stop1 - }; - - let clock = clock.replace("AHB", "HCLK").replace("APB", "PCLK"); - - let val = EnRst { - enable: rcc::Field { - register: reg.clone(), - field: field.name.clone(), - }, - reset, - bus_clock: clock, - stop_mode, - }; - - if en_rst.insert(peri.to_string(), val).is_some() { - bail!("rcc: duplicate en/rst for {} for rcc_{}", peri, rcc_version); - } - } - } - } - } - - Ok(ParsedRcc { en_rst, mux }) - } - - pub fn match_peri_clock( - &self, - rcc_version: &str, - peri_name: &str, - ) -> Option { - const FALLBACKS: &[(&str, &[&str])] = &[ - ("DCMI", &["DCMI_PSSI"]), - ("PSSI", &["DCMI_PSSI"]), - ("FDCAN1", &["FDCAN12"]), - ("FDCAN2", &["FDCAN12"]), - ("ADC", &["ADC1"]), - ("ADC1", &["ADC12"]), - ("ADC2", &["ADC12"]), - ("ADC3", &["ADC34", "ADC345"]), - ("ADC4", &["ADC34", "ADC345"]), - ("ADC5", &["ADC345"]), - ("DAC", &["DAC1"]), - ("DAC1", &["DAC12"]), - ("DAC2", &["DAC12"]), - ("ETH", &["ETHMAC", "ETH1MAC"]), - ("SPI1", &["SPI12", "SPI123"]), - ("SPI2", &["SPI12", "SPI123"]), - ("SPI3", &["SPI123"]), - ("SPI4", &["SPI145"]), - ("SPI5", &["SPI145"]), - ("SAI1", &["SAI12"]), - ("SAI2", &["SAI12"]), - ("USART2", &["USART234578"]), - ("USART3", &["USART234578"]), - ("UART4", &["USART234578"]), - ("UART5", &["USART234578"]), - ("UART7", &["USART234578"]), - ("UART8", &["USART234578"]), - ("USART1", &["USART16910"]), - ("USART6", &["USART16910"]), - ("USART10", &["USART16910"]), - ("UART9", &["USART16910"]), - ("I2C1", &["I2C1235"]), - ("I2C2", &["I2C1235"]), - ("I2C3", &["I2C1235"]), - ("I2C5", &["I2C1235"]), - ]; - - let rcc = self.rccs.get(rcc_version)?; - - let en_rst = get_with_fallback(peri_name, &rcc.en_rst, FALLBACKS)?; - let mux = get_with_fallback(peri_name, &rcc.mux, FALLBACKS); - - let phclk = regex!("^[PH]CLK"); - - let mut maybe_kernel_clock = en_rst.bus_clock.clone(); - // Timers are a bit special, they may have a x2 freq - if regex!(r"^(HR)?TIM\d+$").is_match(peri_name) { - maybe_kernel_clock.push_str("_TIM"); - } - - let kernel_clock = match mux { - Some(mux) => { - // check for mismatch between mux and bus clock. - if phclk.is_match(&en_rst.bus_clock) { - for v in &mux.variants { - if phclk.is_match(v) && v != &maybe_kernel_clock { - panic!( - "rcc_{}: peripheral {} is on bus {} but mux {}.{} refers to {}", - rcc_version, peri_name, maybe_kernel_clock, mux.mux.register, mux.mux.field, v - ) - } - } - } - rcc::KernelClock::Mux(mux.mux.clone()) - } - None => rcc::KernelClock::Clock(maybe_kernel_clock), - }; - - Some(peripheral::Rcc { - bus_clock: en_rst.bus_clock.clone(), - kernel_clock, - enable: en_rst.enable.clone(), - reset: en_rst.reset.clone(), - stop_mode: en_rst.stop_mode.clone(), - }) - } -} - -fn get_with_fallback<'a, T>(key: &str, map: &'a HashMap, fallbacks: &[(&str, &[&str])]) -> Option<&'a T> { - if let Some(res) = map.get(key) { - return Some(res); - } - - if let Some((_, rename)) = fallbacks.iter().find(|(n, _)| *n == key) { - for &n in *rename { - if let Some(res) = map.get(n) { - return Some(res); - } - } - } - - if let Some(capture) = regex!("^([A-Z]+)\\d+$").captures(key) { - if let Some(res) = map.get(capture.get(1).unwrap().as_str()) { - return Some(res); - } - } - - None -} diff --git a/py32-data-serde/src/lib.rs b/py32-data-serde/src/lib.rs index a25883a..3e8c59a 100644 --- a/py32-data-serde/src/lib.rs +++ b/py32-data-serde/src/lib.rs @@ -248,9 +248,6 @@ pub mod chip { pub dma: Option, #[serde(skip_serializing_if = "Option::is_none")] pub channel: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub dmamux: Option, - #[serde(skip_serializing_if = "Option::is_none")] pub request: Option, } } @@ -266,12 +263,6 @@ pub mod chip { pub name: String, pub dma: String, pub channel: u8, - #[serde(skip_serializing_if = "Option::is_none")] - pub dmamux: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub dmamux_channel: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub supports_2d: Option, } } }