From 0051141f0c604c995a35b7e0e28ea4725a5a23ca Mon Sep 17 00:00:00 2001 From: Nikita Solianik Date: Wed, 15 Jul 2026 22:51:09 +0200 Subject: [PATCH 1/8] fix(sn32 uart): remove non-locked osalSysUnlockFromISR --- os/hal/ports/SN32/LLD/SN32F2xx/UART/hal_serial_lld.c | 1 - 1 file changed, 1 deletion(-) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/UART/hal_serial_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/UART/hal_serial_lld.c index b3c36d6dbe..a8a5bc1e81 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/UART/hal_serial_lld.c +++ b/os/hal/ports/SN32/LLD/SN32F2xx/UART/hal_serial_lld.c @@ -311,7 +311,6 @@ static void serve_interrupt(SerialDriver *sdp) { break; } u->TH = b; - osalSysUnlockFromISR(); ls = u->LS; } } From 880d3b5a23b6555fc68e90ecbf07f3a14c8605f0 Mon Sep 17 00:00:00 2001 From: Nikita Solianik Date: Thu, 16 Jul 2026 21:10:07 +0200 Subject: [PATCH 2/8] fix(flash): Fix startup LPMODE for flash --- os/common/ext/SONiX/SN32F2xx/system_SN32F240B.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/os/common/ext/SONiX/SN32F2xx/system_SN32F240B.c b/os/common/ext/SONiX/SN32F2xx/system_SN32F240B.c index 30f63aea27..91234d7110 100644 --- a/os/common/ext/SONiX/SN32F2xx/system_SN32F240B.c +++ b/os/common/ext/SONiX/SN32F2xx/system_SN32F240B.c @@ -177,10 +177,10 @@ void FlashClockUpdate (void) */ void SlowModeSwitch (void) { - SN_SYS0->CLKCFG_b.SYSCLKSEL = 1; //Switch to ILRC - SN_SYS0->AHBCP_b.AHBPRE =0x2; //8kHz only for now + SN_SYS0->CLKCFG_b.SYSCLKSEL = 1; //Switch to ILRC 32kHz + SN_SYS0->AHBCP_b.AHBPRE =0x2; // 32/4 = 8kHz only for now SystemCoreClockUpdate(); - SN_FLASH->LPCTRL = 0x5AFA0002; + SN_FLASH->LPCTRL = 0x5AFA0000; } /** * Initialize the system @@ -197,6 +197,11 @@ void SystemInit (void) #if SYS0_CLKCFG_VAL == IHRC48 //IHRC=48MHz + /* Configure flash wait-states for 48MHz BEFORE enabling IHRC, + * matching the factory firmware init sequence. Writing LPCTRL + * at the reset clock rate (ILRC 32kHz) is safe regardless of + * LPMODE value — there is no race window later. */ + SN_FLASH->LPCTRL = 0x5AFA0004; SN_FLASH->LPCTRL = 0x5AFA0005; SN_SYS0->ANBCTRL = 0x1; @@ -205,7 +210,7 @@ void SystemInit (void) while ((SN_SYS0->CLKCFG & 0x70) != 0x0); #endif - #if SYS0_CLKCFG_VAL == ILRC //ILRC ON + #if SYS0_CLKCFG_VAL == ILRC //ILRC ON SN_FLASH->LPCTRL = 0x5AFA0000; SN_SYS0->CLKCFG = 0x1; while ((SN_SYS0->CLKCFG & 0x70) != 0x10); From 680b249aeec2a60c5880d0d7ba9d127d491e16ee Mon Sep 17 00:00:00 2001 From: Nikita Solianik Date: Fri, 17 Jul 2026 23:52:54 +0200 Subject: [PATCH 3/8] fix(adc): Enable AIN16, AIN17, AIN18, few nitpicks --- os/hal/ports/SN32/LLD/SN32F2xx/ADC/hal_adc_lld.c | 4 ++-- os/hal/ports/SN32/LLD/SN32F2xx/ADC/hal_adc_lld.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/ADC/hal_adc_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/ADC/hal_adc_lld.c index 593ff41b74..86ed360901 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/ADC/hal_adc_lld.c +++ b/os/hal/ports/SN32/LLD/SN32F2xx/ADC/hal_adc_lld.c @@ -42,7 +42,7 @@ ADCDriver ADCD1; /*===========================================================================*/ /* Driver local variables and types. */ /*===========================================================================*/ -#define ADC_CHANNEL_MASK 0x0F +#define ADC_CHANNEL_MASK 0x1F /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ @@ -172,7 +172,6 @@ void adc_lld_start_conversion(ADCDriver *adcp) { /* Apply ADC configuration.*/ if(grpp->avrefhsel) adcSN32EnableAVREFHSEL(adcp); adcp->adc->ADM_b.VHS = grpp->vhs; - adcSN32EnableGCHS(adcp->adc); adcp->adc->ADM_b.ADLEN = grpp->adlen; adcp->number_of_samples = adcp->depth * grpp->num_channels; @@ -191,6 +190,7 @@ void adc_lld_start_conversion(ADCDriver *adcp) { adcp->adc->RIS = 0U; adcp->adc->IE = ADC_IE_AIN(adcp->current_channel); + adcSN32EnableGCHS(adcp->adc); /* ADC conversion start.*/ adcp->adc->ADM_b.ADS |= ADC_ADS_START; } diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/ADC/hal_adc_lld.h b/os/hal/ports/SN32/LLD/SN32F2xx/ADC/hal_adc_lld.h index 70e0894d5e..8ea21955a2 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/ADC/hal_adc_lld.h +++ b/os/hal/ports/SN32/LLD/SN32F2xx/ADC/hal_adc_lld.h @@ -115,7 +115,7 @@ /** * @brief ADC wake-up procedure duration. */ -#if !defined(SN32_USB_HOST_WAKEUP_DURATION) || defined(__DOXYGEN__) +#if !defined(SN32_ADC_WAKEUP_DURATION) || defined(__DOXYGEN__) #define SN32_ADC_WAKEUP_DURATION 100 #endif @@ -139,7 +139,7 @@ #endif /* ADC IRQ priority tests.*/ -#if !OSAL_IRQ_IS_VALID_PRIORITY(SN32_ADC_ADC_IRQ_PRIORITY) +#if !OSAL_IRQ_IS_VALID_PRIORITY(SN32_ADC_IRQ_PRIORITY) #error "Invalid IRQ priority assigned to ADC" #endif From 8f21d8ecd8251c7a2148c4c74792988f475a626a Mon Sep 17 00:00:00 2001 From: Nikita Solianik Date: Tue, 21 Jul 2026 22:32:39 +0200 Subject: [PATCH 4/8] feat(sn32): add Low Voltage Detector support --- os/hal/ports/SN32/SN32F240/hal_lld.c | 20 ++++++++++++++++++++ os/hal/ports/SN32/SN32F240/hal_lld.h | 20 ++++++++++++++++++++ os/hal/ports/SN32/SN32F240/sn32_registry.h | 9 +++++++++ os/hal/ports/SN32/SN32F240B/hal_lld.c | 20 ++++++++++++++++++++ os/hal/ports/SN32/SN32F240B/hal_lld.h | 20 ++++++++++++++++++++ os/hal/ports/SN32/SN32F240B/sn32_registry.h | 7 +++++++ os/hal/ports/SN32/SN32F240C/hal_lld.c | 20 ++++++++++++++++++++ os/hal/ports/SN32/SN32F240C/hal_lld.h | 20 ++++++++++++++++++++ os/hal/ports/SN32/SN32F240C/sn32_registry.h | 6 ++++++ os/hal/ports/SN32/SN32F260/hal_lld.c | 20 ++++++++++++++++++++ os/hal/ports/SN32/SN32F260/hal_lld.h | 20 ++++++++++++++++++++ os/hal/ports/SN32/SN32F260/sn32_registry.h | 7 +++++++ os/hal/ports/SN32/SN32F290/hal_lld.c | 20 ++++++++++++++++++++ os/hal/ports/SN32/SN32F290/hal_lld.h | 20 ++++++++++++++++++++ os/hal/ports/SN32/SN32F290/sn32_registry.h | 6 ++++++ 15 files changed, 235 insertions(+) diff --git a/os/hal/ports/SN32/SN32F240/hal_lld.c b/os/hal/ports/SN32/SN32F240/hal_lld.c index 4380234563..7d85108371 100644 --- a/os/hal/ports/SN32/SN32F240/hal_lld.c +++ b/os/hal/ports/SN32/SN32F240/hal_lld.c @@ -60,12 +60,32 @@ void sn32_clock_init(void) { SystemCoreClockUpdate(); } +#if SN32_LVD_ENABLE == TRUE + +/** + * @brief LVD initialization. + * + * @notapi + */ +static void sn32_lvd_init(void) { + SN_SYS0->LVDCTRL_b.LVDRSTLVL = SN32_LVDRSTLVL; + SN_SYS0->LVDCTRL_b.LVDINTLVL = SN32_LVDINTLVL; + SN_SYS0->LVDCTRL_b.LVDRSTEN = (SN32_LVDRSTEN) ? 1U : 0U; + SN_SYS0->LVDCTRL_b.LVDEN = 1U; +} + +#endif /* SN32_LVD_ENABLE */ + /** * @brief Low level HAL driver initialization. * * @notapi */ void hal_lld_init(void) { +#if SN32_LVD_ENABLE == TRUE + sn32_lvd_init(); +#endif /* SN32_LVD_ENABLE */ + SystemInit(); sn32_clock_init(); } diff --git a/os/hal/ports/SN32/SN32F240/hal_lld.h b/os/hal/ports/SN32/SN32F240/hal_lld.h index a92bca2894..d5c7627244 100644 --- a/os/hal/ports/SN32/SN32F240/hal_lld.h +++ b/os/hal/ports/SN32/SN32F240/hal_lld.h @@ -88,6 +88,26 @@ #include "nvic.h" #include "sn32_sys1.h" +/*===========================================================================*/ +/* LVD driver pre-compile time settings. */ +/*===========================================================================*/ + +#if !defined(SN32_LVD_ENABLE) || defined(__DOXYGEN__) +#define SN32_LVD_ENABLE FALSE +#endif + +#if !defined(SN32_LVDRSTLVL) || defined(__DOXYGEN__) +#define SN32_LVDRSTLVL SN32_LVD_LEVEL_2_40V +#endif + +#if !defined(SN32_LVDINTLVL) || defined(__DOXYGEN__) +#define SN32_LVDINTLVL SN32_LVD_LEVEL_2_40V +#endif + +#if !defined(SN32_LVDRSTEN) || defined(__DOXYGEN__) +#define SN32_LVDRSTEN TRUE +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/os/hal/ports/SN32/SN32F240/sn32_registry.h b/os/hal/ports/SN32/SN32F240/sn32_registry.h index aaa9c80a07..1f097aee65 100644 --- a/os/hal/ports/SN32/SN32F240/sn32_registry.h +++ b/os/hal/ports/SN32/SN32F240/sn32_registry.h @@ -144,6 +144,14 @@ #define SN32_LVD_HANDLER VectorA8 #define SN32_LVD_NUMBER LVD_IRQn +/* LVD threshold levels (3-bit LVDRSTLVL / LVDINTLVL). */ +#define SN32_LVD_LEVEL_1_80V 0x0 +#define SN32_LVD_LEVEL_2_00V 0x1 +#define SN32_LVD_LEVEL_2_40V 0x2 +#define SN32_LVD_LEVEL_2_70V 0x3 +#define SN32_LVD_LEVEL_3_00V 0x4 +#define SN32_LVD_LEVEL_3_60V 0x5 + /* * GPIO units. */ @@ -172,6 +180,7 @@ #define SN32_FLASH_SECTOR_SIZE 1024U #define SN32_FLASH_BASE 0x00000000UL #define FLASH_SIZE (SN32_FLASH_NUMBER_OF_BANKS * SN32_FLASH_SECTORS_PER_BANK * SN32_FLASH_SECTOR_SIZE) + /*===========================================================================*/ /* Common. */ /*===========================================================================*/ diff --git a/os/hal/ports/SN32/SN32F240B/hal_lld.c b/os/hal/ports/SN32/SN32F240B/hal_lld.c index a6794a0573..7e0bf228a2 100644 --- a/os/hal/ports/SN32/SN32F240B/hal_lld.c +++ b/os/hal/ports/SN32/SN32F240B/hal_lld.c @@ -61,12 +61,32 @@ void sn32_clock_init(void) { FlashClockUpdate(); } +#if SN32_LVD_ENABLE == TRUE + +/** + * @brief LVD initialization. + * + * @notapi + */ +static void sn32_lvd_init(void) { + SN_SYS0->LVDCTRL_b.LVDRSTLVL = SN32_LVDRSTLVL; + SN_SYS0->LVDCTRL_b.LVDINTLVL = SN32_LVDINTLVL; + SN_SYS0->LVDCTRL_b.LVDRSTEN = (SN32_LVDRSTEN) ? 1U : 0U; + SN_SYS0->LVDCTRL_b.LVDEN = 1U; +} + +#endif /* SN32_LVD_ENABLE */ + /** * @brief Low level HAL driver initialization. * * @notapi */ void hal_lld_init(void) { +#if SN32_LVD_ENABLE == TRUE + sn32_lvd_init(); +#endif /* SN32_LVD_ENABLE */ + SystemInit(); sn32_clock_init(); } diff --git a/os/hal/ports/SN32/SN32F240B/hal_lld.h b/os/hal/ports/SN32/SN32F240B/hal_lld.h index 60f689cad8..a674d0cf07 100644 --- a/os/hal/ports/SN32/SN32F240B/hal_lld.h +++ b/os/hal/ports/SN32/SN32F240B/hal_lld.h @@ -94,6 +94,26 @@ #include "sn32_ct.h" #include "sn32_sys1.h" +/*===========================================================================*/ +/* LVD driver pre-compile time settings. */ +/*===========================================================================*/ + +#if !defined(SN32_LVD_ENABLE) || defined(__DOXYGEN__) +#define SN32_LVD_ENABLE FALSE +#endif + +#if !defined(SN32_LVDRSTLVL) || defined(__DOXYGEN__) +#define SN32_LVDRSTLVL SN32_LVD_LEVEL_2_40V +#endif + +#if !defined(SN32_LVDINTLVL) || defined(__DOXYGEN__) +#define SN32_LVDINTLVL SN32_LVD_LEVEL_2_40V +#endif + +#if !defined(SN32_LVDRSTEN) || defined(__DOXYGEN__) +#define SN32_LVDRSTEN TRUE +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/os/hal/ports/SN32/SN32F240B/sn32_registry.h b/os/hal/ports/SN32/SN32F240B/sn32_registry.h index f337bb68d4..ff7cce6315 100644 --- a/os/hal/ports/SN32/SN32F240B/sn32_registry.h +++ b/os/hal/ports/SN32/SN32F240B/sn32_registry.h @@ -126,6 +126,12 @@ #define SN32_LVD_HANDLER VectorA8 #define SN32_LVD_NUMBER LVD_IRQn +/* LVD threshold levels (3-bit LVDRSTLVL / LVDINTLVL). */ +#define SN32_LVD_LEVEL_2_40V 0x2 +#define SN32_LVD_LEVEL_2_70V 0x3 +#define SN32_LVD_LEVEL_3_00V 0x4 +#define SN32_LVD_LEVEL_3_60V 0x5 + /* * GPIO units. */ @@ -154,6 +160,7 @@ #define SN32_FLASH_SECTOR_SIZE 64U #define SN32_FLASH_BASE 0x00000000UL #define FLASH_SIZE (SN32_FLASH_NUMBER_OF_BANKS * SN32_FLASH_SECTORS_PER_BANK * SN32_FLASH_SECTOR_SIZE) + /*===========================================================================*/ /* Common. */ /*===========================================================================*/ diff --git a/os/hal/ports/SN32/SN32F240C/hal_lld.c b/os/hal/ports/SN32/SN32F240C/hal_lld.c index a61568a9b6..914b18542c 100644 --- a/os/hal/ports/SN32/SN32F240C/hal_lld.c +++ b/os/hal/ports/SN32/SN32F240C/hal_lld.c @@ -61,12 +61,32 @@ void sn32_clock_init(void) { FlashClockUpdate(); } +#if SN32_LVD_ENABLE == TRUE + +/** + * @brief LVD initialization. + * + * @notapi + */ +static void sn32_lvd_init(void) { + SN_SYS0->LVDCTRL_b.LVDRSTLVL = SN32_LVDRSTLVL; + SN_SYS0->LVDCTRL_b.LVDINTLVL = SN32_LVDINTLVL; + SN_SYS0->LVDCTRL_b.LVDRSTEN = (SN32_LVDRSTEN) ? 1U : 0U; + SN_SYS0->LVDCTRL_b.LVDEN = 1U; +} + +#endif /* SN32_LVD_ENABLE */ + /** * @brief Low level HAL driver initialization. * * @notapi */ void hal_lld_init(void) { +#if SN32_LVD_ENABLE == TRUE + sn32_lvd_init(); +#endif /* SN32_LVD_ENABLE */ + SystemInit(); sn32_clock_init(); } diff --git a/os/hal/ports/SN32/SN32F240C/hal_lld.h b/os/hal/ports/SN32/SN32F240C/hal_lld.h index ef1e5b27ef..51668a5816 100644 --- a/os/hal/ports/SN32/SN32F240C/hal_lld.h +++ b/os/hal/ports/SN32/SN32F240C/hal_lld.h @@ -94,6 +94,26 @@ #include "sn32_ct.h" #include "sn32_sys1.h" +/*===========================================================================*/ +/* LVD driver pre-compile time settings. */ +/*===========================================================================*/ + +#if !defined(SN32_LVD_ENABLE) || defined(__DOXYGEN__) +#define SN32_LVD_ENABLE FALSE +#endif + +#if !defined(SN32_LVDRSTLVL) || defined(__DOXYGEN__) +#define SN32_LVDRSTLVL SN32_LVD_LEVEL_2_40V +#endif + +#if !defined(SN32_LVDINTLVL) || defined(__DOXYGEN__) +#define SN32_LVDINTLVL SN32_LVD_LEVEL_2_40V +#endif + +#if !defined(SN32_LVDRSTEN) || defined(__DOXYGEN__) +#define SN32_LVDRSTEN TRUE +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/os/hal/ports/SN32/SN32F240C/sn32_registry.h b/os/hal/ports/SN32/SN32F240C/sn32_registry.h index e94f790853..854f155650 100644 --- a/os/hal/ports/SN32/SN32F240C/sn32_registry.h +++ b/os/hal/ports/SN32/SN32F240C/sn32_registry.h @@ -136,6 +136,11 @@ #define SN32_LVD_HANDLER VectorA8 #define SN32_LVD_NUMBER LVD_IRQn +/* LVD threshold levels (2-bit LVDRSTLVL / LVDINTLVL). */ +#define SN32_LVD_LEVEL_2_20V 0x0 +#define SN32_LVD_LEVEL_2_70V 0x1 +#define SN32_LVD_LEVEL_3_60V 0x2 + /* * GPIO units. */ @@ -164,6 +169,7 @@ #define SN32_FLASH_SECTOR_SIZE 1024U #define SN32_FLASH_BASE 0x00000000UL #define FLASH_SIZE (SN32_FLASH_NUMBER_OF_BANKS * SN32_FLASH_SECTORS_PER_BANK * SN32_FLASH_SECTOR_SIZE) + /*===========================================================================*/ /* Common. */ /*===========================================================================*/ diff --git a/os/hal/ports/SN32/SN32F260/hal_lld.c b/os/hal/ports/SN32/SN32F260/hal_lld.c index cdbdbc33eb..d1e6e5bd09 100644 --- a/os/hal/ports/SN32/SN32F260/hal_lld.c +++ b/os/hal/ports/SN32/SN32F260/hal_lld.c @@ -60,12 +60,32 @@ void sn32_clock_init(void) { SystemCoreClockUpdate(); } +#if SN32_LVD_ENABLE == TRUE + +/** + * @brief LVD initialization. + * + * @notapi + */ +static void sn32_lvd_init(void) { + SN_SYS0->LVDCTRL_b.LVDRSTLVL = SN32_LVDRSTLVL; + SN_SYS0->LVDCTRL_b.LVDINTLVL = SN32_LVDINTLVL; + SN_SYS0->LVDCTRL_b.LVDRSTEN = (SN32_LVDRSTEN) ? 1U : 0U; + SN_SYS0->LVDCTRL_b.LVDEN = 1U; +} + +#endif /* SN32_LVD_ENABLE */ + /** * @brief Low level HAL driver initialization. * * @notapi */ void hal_lld_init(void) { +#if SN32_LVD_ENABLE == TRUE + sn32_lvd_init(); +#endif /* SN32_LVD_ENABLE */ + SystemInit(); sn32_clock_init(); } diff --git a/os/hal/ports/SN32/SN32F260/hal_lld.h b/os/hal/ports/SN32/SN32F260/hal_lld.h index 4f41bda2cb..24e9eaab67 100644 --- a/os/hal/ports/SN32/SN32F260/hal_lld.h +++ b/os/hal/ports/SN32/SN32F260/hal_lld.h @@ -94,6 +94,26 @@ #include "sn32_ct.h" #include "sn32_sys1.h" +/*===========================================================================*/ +/* LVD driver pre-compile time settings. */ +/*===========================================================================*/ + +#if !defined(SN32_LVD_ENABLE) || defined(__DOXYGEN__) +#define SN32_LVD_ENABLE FALSE +#endif + +#if !defined(SN32_LVDRSTLVL) || defined(__DOXYGEN__) +#define SN32_LVDRSTLVL SN32_LVD_RSTLVL_2_40V +#endif + +#if !defined(SN32_LVDINTLVL) || defined(__DOXYGEN__) +#define SN32_LVDINTLVL SN32_LVD_INTLVL_2_40V +#endif + +#if !defined(SN32_LVDRSTEN) || defined(__DOXYGEN__) +#define SN32_LVDRSTEN TRUE +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/os/hal/ports/SN32/SN32F260/sn32_registry.h b/os/hal/ports/SN32/SN32F260/sn32_registry.h index c80928be93..b05e289162 100644 --- a/os/hal/ports/SN32/SN32F260/sn32_registry.h +++ b/os/hal/ports/SN32/SN32F260/sn32_registry.h @@ -102,6 +102,12 @@ #define SN32_LVD_HANDLER VectorA8 #define SN32_LVD_NUMBER LVD_IRQn +/* LVD threshold levels. LVDRSTLVL (3-bit) and LVDINTLVL (2-bit) use different encodings. */ +#define SN32_LVD_RSTLVL_2_40V 0x2 +#define SN32_LVD_RSTLVL_3_30V 0x4 +#define SN32_LVD_INTLVL_2_40V 0x1 +#define SN32_LVD_INTLVL_3_30V 0x2 + /* * GPIO units. */ @@ -130,6 +136,7 @@ #define SN32_FLASH_SECTOR_SIZE 64U #define SN32_FLASH_BASE 0x00000000UL #define FLASH_SIZE (SN32_FLASH_NUMBER_OF_BANKS * SN32_FLASH_SECTORS_PER_BANK * SN32_FLASH_SECTOR_SIZE) + /** @} */ #endif /* SN32_REGISTRY_H */ diff --git a/os/hal/ports/SN32/SN32F290/hal_lld.c b/os/hal/ports/SN32/SN32F290/hal_lld.c index a74371be64..874b54d753 100644 --- a/os/hal/ports/SN32/SN32F290/hal_lld.c +++ b/os/hal/ports/SN32/SN32F290/hal_lld.c @@ -61,12 +61,32 @@ void sn32_clock_init(void) { FlashClockUpdate(); } +#if SN32_LVD_ENABLE == TRUE + +/** + * @brief LVD initialization. + * + * @notapi + */ +static void sn32_lvd_init(void) { + SN_SYS0->LVDCTRL_b.LVDRSTLVL = SN32_LVDRSTLVL; + SN_SYS0->LVDCTRL_b.LVDINTLVL = SN32_LVDINTLVL; + SN_SYS0->LVDCTRL_b.LVDRSTEN = (SN32_LVDRSTEN) ? 1U : 0U; + SN_SYS0->LVDCTRL_b.LVDEN = 1U; +} + +#endif /* SN32_LVD_ENABLE */ + /** * @brief Low level HAL driver initialization. * * @notapi */ void hal_lld_init(void) { +#if SN32_LVD_ENABLE == TRUE + sn32_lvd_init(); +#endif /* SN32_LVD_ENABLE */ + SystemInit(); sn32_clock_init(); } diff --git a/os/hal/ports/SN32/SN32F290/hal_lld.h b/os/hal/ports/SN32/SN32F290/hal_lld.h index 8eeb6e1baf..ac9167a88d 100644 --- a/os/hal/ports/SN32/SN32F290/hal_lld.h +++ b/os/hal/ports/SN32/SN32F290/hal_lld.h @@ -94,6 +94,26 @@ #include "sn32_ct.h" #include "sn32_sys1.h" +/*===========================================================================*/ +/* LVD driver pre-compile time settings. */ +/*===========================================================================*/ + +#if !defined(SN32_LVD_ENABLE) || defined(__DOXYGEN__) +#define SN32_LVD_ENABLE FALSE +#endif + +#if !defined(SN32_LVDRSTLVL) || defined(__DOXYGEN__) +#define SN32_LVDRSTLVL SN32_LVD_LEVEL_2_40V +#endif + +#if !defined(SN32_LVDINTLVL) || defined(__DOXYGEN__) +#define SN32_LVDINTLVL SN32_LVD_LEVEL_2_40V +#endif + +#if !defined(SN32_LVDRSTEN) || defined(__DOXYGEN__) +#define SN32_LVDRSTEN TRUE +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/os/hal/ports/SN32/SN32F290/sn32_registry.h b/os/hal/ports/SN32/SN32F290/sn32_registry.h index c68bc151bd..3ebd9d24d8 100644 --- a/os/hal/ports/SN32/SN32F290/sn32_registry.h +++ b/os/hal/ports/SN32/SN32F290/sn32_registry.h @@ -192,6 +192,11 @@ #define SN32_LVD_HANDLER VectorA8 #define SN32_LVD_NUMBER LVD_IRQn +/* LVD threshold levels (3-bit LVDRSTLVL / LVDINTLVL). */ +#define SN32_LVD_LEVEL_2_70V 0x3 +#define SN32_LVD_LEVEL_3_00V 0x4 +#define SN32_LVD_LEVEL_3_60V 0x5 + /* * GPIO units. */ @@ -220,6 +225,7 @@ #define SN32_FLASH_SECTOR_SIZE 1024U #define SN32_FLASH_BASE 0x00000000UL #define FLASH_SIZE (SN32_FLASH_NUMBER_OF_BANKS * SN32_FLASH_SECTORS_PER_BANK * SN32_FLASH_SECTOR_SIZE) + /*===========================================================================*/ /* Common. */ /*===========================================================================*/ From 30db011d0523b4bd55a1cce9aae950f4fc621a1f Mon Sep 17 00:00:00 2001 From: Reuben Salagaras Date: Mon, 12 Oct 2026 11:18:35 +1030 Subject: [PATCH 5/8] sn32: SPI: bound RX writes and keep TX fed past transfer end Guard the rxbuf store with idx < count and feed 0x00 into DATA once the nominal transfer completes: the peer can keep clocking a reply tail, and without a refill the engine underflows and shifts out stale bytes. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- os/hal/ports/SN32/LLD/SN32F2xx/SPI/hal_spi_v2_lld.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/SPI/hal_spi_v2_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/SPI/hal_spi_v2_lld.c index 38aa7d7c06..e8cbc51cdb 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/SPI/hal_spi_v2_lld.c +++ b/os/hal/ports/SN32/LLD/SN32F2xx/SPI/hal_spi_v2_lld.c @@ -87,10 +87,14 @@ static inline void spi_lld_irq_handler(SPIDriver *spip) { spip->spi->IC_b.RXFIFOTHIC = true; chSysUnlockFromISR(); - if (spip->rxbuf) spip->rxbuf[spip->idx] = data; + if (spip->rxbuf && spip->idx < spip->count) spip->rxbuf[spip->idx] = data; if (++(spip->idx) >= spip->count) { __spi_isr_complete_code(spip); + /* The peer may keep clocking (reply tail) past the nominal transfer + * length. Without a TX FIFO refill the engine underflows and shifts + * out stale/undefined bytes; feed zeroes so the stream stays clean. */ + spip->spi->DATA = 0x00; } else { spip->spi->DATA = spip->txbuf ? spip->txbuf[spip->idx] : 0x00; } From c3fc209feac7377e20d524c3600127840c81e51c Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Fri, 10 Jul 2026 12:31:03 +0300 Subject: [PATCH 6/8] sn32: fixup RTC peripheral LLD yes, it's just a timer --- .../ports/SN32/LLD/SN32F2xx/RTC/hal_rtc_lld.c | 112 +++++++++++------- .../ports/SN32/LLD/SN32F2xx/RTC/hal_rtc_lld.h | 17 ++- 2 files changed, 84 insertions(+), 45 deletions(-) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/RTC/hal_rtc_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/RTC/hal_rtc_lld.c index 7095346833..753a3cd3be 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/RTC/hal_rtc_lld.c +++ b/os/hal/ports/SN32/LLD/SN32F2xx/RTC/hal_rtc_lld.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2025 Dimitris Mantzouranis + Copyright (C) 2026 Dimitris Mantzouranis Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -13,14 +13,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ /** * @file RTC/hal_rtc_lld.c - * @brief SN32 RTC subsystem low level driver header. + * @brief SN32 RTC subsystem low level driver source. * * @addtogroup RTC * @{ @@ -47,6 +43,13 @@ RTCDriver RTCD1; /* Driver local variables and types. */ /*===========================================================================*/ +/** + * @brief Software-maintained RTC time. + * @note The SN32 RTC only provides a periodic second interrupt. Absolute + * time is maintained entirely in software. + */ +static volatile time_t rtc_time; + /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ @@ -75,20 +78,20 @@ static time_t rtc_encode(const RTCDateTime *timespec) { * * @notapi */ -static void rtc_decode(uint32_t tv_sec, +static void rtc_decode(time_t tv_sec, uint32_t tv_msec, RTCDateTime *timespec) { struct tm tim; struct tm *t; - const time_t time = (const time_t)tv_sec; /* Could be 64 bits.*/ /* If the conversion is successful the function returns a pointer to the object the result was written into.*/ #if defined(__GNUC__) || defined(__CC_ARM) - t = localtime_r(&time, &tim); + t = localtime_r(&tv_sec, &tim); osalDbgAssert(t != NULL, "conversion failed"); #else - t = localtime(&time); + t = localtime(&tv_sec); + osalDbgAssert(t != NULL, "conversion failed"); memcpy(&tim, t, sizeof(struct tm)); #endif @@ -112,8 +115,13 @@ OSAL_IRQ_HANDLER(SN32_RTC_HANDLER) { flags = RTCD1.rtc->RIS; RTCD1.rtc->IC = flags; - if (flags & mskRTC_SECIF) - RTCD1.callback(&RTCD1, RTC_EVENT_SECOND); + if (flags & mskRTC_SECIF) { + rtc_time++; + + if (RTCD1.callback != NULL) { + RTCD1.callback(&RTCD1, RTC_EVENT_SECOND); + } + } OSAL_IRQ_EPILOGUE(); } @@ -134,6 +142,7 @@ void rtc_lld_init(void) { /* RTC pointer initialization.*/ RTCD1.rtc = SN_RTC; + rtc_time = (time_t)0; /* Clock activation.*/ sys1EnableRTC(); @@ -141,6 +150,18 @@ void rtc_lld_init(void) { /* All interrupts initially disabled.*/ RTCD1.rtc->IE = 0; +#if SN32_RTC_CLK_SOURCE == SN32_RTC_CLK_SRC_XTAL + RTCD1.rtc->CLKS |= 1U; +#else + RTCD1.rtc->CLKS &= ~1U; +#endif + + /* + * Configure a 1 Hz period. + * The Sonix RTC is a periodic counter rather than a calendar RTC. + */ + rtc_lld_set_period(&RTCD1, SN32_RTC_PERIOD_DEFAULT); + /* Callback initially disabled.*/ RTCD1.callback = NULL; @@ -162,9 +183,13 @@ void rtc_lld_init(void) { * @notapi */ void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec) { - time_t tv_sec = rtc_encode(timespec); + syssts_t sts; - rtcSN32SetSec(rtcp, tv_sec); + (void)rtcp; + + sts = osalSysGetStatusAndLockX(); + rtc_time = rtc_encode(timespec); + osalSysRestoreStatusX(sts); } /** @@ -177,12 +202,19 @@ void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec) { * @notapi */ void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec) { - uint32_t tv_sec; + syssts_t sts; + time_t t; - rtcSN32GetSec(rtcp, &tv_sec); - rtc_decode(tv_sec, 0, timespec); + (void)rtcp; + + sts = osalSysGetStatusAndLockX(); + t = rtc_time; + osalSysRestoreStatusX(sts); + + rtc_decode(t, 0, timespec); } + /** * @brief Enables or disables RTC callbacks. * @details This function enables or disables callbacks, use a @p NULL pointer @@ -220,55 +252,55 @@ void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback) { } /** - * @brief Get seconds from RTC. + * @brief Set RTC second counter period. + * @details The period value controls the number of RTC clock cycles before + * a second event is generated. + * @note The SN32 RTC period register is limited to 20 bits. + * Values exceeding the maximum are silently clamped. * @note The function can be called from any context. * * @param[in] rtcp pointer to RTC driver structure - * @param[out] tv_sec pointer to seconds value + * @param[in] period second counter reload value * - * @api + * @notapi */ -void rtcSN32GetSec(RTCDriver *rtcp, uint32_t *tv_sec) { - uint32_t time_frac; +void rtc_lld_set_period(RTCDriver *rtcp, uint32_t period) { syssts_t sts; - osalDbgCheck((NULL != tv_sec) && (NULL != rtcp)); + if (period > SN32_RTC_PERIOD_MAX) { + period = SN32_RTC_PERIOD_MAX; + } - /* Entering a reentrant critical zone.*/ sts = osalSysGetStatusAndLockX(); - *tv_sec = rtcp->rtc->SECCNT; + rtcp->period = period; + rtcp->rtc->SECCNTV = period; - /* Leaving a reentrant critical zone.*/ osalSysRestoreStatusX(sts); } /** - * @brief Set seconds in RTC. - * @note The function can be called from any context. + * @brief Gets RTC second counter period. * * @param[in] rtcp pointer to RTC driver structure - * @param[in] tv_sec seconds value * - * @api + * @return the current RTC period value. + * + * @notapi */ -void rtcSN32SetSec(RTCDriver *rtcp, uint32_t tv_sec) { +uint32_t rtc_lld_get_period(RTCDriver *rtcp) { + uint32_t period; syssts_t sts; - osalDbgCheck(NULL != rtcp); - - /* Entering a reentrant critical zone.*/ sts = osalSysGetStatusAndLockX(); - uint32_t reg_value = rtcp->rtc->SECCNTV; // Read current value - reg_value &= ~0xFFFFF; // Clear the lower 20 bits - reg_value |= ((tv_sec >> 16) & 0xFFFFF); // Set the new 20-bit value - rtcp->rtc->SECCNTV = reg_value; // Write back the updated value + period = rtcp->period; - /* Leaving a reentrant critical zone.*/ osalSysRestoreStatusX(sts); + + return period; } #endif /* HAL_USE_RTC */ -/** @} */ +/** @} */ \ No newline at end of file diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/RTC/hal_rtc_lld.h b/os/hal/ports/SN32/LLD/SN32F2xx/RTC/hal_rtc_lld.h index 44aaf60df3..552e83e369 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/RTC/hal_rtc_lld.h +++ b/os/hal/ports/SN32/LLD/SN32F2xx/RTC/hal_rtc_lld.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2025 Dimitris Mantzouranis + Copyright (C) 2026 Dimitris Mantzouranis Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -30,6 +30,11 @@ /*===========================================================================*/ /* Driver constants. */ /*===========================================================================*/ +#define SN32_RTC_PERIOD_DEFAULT 0x8000U +#define SN32_RTC_PERIOD_MAX ((1U << 20) - 1U) +#define SN32_RTC_CLK_SRC_ILRC 0U +#define SN32_RTC_CLK_SRC_XTAL 1U +#define SN32_RTC_CLK_SOURCE SN32_RTC_CLK_SRC_ILRC /** * @name Implementation capabilities @@ -103,9 +108,11 @@ typedef struct hal_rtc_alarm { */ #define rtc_lld_driver_fields \ /* Pointer to the RTC registers block.*/ \ - RTC_TypeDef *rtc; \ + SN_RTC_Type *rtc; \ /* Callback pointer.*/ \ - rtccb_t callback; + rtccb_t callback; \ + /* Reload value for the 1Hz second generator. */ \ + uint32_t period; /*===========================================================================*/ /* Driver macros. */ @@ -125,8 +132,8 @@ extern "C" { void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec); void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec); void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback); - void rtcSN32GetSec(RTCDriver *rtcp, uint32_t *tv_sec); - void rtcSN32SetSec(RTCDriver *rtcp, uint32_t tv_sec); + void rtc_lld_set_period(RTCDriver *rtcp, uint32_t period); + uint32_t rtc_lld_get_period(RTCDriver *rtcp); #ifdef __cplusplus } #endif From c8eb9c12f09ae01871115624e0b1a356097a301a Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Fri, 10 Jul 2026 13:56:48 +0300 Subject: [PATCH 7/8] sn32f290: build RTC peripheral LLD --- os/hal/ports/SN32/SN32F290/platform.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/os/hal/ports/SN32/SN32F290/platform.mk b/os/hal/ports/SN32/SN32F290/platform.mk index 5c86ada8f1..1307a38c2a 100644 --- a/os/hal/ports/SN32/SN32F290/platform.mk +++ b/os/hal/ports/SN32/SN32F290/platform.mk @@ -29,6 +29,7 @@ include ${CHIBIOS_CONTRIB}/os/hal/ports/SN32/LLD/SN32F2xx/I2C/driver.mk include ${CHIBIOS_CONTRIB}/os/hal/ports/SN32/LLD/SN32F2xx/WDT/driver.mk include ${CHIBIOS_CONTRIB}/os/hal/ports/SN32/LLD/SN32F2xx/UART/driver.mk include ${CHIBIOS_CONTRIB}/os/hal/ports/SN32/LLD/SN32F2xx/ADC/driver.mk +include ${CHIBIOS_CONTRIB}/os/hal/ports/SN32/LLD/SN32F2xx/RTC/driver.mk # Shared variables ALLCSRC += $(PLATFORMSRC_CONTRIB) From 4b5588b511c0e98b4ae8c3b81357e4468ec9d1cb Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Fri, 10 Jul 2026 16:25:52 +0300 Subject: [PATCH 8/8] sn32 rtc: provide correct defaults --- os/hal/ports/SN32/LLD/SN32F2xx/RTC/hal_rtc_lld.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/RTC/hal_rtc_lld.h b/os/hal/ports/SN32/LLD/SN32F2xx/RTC/hal_rtc_lld.h index 552e83e369..be31420624 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/RTC/hal_rtc_lld.h +++ b/os/hal/ports/SN32/LLD/SN32F2xx/RTC/hal_rtc_lld.h @@ -30,12 +30,17 @@ /*===========================================================================*/ /* Driver constants. */ /*===========================================================================*/ -#define SN32_RTC_PERIOD_DEFAULT 0x8000U #define SN32_RTC_PERIOD_MAX ((1U << 20) - 1U) #define SN32_RTC_CLK_SRC_ILRC 0U #define SN32_RTC_CLK_SRC_XTAL 1U #define SN32_RTC_CLK_SOURCE SN32_RTC_CLK_SRC_ILRC +#if SN32_RTC_CLK_SOURCE == SN32_RTC_CLK_SRC_ILRC +# define SN32_RTC_PERIOD_DEFAULT (32000UL) +#else +# define SN32_RTC_PERIOD_DEFAULT (32768UL) +#endif + /** * @name Implementation capabilities */