{"id":16358221,"url":"https://github.com/newam/stm32wl-lightswitch-demo","last_synced_at":"2025-09-24T05:32:02.152Z","repository":{"id":37526510,"uuid":"398623696","full_name":"newAM/stm32wl-lightswitch-demo","owner":"newAM","description":"Demo project for the stm32wlxx-hal","archived":false,"fork":false,"pushed_at":"2024-03-31T20:29:58.000Z","size":125,"stargazers_count":7,"open_issues_count":2,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-01-11T04:42:43.143Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/newAM.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2021-08-21T17:53:52.000Z","updated_at":"2023-09-02T14:01:47.000Z","dependencies_parsed_at":"2024-03-31T21:28:14.750Z","dependency_job_id":"a294b2b7-6c4e-41ff-b746-2c81e18ffa28","html_url":"https://github.com/newAM/stm32wl-lightswitch-demo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/newAM%2Fstm32wl-lightswitch-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/newAM%2Fstm32wl-lightswitch-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/newAM%2Fstm32wl-lightswitch-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/newAM%2Fstm32wl-lightswitch-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/newAM","download_url":"https://codeload.github.com/newAM/stm32wl-lightswitch-demo/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234044995,"owners_count":18770892,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T02:05:07.072Z","updated_at":"2025-09-24T05:31:56.791Z","avatar_url":"https://github.com/newAM.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# STM32WL Lightswitch Demo\n\nThis is a demo project for the [stm32wl-hal].\n\nThis runs on two [NUCLEO-WL55JC2] boards.\n\nWhat does it do?  Well, it is a real fancy lightswitch.\nPress B3 on the board flashed with the \"client\" firmware, it will toggle its own\nLED, then the board with the \"server\" firmware will toggle its LED after\nauthenticating the request.\n\n## Requirements\n\n1. [rustup](https://rustup.rs/)\n2. Two [NUCLEO-WL55JC2]\n3. [probe-rs]\n\n## Usage\n\nRun the `server` package and `client` package on two separate targets at the\nsame time using `probe-rs`.\n\n```console\n$ probe-rs list\nThe following debug probes were found:\n[0]: STLink V3 (VID: 0483, PID: 374e, Serial: 001600345553500A20393256, StLink)\n[1]: STLink V3 (VID: 0483, PID: 374e, Serial: 001D00145553500A20393256, StLink)\n$ DEFMT_LOG=trace cargo run -p server -- --probe 0483:374e:001600345553500A20393256\n$ DEFMT_LOG=trace cargo run -p client -- --probe 0483:374e:001D00145553500A20393256\n```\n\nIf you want to be fancy, I use tmux to launch these at the same time in one\nterminal session.\n\n```bash\ntmux new-session \"DEFMT_LOG=trace cargo run -p server -- --probe 0483:374e:001600345553500A20393256\" \\; split-window \"DEFMT_LOG=trace cargo run -p client -- --probe 0483:374e:001D00145553500A20393256\" \\; setw remain-on-exit on \\;\n```\n\n## Features demonstrated\n\n* ADC sampling\n* AES GCM encryption + decryption\n* GFSK TX + RX\n* GPIOs\n* Random number generation\n* RTC\n* Timers\n\n## Performance\n\nEnd-to-end latency is about 31.3 ms.\n\n## Security\n\nThe usual warnings apply, assume the code is full of security bugs.\n\nThe code is for demonstration purposes only and does not represent best\nsecurity practices.\nImplementing a custom protocol is typically a bad idea when security is a\nrequirement.\n\nThe code **is not** secure as-is:\n\n1. The server time is not accurate, leading to nonce reuse.\n2. The time-synchronization nonce is reset when the server is reset,\n   leading to nonce reuse.\n3. The private key is comitted to a public repository.\n\nA better nonce would be a non-volatile value stored in flash, but I do not want\nto wear out your flash for a demonstration.\n\n```rs\n/// Non-volatile u64 stored in the last page of flash\n///\n/// * Service lifetime is 30 years (flash data detention)\n/// * Page endurance is 10k cycles\n/// * Page size is 2048 bytes\n///\n/// service_days = 30 * 365 = 10950\n/// u64_writes = 10k * (2048 / 8) = 2_560_000\n/// writes_per_day = u64_writes / service_days = 233.79\n///\n/// You can use more pages or an external EEPROM if you need more writes/day.\npub struct NonVolatileU64 {\n    _priv: (),\n}\n\nimpl NonVolatileU64 {\n    const U64_PER_PAGE: usize = Page::SIZE / size_of::\u003cu64\u003e();\n    const U64_PER_PAGE_ISIZE: isize = Self::U64_PER_PAGE as isize;\n    const PAGE: Page = unsafe { Page::from_index_unchecked(127) };\n    const FIRST: *const u64 = Self::PAGE.addr() as *const u64;\n    const LAST: *const u64 = (Self::PAGE.addr() + Page::SIZE - size_of::\u003cu64\u003e()) as *const u64;\n\n    #[inline]\n    pub fn fetch_increment(flash: \u0026mut pac::FLASH) -\u003e Result\u003cu64, flash::Error\u003e {\n        if let Some((val, offset)) = Self::fetch() {\n            let mut flash: Flash = Flash::unlock(flash);\n\n            let next: *mut u64 = if offset == 0 {\n                unsafe { flash.page_erase(Self::PAGE)? };\n                Self::FIRST as *mut u64\n            } else {\n                unsafe { Self::LAST.offset(-offset + 1) as *mut u64 }\n            };\n\n            // in theory this should be a checked add, panicing at overflow\n            // but the flash page will die before u64 wraps\n            let next_val: u64 = val.wrapping_add(1);\n\n            unsafe { flash.standard_program(\u0026next_val, next)? };\n\n            Ok(next_val)\n        } else {\n            let mut flash: Flash = Flash::unlock(flash);\n            unsafe {\n                flash.page_erase(Self::PAGE)?;\n                flash.standard_program(\u00260, Self::FIRST as *mut u64)?\n            };\n            Ok(0)\n        }\n    }\n\n    fn fetch() -\u003e Option\u003c(u64, isize)\u003e {\n        for offset in 0..Self::U64_PER_PAGE_ISIZE {\n            let ptr: *const u64 = unsafe { Self::LAST.offset(-offset) };\n            let value: u64 = unsafe { ptr.read_volatile() };\n            if value != u64::MAX {\n                return Some((value, offset));\n            }\n        }\n        None\n    }\n}\n```\n\n## Limitations\n\nNotes on what needs to be improved to extend this for a real-world application:\n\n1. Security, see above.\n2. Error handling! Currently everything panics upon unexpected errors.\n   Retry loops should be used to handle the unexpected.\n3. Adding node addresses to serve multiple clients.\n4. Entry/exit into a low power state when the client is idle.\n5. Saving panic messages to non-volatile memory,\n   and a mechanism to retrieve the panic messages.\n\n[stm32wl-hal]: https://github.com/newAM/stm32wl-hal\n[NUCLEO-WL55JC2]: https://www.st.com/en/evaluation-tools/nucleo-wl55jc.html#sample-buy\n[probe-rs]: https://github.com/probe-rs/probe-rs\n[rustup]: https://rustup.rs/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnewam%2Fstm32wl-lightswitch-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnewam%2Fstm32wl-lightswitch-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnewam%2Fstm32wl-lightswitch-demo/lists"}