Skip to content

Commit d9e0036

Browse files
authored
Stm32g431 (#401)
This is the same as #400, but it removed the accidental commit/push of EspLora. Also applies the fix to the comments. - [x] #400 (comment) - [x] #400 (comment) - [x] #400 (comment) - [x] #400 (comment)
1 parent 34f0e3b commit d9e0036

File tree

4 files changed

+283
-1
lines changed

4 files changed

+283
-1
lines changed

edg/abstract_parts/IoControllerInterfaceMixins.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ class IoControllerUsb(BlockInterfaceMixin[BaseIoController]):
5555
This WILL NOT WORK when used in .with_mixin, since this defines no fields."""
5656
pass
5757

58+
class IoControllerUsbCc(BlockInterfaceMixin[BaseIoController]):
59+
def __init__(self, *args, **kwargs) -> None:
60+
super().__init__(*args, **kwargs)
61+
62+
self.cc = self.Port(Vector(UsbCcPort.empty()), optional=True,
63+
doc="Microcontroller USB Power delivery CC pins")
64+
self.implementation(lambda base: base._io_ports.append(self.cc))
65+
5866

5967
class IoControllerI2s(BlockInterfaceMixin[BaseIoController]):
6068
def __init__(self, *args, **kwargs) -> None:

edg/abstract_parts/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@
9696
from .IoController import BaseIoController, IoController, IoControllerPowerRequired, BaseIoControllerPinmapGenerator
9797
from .IoControllerExportable import BaseIoControllerExportable
9898
from .IoControllerInterfaceMixins import IoControllerSpiPeripheral, IoControllerI2cTarget, IoControllerTouchDriver,\
99-
IoControllerDac, IoControllerCan, IoControllerUsb, IoControllerI2s, IoControllerDvp8
99+
IoControllerDac, IoControllerCan, IoControllerUsb, IoControllerI2s, IoControllerDvp8, IoControllerUsbCc
100100
from .IoControllerInterfaceMixins import IoControllerPowerOut, IoControllerUsbOut, IoControllerVin
101101
from .IoControllerInterfaceMixins import IoControllerWifi, IoControllerBluetooth, IoControllerBle
102102
from .IoControllerProgramming import IoControllerWithSwdTargetConnector
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
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

edg/parts/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
from .Microcontroller_Stm32f103 import Stm32f103_48
7878
from .Microcontroller_Stm32f303 import Nucleo_F303k8
7979
from .Microcontroller_Stm32g031 import Stm32g031_G
80+
from .Microcontroller_Stm32g431 import Stm32g431kb
8081
from .Microcontroller_Stm32l432 import Stm32l432k
8182
from .Microcontroller_nRF52840 import Holyiot_18010, Mdbt50q_1mv2, Feather_Nrf52840
8283
from .Microcontroller_Esp import EspProgrammingHeader, EspProgrammingAutoReset, EspProgrammingPinHeader254, EspProgrammingTc2030

0 commit comments

Comments
 (0)