|
| 1 | +from typing import * |
| 2 | + |
| 3 | +from .JlcPart import JlcPart |
| 4 | +from ..abstract_parts import * |
| 5 | + |
| 6 | + |
| 7 | +@abstract_block |
| 8 | +class Stm32g431Base_Device(IoControllerI2cTarget, IoControllerCan, IoControllerUsb, InternalSubcircuit, IoControllerUsbCc, |
| 9 | + BaseIoControllerPinmapGenerator, |
| 10 | + GeneratorBlock, JlcPart, FootprintBlock): |
| 11 | + PACKAGE: str # package name for footprint(...) |
| 12 | + PART: str # part name for footprint(...) |
| 13 | + LCSC_PART: str |
| 14 | + LCSC_BASIC_PART: bool |
| 15 | + |
| 16 | + SYSTEM_PIN_REMAP: Dict[str, Union[str, List[str]]] # pin name in base -> pin name(s) |
| 17 | + RESOURCE_PIN_REMAP: Dict[str, str] # resource name in base -> pin name |
| 18 | + |
| 19 | + def __init__(self, **kwargs) -> None: |
| 20 | + super().__init__(**kwargs) |
| 21 | + |
| 22 | + # Power and ground |
| 23 | + self.pwr = self.Port(VoltageSink( |
| 24 | + voltage_limits=(1.71, 3.6) * Volt, |
| 25 | + current_draw=(14 * nAmp, 44.0 * mAmp) # Table 32 |
| 26 | + ), [Power]) |
| 27 | + |
| 28 | + self.gnd = self.Port(Ground(), [Common]) |
| 29 | + |
| 30 | + self.swd = self.Port(SwdTargetPort.empty()) |
| 31 | + self._io_ports.insert(0, self.swd) |
| 32 | + self.nrst = self.Port(DigitalSink.empty(), optional=True) # internally pulled up |
| 33 | + |
| 34 | + def _system_pinmap(self) -> Dict[str, CircuitPort]: |
| 35 | + return VariantPinRemapper({ |
| 36 | + 'Vdd': self.pwr, |
| 37 | + 'Vss': self.gnd, |
| 38 | + # 'VddA': self.pwr, |
| 39 | + # 'VssA': self.gnd, |
| 40 | + 'BOOT0': self.gnd, |
| 41 | + 'PG10-NRST': self.nrst, |
| 42 | + }).remap(self.SYSTEM_PIN_REMAP) |
| 43 | + |
| 44 | + def _io_pinmap(self) -> PinMapUtil: |
| 45 | + input_range = self.gnd.link().voltage.hull(self.pwr.link().voltage) |
| 46 | + io_voltage_limit = (input_range + (-0.3, 3.6) * Volt).intersect( |
| 47 | + self.gnd.link().voltage + (-0.3, 5.5) * Volt) # Section 5.3.1 |
| 48 | + input_threshold_factor = (0.3, 0.7) # Section 5.3.14 |
| 49 | + current_limits = (-20, 20) * mAmp # Table 15 |
| 50 | + |
| 51 | + dio_ft_model = DigitalBidir.from_supply( |
| 52 | + self.gnd, self.pwr, |
| 53 | + voltage_limit_abs=io_voltage_limit, |
| 54 | + current_limits=current_limits, |
| 55 | + input_threshold_factor=input_threshold_factor, |
| 56 | + pullup_capable=True, pulldown_capable=True |
| 57 | + ) |
| 58 | + dio_tt_model = DigitalBidir.from_supply( |
| 59 | + self.gnd, self.pwr, |
| 60 | + voltage_limit_tolerance=(-0.3, 0.3) * Volt, # Table 19 |
| 61 | + current_draw=(0, 0) * Amp, current_limits=current_limits, |
| 62 | + input_threshold_factor=input_threshold_factor, |
| 63 | + pullup_capable=True, pulldown_capable=True |
| 64 | + ) |
| 65 | + |
| 66 | + # Pin definition, 4.10 |
| 67 | + dio_fta_model = dio_ftca_model = dio_ftf_model = dio_ftfa_model = \ |
| 68 | + dio_ftfu_model = dio_ftfd_model = dio_ftda_model = dio_ftu_model = dio_ft_model |
| 69 | + dio_tta_model = dio_tt_model |
| 70 | + |
| 71 | + dio_ftc_model = DigitalBidir.from_supply( |
| 72 | + self.gnd, self.pwr, |
| 73 | + voltage_limit_abs=(-0.3, 5.0) * Volt, |
| 74 | + current_limits=current_limits, |
| 75 | + input_threshold_factor=input_threshold_factor, |
| 76 | + pullup_capable=True, pulldown_capable=True |
| 77 | + ) |
| 78 | + |
| 79 | + adc_model = AnalogSink.from_supply( |
| 80 | + self.gnd, self.pwr, |
| 81 | + voltage_limit_tolerance=(-0.3, 0.3) * Volt, |
| 82 | + signal_limit_tolerance=(0, 0), |
| 83 | + impedance=(50, float('inf')) * kOhm # TODO: this is maximum external input impedance, maybe restrictive |
| 84 | + ) |
| 85 | + dac_model = AnalogSource.from_supply( |
| 86 | + self.gnd, self.pwr, |
| 87 | + signal_out_bound=(0.2 * Volt, -0.2 * Volt), # signal_out_bound only applies when output buffer on |
| 88 | + impedance=(9.6, 13.8) * kOhm # assumes buffer off |
| 89 | + ) |
| 90 | + self.nrst.init_from(DigitalSink.from_supply( # specified differently than other pins |
| 91 | + self.gnd, self.pwr, |
| 92 | + voltage_limit_abs=io_voltage_limit, # assumed |
| 93 | + input_threshold_factor=(0.3, 0.7), |
| 94 | + pullup_capable=True # internal pullup |
| 95 | + )) |
| 96 | + |
| 97 | + uart_model = UartPort(DigitalBidir.empty()) |
| 98 | + spi_model = SpiController(DigitalBidir.empty()) |
| 99 | + i2c_model = I2cController(DigitalBidir.empty()) |
| 100 | + i2c_target_model = I2cTarget(DigitalBidir.empty()) |
| 101 | + |
| 102 | + return PinMapUtil([ # for 32 pins only for now |
| 103 | + PinResource('PF0', {'PF0': dio_ftfa_model, 'ADC1_IN10': adc_model}), # TODO remappable to OSC_IN |
| 104 | + PinResource('PF1', {'PF1': dio_fta_model, 'ADC2_IN10': adc_model}), # TODO remappable to OSC_OUT |
| 105 | + |
| 106 | + PinResource('PA0', {'PA0': dio_tta_model, 'ADC12_IN1': adc_model}), |
| 107 | + PinResource('PA1', {'PA1': dio_tta_model, 'ADC12_IN2': adc_model}), |
| 108 | + PinResource('PA2', {'PA2': dio_tta_model, 'ADC1_IN3': adc_model}), |
| 109 | + PinResource('PA3', {'PA3': dio_tta_model, 'ADC1_IN4': adc_model}), |
| 110 | + PinResource('PA4', {'PA4': dio_tta_model, 'ADC2_IN17': adc_model, 'DAC1_OUT1': dac_model}), |
| 111 | + PinResource('PA5', {'PA5': dio_tta_model, 'ADC2_IN13': adc_model, 'DAC1_OUT2': dac_model}), |
| 112 | + PinResource('PA6', {'PA6': dio_tta_model, 'ADC2_IN3': adc_model}), |
| 113 | + PinResource('PA7', {'PA7': dio_tta_model, 'ADC2_IN4': adc_model}), |
| 114 | + PinResource('PA8', {'PA8': dio_ftf_model}), |
| 115 | + PinResource('PA9', {'PA9': dio_ftfd_model}), |
| 116 | + PinResource('PA10', {'PA10': dio_ftda_model}), |
| 117 | + PinResource('PA11', {'PA11': dio_ftu_model}), # USB_DM |
| 118 | + PinResource('PA12', {'PA12': dio_ftu_model}), # USB_DP |
| 119 | + PinResource('PA13', {'PA13': dio_ftf_model}), |
| 120 | + PinResource('PA14', {'PA14': dio_ftf_model}), |
| 121 | + PinResource('PA15', {'PA15': dio_ftf_model}), |
| 122 | + |
| 123 | + PinResource('PB0', {'PB0': dio_tta_model, 'ADC1_IN15': adc_model}), |
| 124 | + PinResource('PB3', {'PB3': dio_ft_model}), |
| 125 | + PinResource('PB4', {'PB4': dio_ftc_model}), |
| 126 | + PinResource('PB5', {'PB5': dio_ftf_model}), |
| 127 | + PinResource('PB6', {'PB6': dio_ftc_model}), |
| 128 | + PinResource('PB7', {'PB7': dio_ftf_model}), |
| 129 | + PinResource('PB8', {'PB8': dio_ftf_model}), |
| 130 | + |
| 131 | + # From table 13 |
| 132 | + PeripheralFixedResource('SPI1', spi_model, { |
| 133 | + 'sck': ['PA5', 'PB3'], 'miso': ['PA6', 'PB4'], 'mosi': ['PA7', 'PB5'] |
| 134 | + }), |
| 135 | + PeripheralFixedResource('SPI2', spi_model, { |
| 136 | + 'sck': ['PF1'], 'miso': ['PA10'], 'mosi': ['PA11'] |
| 137 | + }), |
| 138 | + PeripheralFixedResource('SPI3', spi_model, { |
| 139 | + 'sck': ['PB3'], 'miso': ['PB4'], 'mosi': ['PB5'] |
| 140 | + }), |
| 141 | + PeripheralFixedResource('I2S2', I2sController(DigitalBidir.empty()), { |
| 142 | + 'sck': ['PB13', 'PF1'], 'ws': ['PB12', 'PF0'], 'sd': ['PA11', 'PB15'] |
| 143 | + }), |
| 144 | + PeripheralFixedResource('I2S3', I2sController(DigitalBidir.empty()), { |
| 145 | + 'sck': ['PB3'], 'ws': ['PA4', 'PA15'], 'sd': ['PB5'] |
| 146 | + }), |
| 147 | + PeripheralFixedResource('USART1', uart_model, { |
| 148 | + 'tx': ['PA9', 'PB6'], 'rx': ['PA10', 'PB7'] |
| 149 | + }), |
| 150 | + PeripheralFixedResource('USART2', uart_model, { |
| 151 | + 'tx': ['PA2', 'PA14', 'PB3'], 'rx': ['PA3', 'PA15', 'PB4'] |
| 152 | + }), |
| 153 | + PeripheralFixedResource('USART3', uart_model, { |
| 154 | + 'tx': ['PB9', 'PB10'], 'rx': ['PB8', 'PB11', ] |
| 155 | + }), |
| 156 | + PeripheralFixedResource('LPUART1', uart_model, { |
| 157 | + 'tx': ['PA2', 'PB11'], 'rx': ['PA3', 'PB10'] |
| 158 | + }), |
| 159 | + PeripheralFixedResource('I2C1', i2c_model, { |
| 160 | + 'scl': ['PA13', 'PA15', 'PB8'], 'sda': ['PA14', 'PB7', 'PB9'] |
| 161 | + }), |
| 162 | + PeripheralFixedResource('I2C1_T', i2c_target_model, { |
| 163 | + 'scl': ['PA13', 'PA15', 'PB8'], 'sda': ['PA14', 'PB7', 'PB9'] |
| 164 | + }), |
| 165 | + PeripheralFixedResource('I2C2', i2c_model, { |
| 166 | + 'scl': ['PA9'], 'sda': ['PA8', 'PF0'] |
| 167 | + }), |
| 168 | + PeripheralFixedResource('I2C2_T', i2c_target_model, { |
| 169 | + 'scl': ['PA9'], 'sda': ['PA8', 'PF0'] |
| 170 | + }), |
| 171 | + PeripheralFixedResource('I2C3', i2c_model, { |
| 172 | + 'scl': ['PA8'], 'sda': ['PB5'] |
| 173 | + }), |
| 174 | + PeripheralFixedResource('FDCAN', CanControllerPort(DigitalBidir.empty()), { |
| 175 | + 'tx': ['PA12', 'PB9'], 'rx': ['PA11', 'PB8'] |
| 176 | + }), |
| 177 | + PeripheralFixedResource('SWD', SwdTargetPort(DigitalBidir.empty()), { |
| 178 | + 'swdio': ['PA13'], 'swclk': ['PA14'], |
| 179 | + }), |
| 180 | + PeripheralFixedResource('USB', UsbDevicePort(DigitalBidir.empty()), { |
| 181 | + 'dm': ['PA11'], 'dp': ['PA12'] |
| 182 | + }), |
| 183 | + PeripheralFixedResource('USBCC', UsbCcPort(pullup_capable=True), { |
| 184 | + 'cc1': ['PB6'], 'cc2': ['PB4'] |
| 185 | + }), |
| 186 | + ]).remap_pins(self.RESOURCE_PIN_REMAP) |
| 187 | + |
| 188 | + def generate(self) -> None: |
| 189 | + super().generate() |
| 190 | + self.footprint( |
| 191 | + 'U', self.PACKAGE, |
| 192 | + self._make_pinning(), |
| 193 | + mfr='STMicroelectronics', part=self.PART, |
| 194 | + datasheet='https://www.st.com/resource/en/datasheet/stm32g431kb.pdf' |
| 195 | + ) |
| 196 | + self.assign(self.lcsc_part, self.LCSC_PART) |
| 197 | + self.assign(self.actual_basic_part, False) |
| 198 | + |
| 199 | + |
| 200 | +class Stm32g431_G_Device(Stm32g431Base_Device): |
| 201 | + SYSTEM_PIN_REMAP = { |
| 202 | + 'Vdd': ['1', '15', '17'], # 15 VDDA |
| 203 | + 'Vss': ['14', '16', '32'], # 14 VSSA |
| 204 | + 'BOOT0': '31', |
| 205 | + 'PG10-NRST': '4', |
| 206 | + } |
| 207 | + RESOURCE_PIN_REMAP = { |
| 208 | + 'PF0': '2', |
| 209 | + 'PF1': '3', |
| 210 | + 'PA0': '5', |
| 211 | + 'PA1': '6', |
| 212 | + 'PA2': '7', |
| 213 | + 'PA3': '8', |
| 214 | + 'PA4': '9', |
| 215 | + 'PA5': '10', |
| 216 | + 'PA6': '11', |
| 217 | + 'PA7': '12', |
| 218 | + 'PA8': '18', |
| 219 | + 'PA9': '19', |
| 220 | + 'PA10': '20', |
| 221 | + 'PA11': '21', |
| 222 | + 'PA12': '22', |
| 223 | + 'PA13': '23', |
| 224 | + 'PA14': '24', |
| 225 | + 'PA15': '25', |
| 226 | + 'PB0': '13', |
| 227 | + 'PB3': '26', |
| 228 | + 'PB4': '27', |
| 229 | + 'PB5': '28', |
| 230 | + 'PB6': '29', |
| 231 | + 'PB7': '30', |
| 232 | + } |
| 233 | + PACKAGE = 'Package_DFN_QFN:UFQFPN-32-1EP_5x5mm_P0.5mm_EP3.5x3.5mm' |
| 234 | + PART = 'STM32G431KB' |
| 235 | + LCSC_PART = 'C1341901' # STM32G431KBU3 |
| 236 | + |
| 237 | + |
| 238 | +@abstract_block |
| 239 | +class Stm32g431Base(Resettable, IoControllerI2cTarget, Microcontroller, IoControllerWithSwdTargetConnector, |
| 240 | + IoControllerPowerRequired, BaseIoControllerExportable, GeneratorBlock): |
| 241 | + DEVICE: Type[Stm32g431Base_Device] = Stm32g431Base_Device |
| 242 | + |
| 243 | + def __init__(self, **kwargs): |
| 244 | + super().__init__(**kwargs) |
| 245 | + self.ic: Stm32g431Base_Device |
| 246 | + self.generator_param(self.reset.is_connected()) |
| 247 | + |
| 248 | + def contents(self): |
| 249 | + super().contents() |
| 250 | + with self.implicit_connect( |
| 251 | + ImplicitConnect(self.pwr, [Power]), |
| 252 | + ImplicitConnect(self.gnd, [Common]) |
| 253 | + ) as imp: |
| 254 | + self.ic = imp.Block(self.DEVICE(pin_assigns=ArrayStringExpr())) |
| 255 | + self.connect(self.swd_node, self.ic.swd) |
| 256 | + self.connect(self.reset_node, self.ic.nrst) |
| 257 | + |
| 258 | + # from https://www.st.com/resource/en/application_note/an5093-getting-started-with-stm32g4-series--hardware-development-boards-stmicroelectronics.pdf |
| 259 | + self.pwr_cap0 = imp.Block(DecouplingCapacitor(10 * uFarad(tol=0.2))) |
| 260 | + # from the above pdf, we need 100nF per number of VDD |
| 261 | + self.pwr_cap1 = imp.Block(DecouplingCapacitor(100 * nFarad(tol=0.2))) |
| 262 | + self.pwr_cap2 = imp.Block(DecouplingCapacitor(100 * nFarad(tol=0.2))) |
| 263 | + self.pwr_cap3 = imp.Block(DecouplingCapacitor(100 * nFarad(tol=0.2))) |
| 264 | + self.pwr_cap4 = imp.Block(DecouplingCapacitor(1 * uFarad(tol=0.2))) |
| 265 | + |
| 266 | + def generate(self): |
| 267 | + super().generate() |
| 268 | + if self.get(self.reset.is_connected()): |
| 269 | + self.connect(self.reset, self.ic.nrst) # otherwise NRST has internal pull-up |
| 270 | + |
| 271 | + |
| 272 | +class Stm32g431kb(Stm32g431Base): |
| 273 | + DEVICE = Stm32g431_G_Device |
0 commit comments