From 5d3cdd0a74d8ff88181388ec4a9e868d6b0c51cc Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Thu, 4 Jan 2024 13:00:03 -0500 Subject: [PATCH] Add the EFR32 watchdog to RPC firmware (#33) * Create a `.gitignore` file * Add a watchdog Gecko SDK extension * Trust Gecko SDK extensions when building * Allow patching the generated project file * Add watchdog to RCP firmwares * Ensure `pip` is available * `yq` is available in Debian, use it directly * Use correct parameter for `slc signature trust` command * Ensure extension path is absolute * Link extensions within the SDK to get slc-cli to actually work * Revert namespacing for `#define`s hard-coded in the SDK * [WIP] Simplify extension to bare minimum * Register watchdog initialization later * Remove debugging code * Reset the watchdog timer at 25% * Pass through `slcp_yaml_changes` * Feed watchdog timer within the app, not in a timer interrupt handler * Drop watchdog period to 2 seconds * Stop running the watchdog when in debugger --- .github/workflows/build.yaml | 7 ++ .github/workflows/silabs-firmware-build.yaml | 22 +++++ .gitignore | 1 + Dockerfile | 1 + .../inc/nc_efr32_wdog.h | 26 ++++++ .../nc_efr32_watchdog.slcc | 38 ++++++++ .../nc_efr32_watchdog.slce | 8 ++ .../src/nc_efr32_wdog.c | 92 +++++++++++++++++++ 8 files changed, 195 insertions(+) create mode 100644 .gitignore create mode 100644 gecko_sdk_extensions/nc_efr32_watchdog_extension/inc/nc_efr32_wdog.h create mode 100644 gecko_sdk_extensions/nc_efr32_watchdog_extension/nc_efr32_watchdog.slcc create mode 100644 gecko_sdk_extensions/nc_efr32_watchdog_extension/nc_efr32_watchdog.slce create mode 100644 gecko_sdk_extensions/nc_efr32_watchdog_extension/src/nc_efr32_wdog.c diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 358cb150..283e3bd1 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -98,10 +98,16 @@ jobs: device: MGM210PA32JIA components: simple_led:board_activity,cpc_security_secondary_none,zigbee_mfglib patchpath: "RCPMultiPAN/Yellow" + slcp_yaml_changes: > + . += {"sdk_extension": [{"id": "nc_efr32_watchdog", version: "1.0.0"}]} + | .component += [{"from": "nc_efr32_watchdog", "id": "nc_efr32_watchdog"}] - target: skyconnect device: EFR32MG21A020F512IM32 components: cpc_security_secondary_none,zigbee_mfglib patchpath: "RCPMultiPAN/SkyConnect" + slcp_yaml_changes: > + . += {"sdk_extension": [{"id": "nc_efr32_watchdog", version: "1.0.0"}]} + | .component += [{"from": "nc_efr32_watchdog", "id": "nc_efr32_watchdog"}] uses: ./.github/workflows/silabs-firmware-build.yaml with: image_name: ${{ needs.build-container.outputs.image_name }} @@ -111,6 +117,7 @@ jobs: device: ${{ matrix.device }} components: ${{ matrix.components }} patchpath: ${{ matrix.patchpath }} + slcp_yaml_changes: ${{ matrix.slcp_yaml_changes }} sdk_version: ${{ needs.build-container.outputs.sdk_version }} metadata_fw_type: "rcp-uart-802154" baudrate: 460800 diff --git a/.github/workflows/silabs-firmware-build.yaml b/.github/workflows/silabs-firmware-build.yaml index 8d640808..81b6899f 100644 --- a/.github/workflows/silabs-firmware-build.yaml +++ b/.github/workflows/silabs-firmware-build.yaml @@ -47,6 +47,9 @@ on: required: false default: "null" type: string + slcp_yaml_changes: + required: false + type: string jobs: firmware-build: @@ -63,6 +66,19 @@ jobs: - name: Adjust permission shell: bash run: chown builder . + + - name: Link SDK extensions + shell: bash + run: | + # XXX: slc-cli does not actually work when the extensions aren't in the SDK! + ln -s $PWD/gecko_sdk_extensions /gecko_sdk/extension + + - name: Trust SDK extensions + run: | + for ext in /gecko_sdk/extension/*/; do + slc signature trust --extension-path="$ext" + done + - name: Generate Firmware Project run: | slc generate \ @@ -110,6 +126,12 @@ jobs: sed -i "s/^C_DEFS\s*=.*$/C_DEFS = '-DOPENTHREAD_BUILD_DATETIME=\"$meta_datetime\"' ${{ inputs.extra_c_defs }}/" \ "${{ inputs.project_name }}.Makefile" + - name: Patch SLCP project file + if: "${{ inputs.slcp_yaml_changes != '' }}" + run: | + cd ${{ inputs.firmware_name }} + yq --in-place --yaml-output '${{ inputs.slcp_yaml_changes }}' "${{ inputs.project_name }}.slcp" + - name: Build Firmware run: | cd ${{ inputs.firmware_name }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..496ee2ca --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index b053f6c2..8929e12d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,6 +10,7 @@ RUN \ git \ git-lfs \ jq \ + yq \ libgl1 \ make \ default-jre-headless \ diff --git a/gecko_sdk_extensions/nc_efr32_watchdog_extension/inc/nc_efr32_wdog.h b/gecko_sdk_extensions/nc_efr32_watchdog_extension/inc/nc_efr32_wdog.h new file mode 100644 index 00000000..d1af5b8b --- /dev/null +++ b/gecko_sdk_extensions/nc_efr32_watchdog_extension/inc/nc_efr32_wdog.h @@ -0,0 +1,26 @@ +/***************************************************************************//** + * @file nc_efr32_wdog.h + * @brief Legacy HAL Watchdog + ******************************************************************************* + * # License + * Copyright 2022 Silicon Laboratories, Inc, www.silabs.com + ******************************************************************************* + * + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + ******************************************************************************/ + +#include +#include "em_cmu.h" +#include "em_wdog.h" +#include "em_rmu.h" +#include "sli_cpc_timer.h" +#include "sl_component_catalog.h" + +void nc_enable_watchdog(void); +void nc_periodic_timer(sli_cpc_timer_handle_t *handle, void *data); \ No newline at end of file diff --git a/gecko_sdk_extensions/nc_efr32_watchdog_extension/nc_efr32_watchdog.slcc b/gecko_sdk_extensions/nc_efr32_watchdog_extension/nc_efr32_watchdog.slcc new file mode 100644 index 00000000..688ae1ba --- /dev/null +++ b/gecko_sdk_extensions/nc_efr32_watchdog_extension/nc_efr32_watchdog.slcc @@ -0,0 +1,38 @@ +root_path: ./ +id: nc_efr32_watchdog +label: EFR32 Watchdog +package: ext-comp +category: External Components +quality: production +description: > + EFR32 Watchdog. +requires: + - name: component_catalog + - name: emlib_wdog + - name: emlib_wdog +provides: + - name: nc_efr32_watchdog + +source: + - path: src/nc_efr32_wdog.c + +include: + - path: inc + file_list: + - path: nc_efr32_wdog.h + +template_contribution: + - name: component_catalog + value: nc_efr32_watchdog + - name: event_handler + value: + event: service_init + include: "nc_efr32_wdog.h" + handler: nc_enable_watchdog + priority: 9999 # load very very late + - name: event_handler + value: + event: service_process_action + include: "nc_efr32_wdog.h" + handler: nc_poke_watchdog + priority: 9999 # run last diff --git a/gecko_sdk_extensions/nc_efr32_watchdog_extension/nc_efr32_watchdog.slce b/gecko_sdk_extensions/nc_efr32_watchdog_extension/nc_efr32_watchdog.slce new file mode 100644 index 00000000..ba087a3f --- /dev/null +++ b/gecko_sdk_extensions/nc_efr32_watchdog_extension/nc_efr32_watchdog.slce @@ -0,0 +1,8 @@ +id: "nc_efr32_watchdog" +label: "EFR32 Watchdog" +version: "1.0.0" +sdk: + id: "gecko_sdk" + version: 4.3.2 +component_path: + - path: "./" \ No newline at end of file diff --git a/gecko_sdk_extensions/nc_efr32_watchdog_extension/src/nc_efr32_wdog.c b/gecko_sdk_extensions/nc_efr32_watchdog_extension/src/nc_efr32_wdog.c new file mode 100644 index 00000000..21979c00 --- /dev/null +++ b/gecko_sdk_extensions/nc_efr32_watchdog_extension/src/nc_efr32_wdog.c @@ -0,0 +1,92 @@ +/***************************************************************************//** + * @file nc_efr32_wdog.c + * @brief Legacy HAL Watchdog + ******************************************************************************* + * # License + * Copyright 2022 Silicon Laboratories, Inc, www.silabs.com + ******************************************************************************* + * + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + ******************************************************************************/ + +#include "em_wdog.h" +#include "nc_efr32_wdog.h" + +static bool feed_watchdog_on_warn_interrupt; + + +#if (_SILICON_LABS_32B_SERIES >= 1) +void WDOG0_IRQHandler(void) +{ + uint32_t interrupts; + + interrupts = WDOGn_IntGet(WDOG0); + WDOGn_IntClear(WDOG0, interrupts); + + if (feed_watchdog_on_warn_interrupt) { + WDOGn_Feed(WDOG0); + feed_watchdog_on_warn_interrupt = false; + } +} +#endif + + +void nc_enable_watchdog(void) +{ + // Enable LE interface +#if !defined(_SILICON_LABS_32B_SERIES_2) + CMU_ClockEnable(cmuClock_HFLE, true); + CMU_OscillatorEnable(cmuOsc_LFRCO, true, true); +#endif + +#if defined(_SILICON_LABS_32B_SERIES_2) && !defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1) + CMU_ClockEnable(cmuClock_WDOG0, true); +#endif + + // Make sure FULL reset is used on WDOG timeout +#if defined(_RMU_CTRL_WDOGRMODE_MASK) + RMU_ResetControl(rmuResetWdog, rmuResetModeFull); +#endif + + WDOG_Init_TypeDef init = WDOG_INIT_DEFAULT; + init.enable = false; + init.debugRun = false; + init.perSel = wdogPeriod_64k; // 2 seconds + init.warnSel = wdogWarnTime75pct; + +#if defined(_WDOG_CTRL_CLKSEL_MASK) + init.clkSel = wdogClkSelLFRCO; +#else + // Series 2 devices select watchdog oscillator with the CMU. + CMU_ClockSelectSet(cmuClock_WDOG0, cmuSelect_LFRCO); +#endif + + WDOGn_Unlock(WDOG0); + WDOGn_Init(WDOG0, &init); + + // Enable warning interrupt + NVIC_ClearPendingIRQ(WDOG0_IRQn); + WDOGn_IntClear(WDOG0, WDOG_IF_WARN); + NVIC_EnableIRQ(WDOG0_IRQn); + WDOGn_IntEnable(WDOG0, WDOG_IEN_WARN); + + WDOGn_Enable(WDOG0, true); + WDOGn_Feed(WDOG0); + + feed_watchdog_on_warn_interrupt = false; +} + + +void nc_poke_watchdog() +{ + CORE_DECLARE_IRQ_STATE; + CORE_ENTER_ATOMIC(); + feed_watchdog_on_warn_interrupt = true; + CORE_EXIT_ATOMIC(); +}