Skip to content

Commit 543f968

Browse files
committed
chore: Swan Init and Clean-up
1 parent acb4101 commit 543f968

File tree

3 files changed

+149
-83
lines changed

3 files changed

+149
-83
lines changed

variants/STM32L4xx/L4R5Z(G-I)Y_L4R9Z(G-I)Y_L4S5ZIY_L4S9ZIY/PeripheralPins_SWAN_R5.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@
1111
*******************************************************************************
1212
*/
1313
/*
14-
* Automatically generated from STM32L4R5Z(G-I)Yx.xml, STM32L4R9Z(G-I)Yx.xml
15-
* STM32L4S5ZIYx.xml, STM32L4S9ZIYx.xml
16-
* CubeMX DB release 6.0.21
14+
* Manually generated by Blues with knowledge of the SWAN_R5 schematic
15+
* https://github.com/blues/note-hardware/blob/master/Swan/v3.0/Feather/Swan%20Feather%20schematic%20v3.0.pdf
1716
*/
1817
#if defined(ARDUINO_SWAN_R5)
1918
#include "Arduino.h"

variants/STM32L4xx/L4R5Z(G-I)Y_L4R9Z(G-I)Y_L4S5ZIY_L4S9ZIY/variant_SWAN_R5.cpp

Lines changed: 113 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*
1111
*******************************************************************************
1212
*/
13+
1314
#if defined(ARDUINO_SWAN_R5)
1415
#include "pins_arduino.h"
1516

@@ -122,81 +123,112 @@ WEAK void initVariant(void)
122123
{
123124
/* All pins set to high-Z (floating) initially */
124125
/* DS12023 Rev 5, Section 3.10.5 - Reset mode: */
125-
/* In order to improve the consumption under reset, the I/Os state under and after reset is
126-
* “analog state” (the I/O schmitt trigger is disable). In addition, the internal reset pull-up is
127-
* deactivated when the reset source is internal.
126+
/* In order to improve the consumption under reset, the I/Os state under
127+
* and after reset is "analog state" (the I/O schmitt trigger is disabled).
128+
* In addition, the internal reset pull-up is deactivated when the reset
129+
* source is internal.
128130
*/
129131

130-
/* Turn on the 3V3 regulator */
131-
__HAL_RCC_GPIOE_CLK_ENABLE();
132-
GPIO_InitTypeDef GPIO_InitStruct;
133-
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
134-
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
135-
GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_6;
136-
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
137-
HAL_GPIO_WritePin(GPIOE, GPIO_InitStruct.Pin, GPIO_PIN_SET);
132+
/* Configure the 3V3 regulator */
133+
{
134+
__HAL_RCC_GPIOE_CLK_ENABLE();
135+
GPIO_InitTypeDef GPIO_InitStruct = {};
136+
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
137+
138+
/* PE4 is ENABLE_3V3 */
139+
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
140+
GPIO_InitStruct.Pin = GPIO_PIN_4;
141+
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
142+
143+
/* PE6 is DISCHARGE_3V3 */
144+
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
145+
GPIO_InitStruct.Pin = GPIO_PIN_6;
146+
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
147+
148+
/* Enable 3V3 regulator and disable discharging */
149+
HAL_GPIO_WritePin(GPIOE, (GPIO_PIN_4 | GPIO_PIN_6), GPIO_PIN_SET);
150+
}
138151
}
139152

140153
/**
141-
* @brief System Clock Configuration – High-performance STM32L4R5xx with PLL from MSI
142-
*
143-
* Key features:
144-
* • SYSCLK = 120 MHz from PLL (MSI Range 11 /6 × 30 /2 via PLLR)
145-
* • USB FS uses MSI Range 11 as CLK48 source ("The MSI clock can be selected as clock source for the USB FS device, SDMMC1 and RNG when the MSI is in Range 11 (48 MHz)", RM0432 Rev 9 §6.2.10)
146-
* • OSPI clocked from SYSCLK (120 MHz)
147-
* • ADC clocked from SYSCLK (120 MHz)
148-
* • LSE enabled for RTC timing
149-
* • Voltage Scale 1 Boost required for 120 MHz ("In Range 1 boost mode (R1MODE = 0), the maximum system clock frequency is 120 MHz", RM0432 §5.3.11)
150-
* • MSI PLL-mode enabled ("The MSI PLL-mode can be used to obtain a more accurate MSI frequency when the device wakes up from Stop mode", RM0432 §6.3.16)
151-
*
152-
* References:
153-
* • RM0432 Rev 9 – STM32L4+ Series advanced Arm-based 32-bit MCUs (www.st.com/resource/en/reference_manual/rm0432-stm32l4-series-advanced-armbased-32bit-mcus-stmicroelectronics.pdf)
154-
* • RM0432 §6.2.5 – PLL characteristics: VCO frequency range 64-344 MHz
155-
* • RM0432 §6.4.4 – PLL configuration: PLLM divides input to 4-16 MHz range
156-
* • RM0432 §6.2.14 – "PLLR clock output is used to generate the system clock"
157-
* • RM0432 Table 15 – Flash latency 5 wait states at 120 MHz in Range 1 Boost
158-
* • RM0432 Table 31 – LSEDRV[1:0] = 01 for medium low drive capability
159-
* • STM32CubeL4 v1.18.0 (07 Jun 2023) – USB_Device examples for NUCLEO-L4R5ZI (www.st.com/en/embedded-software/stm32cubel4.html)
160-
* • AN2867 Rev 23 (Jan 2025) – Guidelines for oscillator design on STM32 MCUs/MPUs (www.st.com/resource/en/application_note/an2867-guidelines-for-oscillator-design-on-stm8afals-and-stm32-mcusmpus-stmicroelectronics.pdf)
161-
*/
154+
* @brief System Clock Configuration - High-performance STM32L4R5xx with PLL from MSI
155+
*
156+
* Key features:
157+
* - SYSCLK = 120 MHz from PLL (MSI Range 11 /6 x 30 /2 via PLLR)
158+
* - USB FS uses MSI Range 11 as CLK48 source (48 MHz, RM0432 s.6.2.3)
159+
* - OSPI clocked from SYSCLK (120 MHz)
160+
* - ADC clocked from SYSCLK (120 MHz)
161+
* - LSE enabled for RTC timing and MSI auto-calibration (MSIPLLEN)
162+
* - Voltage Scale 1 Boost required for 120 MHz (RM0432 s.5.1.8)
163+
* - MSI PLL-mode (MSIPLLEN) enabled after peripheral clocks to avoid premature MSIRDY deassertion during PeriphCLKConfig
164+
*
165+
* References:
166+
* - RM0432 Rev 9 - STM32L4+ Series advanced Arm-based 32-bit MCUs
167+
* (www.st.com/resource/en/reference_manual/rm0432-stm32l4-series-advanced-armbased-32bit-mcus-stmicroelectronics.pdf)
168+
* - RM0432 s.5.1.8 - Dynamic voltage scaling management: Range 1 boost mode up to 120 MHz
169+
* - RM0432 s.6.2.3 - MSI clock: MSI as CLK48 source for USB FS in Range 11; MSI PLL-mode (MSIPLLEN)
170+
* - RM0432 s.6.2.5 - PLL: source input range 4-16 MHz
171+
* - RM0432 s.6.4.4 - PLL configuration register (RCC_PLLCFGR): PLLM/PLLN/PLLR fields;
172+
* VCO input 2.66-8 MHz; VCO output 64-344 MHz; PLLR drives SYSCLK
173+
* - RM0432 Table 12 - Flash latency: 5 wait states at 120 MHz in Range 1 Boost
174+
* - RM0432 s.6.4.29 - RCC_BDCR: LSEDRV[1:0] = 01 for medium low drive capability
175+
* - AN2867 Rev 23 (Jan 2025) - Guidelines for oscillator design on STM32 MCUs/MPUs
176+
* (www.st.com/resource/en/application_note/an2867-guidelines-for-oscillator-design-on-stm8afals-and-stm32-mcusmpus-stmicroelectronics.pdf)
177+
*/
162178
WEAK void SystemClock_Config(void)
163179
{
164180
RCC_OscInitTypeDef RCC_OscInitStruct = {};
165181
RCC_ClkInitTypeDef RCC_ClkInitStruct = {};
166182
RCC_PeriphCLKInitTypeDef PeriphClkInit = {};
167183

168-
/* -------------------------------------------------------------------------
169-
* 1. Voltage scaling – Scale 1 Boost for SYSCLK up to 120 MHz
170-
* "Range 1 boost mode is selected by setting the BOOSTEN bit … and allows to reach 120 MHz"
171-
* (RM0432 Rev 9 §5.3.11 Voltage regulator)
172-
* ------------------------------------------------------------------------- */
184+
/** Enable PWR peripheral clock
185+
*
186+
* RM0432 s.6.4.19: PWREN (RCC_APB1ENR1 bit 28) resets to 0, so this call
187+
* is required before accessing any PWR register (e.g.,
188+
* HAL_PWREx_ControlVoltageScaling below).
189+
* CubeMX generates this unconditionally for all STM32L4 projects.
190+
*/
191+
__HAL_RCC_PWR_CLK_ENABLE();
192+
193+
/* Voltage scaling - Scale 1 Boost required for SYSCLK = 120 MHz
194+
* RM0432 s.5.1.8: "In Range 1 boost mode (R1MODE = 0), the maximum system
195+
* clock frequency is 120 MHz"
196+
*/
173197
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST) != HAL_OK) {
174198
Error_Handler();
175199
}
176200

177-
/* -------------------------------------------------------------------------
178-
* 2. LSE drive capability – medium low (LSEDRV[1:0] = 01)
179-
* "LSEDRV[1:0] = 01: medium low drive capability"
180-
* (RM0432 Rev 9 Table 31 LSE drive capability)
181-
* See AN2867 Rev 23 §5.2 for STM32-compatible low-speed resonators
182-
* ------------------------------------------------------------------------- */
201+
/** Configure LSE Drive Capability
202+
*
203+
* Use MEDIUMLOW (not LOW): RCC_LSEDRIVE_LOW risks marginal LSE startup on units
204+
* near the crystal ESR tolerance limit and degrades MSI PLL mode (MSIPLLEN) lock
205+
* quality. ST recommends MEDIUMLOW as the minimum when MSIPLLEN is in use.
206+
* (RM0432 s.6.4.29; AN2867 Rev 23)
207+
*
208+
* Backup domain access must be enabled before configuring LSE, as RCC->BDCR
209+
* is write-protected after reset and silently ignores writes until the lock
210+
* is cleared.
211+
*/
183212
HAL_PWR_EnableBkUpAccess();
184213
__HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_MEDIUMLOW);
185214

186-
/* -------------------------------------------------------------------------
187-
* 3. Oscillator configuration
188-
* • MSI = ON, Range 11 (48 MHz) – PLL source and USB CLK48
189-
* • LSE = ON – for RTC
190-
* • PLL = ON – MSI /6 ×30 /2 (PLLR) = 120 MHz SYSCLK
191-
* PLL input = 48 /6 = 8 MHz (4-16 MHz range, RM0432 §6.4.4)
192-
* VCO = 8 ×30 = 240 MHz (64-344 MHz range, RM0432 §6.2.5)
193-
* SYSCLK from PLLR /2 = 120 MHz (RM0432 §6.2.14)
194-
* • HSI not included (off by default)
195-
* ------------------------------------------------------------------------- */
196-
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_MSI;
215+
/** Initializes the RCC Oscillators according to the specified parameters
216+
* in the RCC_OscInitTypeDef structure.
217+
*
218+
* Oscillator configuration summary:
219+
* - MSI: MSIRANGE_11 (48 MHz) -- PLL source and USB CLK48 (RM0432 s.6.2.3)
220+
* - LSE: ON -- for RTC and MSI auto-calibration (MSIPLLEN)
221+
* - PLL: ON (MSI 48 MHz / PLLM=6 x PLLN=30 / PLLR=2 = 120 MHz)
222+
* - PLL source: 48 MHz (4-16 MHz range, RM0432 s.6.2.5)
223+
* - PLL input (after PLLM): 48/6 = 8 MHz (2.66-8 MHz range, RM0432 s.6.4.4)
224+
* - VCO: 8x30 = 240 MHz (64-344 MHz range, RM0432 s.6.4.4)
225+
* - SYSCLK from PLLR/2 = 120 MHz (RM0432 s.6.4.4)
226+
*/
227+
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE
228+
| RCC_OSCILLATORTYPE_MSI;
197229
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
198230
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
199-
RCC_OscInitStruct.MSICalibrationValue = 0;
231+
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
200232
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_11;
201233
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
202234
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
@@ -209,47 +241,51 @@ WEAK void SystemClock_Config(void)
209241
Error_Handler();
210242
}
211243

212-
/* -------------------------------------------------------------------------
213-
* 4. System clock mux and bus dividers
214-
* SYSCLK = PLLR = 120 MHz, no AHB/APB dividers
215-
* Flash latency = 5 WS ("5 wait states" at 120 MHz, Range 1 Boost, RM0432 Table 15)
216-
* ------------------------------------------------------------------------- */
244+
/** Initializes the CPU, AHB and APB buses clocks
245+
*
246+
* SYSCLK = PLLCLK (120 MHz). No AHB/APB dividers.
247+
*/
217248
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1
218249
| RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_SYSCLK;
219250
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
220251
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
221252
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
222253
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
223-
254+
/* FLASH_LATENCY_5: required for 120 MHz at Range 1 Boost (RM0432 Table 12) */
224255
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) {
225256
Error_Handler();
226257
}
227258

228-
/* -------------------------------------------------------------------------
229-
* 5. Peripheral clock selection
230-
* • USB → MSI (48 MHz, valid in Range 11, RM0432 §6.2.10)
231-
* • OSPI → SYSCLK (120 MHz)
232-
* • ADC → SYSCLK (120 MHz)
233-
* • SDMMC1 not selected
234-
* (RM0432 §6.3.2: Peripheral clocks set after SYSCLK)
235-
* ------------------------------------------------------------------------- */
259+
/** Initializes the Peripheral clocks
260+
*
261+
* USB clock: MSI Range 11 (48 MHz). RM0432 s.6.2.3: "The MSI clock can be
262+
* selected as clock source for the USB FS device, SDMMC1 and RNG when the
263+
* MSI is in Range 11 (48 MHz)."
264+
* OSPI and ADC clocked from SYSCLK (120 MHz).
265+
*/
236266
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC
237267
| RCC_PERIPHCLK_OSPI
238-
// | RCC_PERIPHCLK_SDMMC1
239-
| RCC_PERIPHCLK_USB
268+
| RCC_PERIPHCLK_USB;
240269
PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_SYSCLK;
241270
PeriphClkInit.OspiClockSelection = RCC_OSPICLKSOURCE_SYSCLK;
242271
PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_MSI;
243-
// PeriphClkInit.Sdmmc1ClockSelection = RCC_SDMMC1CLKSOURCE_NONE;
244272
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
245273
Error_Handler();
246274
}
247275

248-
/* -------------------------------------------------------------------------
249-
* 6. MSI PLL-mode enable
250-
* "The MSI PLL-mode can be used to obtain a more accurate MSI frequency when the device wakes up from Stop mode"
251-
* (RM0432 Rev 9 §6.3.16 MSI PLL-mode)
252-
* ------------------------------------------------------------------------- */
276+
/** Enable MSI Auto calibration (MSIPLLEN, RCC_CR[2])
277+
*
278+
* RM0432 s.6.2.3: setting MSIPLLEN causes the MSI hardware to automatically
279+
* trim itself against LSE as a phase reference. LSE must already be stable
280+
* (LSERDY=1) before the bit is set -- guaranteed here because
281+
* HAL_RCC_OscConfig() waited for LSERDY before returning.
282+
*
283+
* This call must come AFTER HAL_RCCEx_PeriphCLKConfig() -- setting MSIPLLEN
284+
* causes MSIRDY to deassert transiently while MSI re-synchronises to LSE.
285+
* Because SYSCLK is PLLCLK (120 MHz), SysTick is decoupled from MSI and
286+
* HAL_GetTick() remains reliable; the concern is HAL routines that check
287+
* MSIRDY as a readiness flag, all of which must complete before this call.
288+
*/
253289
HAL_RCCEx_EnableMSIPLLMode();
254290
}
255291

variants/STM32L4xx/L4R5Z(G-I)Y_L4R9Z(G-I)Y_L4S5ZIY_L4S9ZIY/variant_SWAN_R5.h

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,41 @@
156156
#define DISABLE_DISCHARGING HIGH
157157
#define ENABLE_DISCHARGING LOW
158158
#endif
159-
#ifndef BATTERY_VOLTAGE
160-
#define BATTERY_VOLTAGE PA0
159+
160+
// Macro functions for 3V3 regulator management
161+
#ifndef ENABLE_3V3_REGULATOR
162+
# define ENABLE_3V3_REGULATOR() do { \
163+
digitalWrite(DISCHARGE_3V3, DISABLE_DISCHARGING); \
164+
digitalWrite(ENABLE_3V3, HIGH); \
165+
} while (0)
166+
#endif
167+
#ifndef DISABLE_3V3_REGULATOR
168+
# define DISABLE_3V3_REGULATOR() do { \
169+
digitalWrite(ENABLE_3V3, LOW); \
170+
} while (0)
171+
#endif
172+
#ifndef DRAIN_3V3_REGULATOR_MS
173+
# define DRAIN_3V3_REGULATOR_MS(ms) do { \
174+
if (digitalRead(ENABLE_3V3)) { break; } \
175+
digitalWrite(DISCHARGE_3V3, ENABLE_DISCHARGING); \
176+
delay(ms); \
177+
digitalWrite(DISCHARGE_3V3, DISABLE_DISCHARGING); \
178+
} while (0)
179+
#endif
180+
181+
// Dedicated board pins
182+
#ifndef VMAIN_ADC
183+
#define VMAIN_ADC PA0
184+
#define VMAIN_ADC_DIV_BOT_R 4.3f
185+
#define VMAIN_ADC_DIV_TOP_R 10.0f
186+
#define VMAIN_ADC_DIV_K ((double)((VMAIN_ADC_DIV_TOP_R + VMAIN_ADC_DIV_BOT_R) / VMAIN_ADC_DIV_BOT_R))
187+
#endif
188+
#ifndef VMAIN_MV
189+
# define VMAIN_MV() ({ \
190+
__HAL_ADC_CALC_DATA_TO_VOLTAGE(__LL_ADC_CALC_VREFANALOG_VOLTAGE(analogRead(AVREF), LL_ADC_GetResolution(ADC1)), analogRead(VMAIN_ADC), LL_ADC_GetResolution(ADC1)) * VMAIN_ADC_DIV_K; \
191+
})
161192
#endif
162-
// Charge detection is not supported on the Swan
193+
// Charge detection is not implemented on the Swan hardware
163194
// #ifndef CHARGE_DETECT
164195
// #define CHARGE_DETECT
165196
// #endif

0 commit comments

Comments
 (0)