Skip to main content

embedded-medical-device

Firmware development for STM32, nRF52840, and RP2040 medical devices with BLE/USB communication, IEEE 11073 protocols, and secure data handling. When building point-of-care devices (pulse oximeters, BP monitors, glucose meters), embedded gateways, or medical IoT endpoints with TinyGo.

ソース情報

リポジトリ
plurigrid/asi
ソースの最終更新活動
2026年6月10日 11:55
検出された SKILL.md の言語
英語
スター
64
フォーク
12

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

ファイルエクスプローラー
2 ファイル

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
embedded-medical-device
description
Firmware development for STM32, nRF52840, and RP2040 medical devices with BLE/USB communication, IEEE 11073 protocols, and secure data handling. When building point-of-care devices (pulse oximeters, BP monitors, glucose meters), embedded gateways, or medical IoT endpoints with TinyGo.
license
Proprietary. See LICENSE.txt for medical device regulations and compliance.
compatibility
Requires TinyGo 0.40.0+, ARM Cortex-M target support, Nordic SoftDevice (nRF52840), STM32CubeMX (STM32 targets), or Pico SDK (RP2040). Crypto via hardware CryptoAuth secure element (ATECC608A/B) recommended for FDA/IEC 62443 compliance.
metadata
{"version":"1.0.0","device-targets":"nRF52840,STM32F4,STM32H7,RP2040","protocol-support":"IEEE 11073,FHIR,BLE,USB-CDC,UART","crypto-support":"SHA256,AES-128-GCM,ECDSA (hardware-backed)","binary-size-estimated":"45-120 KB (depends on protocol stack)"}
allowed-tools
Bash(tinygo:build*) Bash(openocd:*) Bash(nrfjprog:*) Read
# Embedded Medical Device Firmware Development ## Quick Start ### nRF5340-DK Dual-Core Medical Device (Recommended) **Setup** (5 minutes): 1. Get nRF5340-DK ($99 from Nordic): includes J-Link debugger, USB UART, sensor connectors 2. Install TinyGo: `brew install tinygo` (supports nRF5340 in 0.40.0+) 3. Connect MAX30102 pulse ox sensor to I2C (GPIO 26=SDA, GPIO 27=SCL) 4. Connect serial monitor: `screen /dev/tty.usbmodem14101 115200` **Application processor firmware** (runs on main Cortex-M33): ```go package main import ( "github.com/tinygo-org/bluetooth" "machine" "time" ) func main() { // Initialize sensors on application processor i2c := machine.I2C0 i2c.Configure(machine.I2CConfig{ Frequency: 100_000, SCL: machine.GPIO27, SDA: machine.GPIO26, }) // Read sensor loop (never blocked by BLE on separate processor) ticker := time.NewTicker(10 * time.Millisecond) // 100 Hz sampling for range ticker.C { spo2 := readMAX30102(i2c) // 5µs I2C transaction hr := computeHeartRate(spo2) // Send to BLE (network processor handles async) sendToGATT(spo2, hr) println("SpO2:", spo2, "HR:", hr) } } func readMAX30102(i2c machine.I2C) uint8 { // Fast I2C read (doesn't block sensor loop thanks to dual-core) data := make([]byte, 2) i2c.ReadRegister(0x57, 0x07, data) // RED_LED_CONFIG return data[0] } func computeHeartRate(spo2 uint8) uint8 { return 72 // simplified; real firmware uses FFT on PPG waveform } func sendToGATT(spo2, hr uint8) { // Non-blocking send (network processor handles BLE) // See BLE section below } ``` **Network processor firmware** (runs on Cortex-M4, handles BLE interrupts): The Nordic SoftDevice runs on the network processor automatically. Your application processor calls BLE functions via IPC (Inter-Processor Communication), which is transparent to you—just use the `bluetooth` package as normal. **Key benefit**: While BLE is advertising or transmitting, your sensor loop on the application processor runs **uninterrupted**. This guarantees real-time sensor data at 200+ Hz (required for pulse oximetry accuracy). ### Minimal BLE Pulse Oximeter (nRF52840) ```go package main import ( "github.com/tinygo-org/bluetooth" "machine" "time" ) func main() { // Initialize BLE peripheral role (medical device advertises itself) adapter := bluetooth.DefaultAdapter adapter.Enable() // GATT service for pulse oximetry (IEEE 11073-20601) adv := adapter.StartAdvertisement(&bluetooth.AdvertisementOptions{ LocalName: "PulseOx-001", }) // Simulate SpO2 reading (normally from ADC connected to LED) ticker := time.NewTicker(1 * time.Second) for range ticker.C { spo2 := readSensorValue() // 95-100% typically // Notify connected client with spo2 value _ = spo2 } } func readSensorValue() uint8 { // Connect ADC to photodiode, compute SpO2 via FFT (see references/) return 97 } ``` ### Key Architecture ``` Medical Device Firmware (TinyGo) ├── BLE/USB Transport (tinygo-org/bluetooth or machine/usb/cdc) ├── Sensor Integration (ADC, I2C, SPI) ├── IEEE 11073 Protocol Stack (lightweight Rust/Go bridge or pure Go) ├── Hardware Crypto (via CryptoAuth secure element over I2C) ├── Data Validation (agentskills embedded skill validation) └── Secure Boot & Attestation (if available on target) ``` ## Part 1: Target Microcontroller Selection ### nRF5340-DK (Recommended for Next-Generation Medical Devices) - **Strengths**: Dual Cortex-M33 (Application + Network processors), 512 KB RAM, 1 MB flash, native BLE 5.3 + Thread, Matter support - **Always-on core**: Network processor handles BLE interrupt processing independently (critical for real-time sensor data) - **Use case**: Clinical-grade medical devices, continuous monitoring, low-power wireless gateways - **TinyGo support**: Excellent (new support in TinyGo 0.40.0+) - **Dev kit**: nRF5340-DK ($99, includes J-Link debugger, UART, multiple sensor connectors) - **Binary footprint**: ~80-100 KB with BLE 5.3 stack (smaller than nRF52840 due to Cortex-M33 efficiency) - **Power**: ~2.1 mA active BLE (vs 4 mA nRF52840), ideal for battery-powered medical devices - **Key advantage**: Dual-core means BLE interrupt processing never blocks sensor sampling **Medical advantage**: nRF5340's always-on network processor ensures **real-time sensor data** isn't missed during Bluetooth communication. Critical for pulse oximetry (200 Hz sampling) and ECG (500+ Hz). **Architecture**: ``` nRF5340-DK ├── Application Processor (Cortex-M33) │ ├── Main firmware (sensor logic, FHIR validation) │ ├── I2C: MAX30102 (pulse oximetry) or other sensors │ └── UART/SPI: Data logging to flash │ └── Network Processor (Cortex-M4) ├── Nordic SoftDevice (BLE 5.3, Thread) ├── Always-on real-time processing └── Can wake application processor on events ``` **Comparison to nRF52840**: | Feature | nRF5340-DK | nRF52840 | |---------|-----------|---------| | Dual-core | ✓ (M33+M4) | ✗ (single M4) | | Real-time sensors | ✓ Never blocked | Shared with BLE | | RAM | 512 KB | 256 KB | | BLE version | 5.3 (latest) | 5.2 | | Dev kit cost | $99 | $35-50 | | Power (active) | 2.1 mA | 4.0 mA | | Matter support | ✓ | ✗ | | TinyGo 0.40+ | ✓ | ✓ | **Recommendation**: Use **nRF5340-DK** for FDA submissions (dual-core ensures real-time guarantees), **nRF52840** for simple prototypes (cheaper, sufficient for low-frequency sensors). ### nRF52840 (Best for Medical BLE - Budget Option) - **Strengths**: Native BLE (no WiFi complexity), 256 KB RAM, 1 MB flash, Nordic SoftDevice support - **Use case**: Personal health devices (pulse oximeter, BP monitor, glucose meter) - **TinyGo support**: Excellent (Adafruit boards pre-loaded with SoftDevice) - **Boards**: Adafruit nRF52840 Feather, Arduino Nano 33 BLE, Pimoroni Tiny2040 - **Binary footprint**: ~60-80 KB with BLE stack - **Limitation**: Single-core means sensor sampling and BLE communication compete for CPU **Example**: nRF52840 Feather + Adafruit pulse oximeter breakout + ATECC608A secure element ``` nRF52840 Feather ├── SPI: ATECC608A (hardware crypto, tamper-resistant) ├── I2C: MAX30102 (pulse oximetry sensor) ├── GPIO: LED indicators, button └── BLE: Advertises SpO2 readings to mobile app ``` ### STM32F4/H7 (Clinical Bench Equipment) - **Strengths**: Large flash (512KB-2MB), fast Cortex-M4/M7, extensive peripherals - **Use case**: Benchtop analyzers, ECG machines, ventilator controllers - **TinyGo support**: Partial (some ST NUCLEO boards supported) - **Challenge**: No native BLE; requires external BLE module (e.g., nRF24L01 or separate nRF52) - **Binary footprint**: ~80-120 KB (depends on protocol stack) **Architecture**: STM32 + nRF24L01 bridge (separate MCU for wireless) ``` STM32F407 (clinical device logic) ├── UART1: Communication with nRF24L01 BLE bridge ├── ADC: Multi-channel sensor inputs (ECG leads, temperature, etc.) ├── Flash: 512 KB (firmware + patient data records) └── SPI: SD card for data logging nRF24L01 (separate TinyGo firmware) ├── BLE radio (if variant available) ├── Or: 2.4 GHz ISM band (medical telemetry) └── UART back to STM32 ``` ### RP2040 (Emerging, Dual-Core Promise) - **Strengths**: Cheap ($1-2), dual ARM Cortex-M0+, good peripherals - **Use case**: Distributed sensor networks, gateway devices - **TinyGo support**: Excellent (Raspberry Pi Pico native support, multicore in recent TinyGo) - **Challenge**: Limited RAM (264 KB), no native Bluetooth (but can add external module) - **Binary footprint**: ~40-60 KB minimal **Emerging pattern**: RP2040 in star topology ``` Gateway RP2040 (multicore, runs edge WASI) ├── Core 0: Collects data from peripheral BLE devices (via USB host or separate radio) ├── Core 1: Processes FHIR serialization, validates with agentskills └── USB-CDC: Streams structured data to medical gateway/EHR Peripheral nRF52840 devices (pulse ox, BP monitor, glucose meter) └── BLE: Advertises to gateway RP2040 (acting as central) ``` --- ## Part 2: BLE and IEEE 11073 Protocol Stack ### BLE + GATT Structure for Medical Devices IEEE 11073-20601 (Personal Health Device) defines GATT profiles: ``` Medical Device GATT Service ├── Device Information │ ├── Manufacturer: "Boxxy Medical" │ ├── Model: "PulseOx v1" │ └── Serial: (from secure element) ├── Pulse Oximetry Service (0x180D1 custom) │ ├── SpO2 Characteristic (read, notify) │ ├── HR Characteristic (read, notify) │ └── Status Characteristic (read) ├── Battery Service │ ├── Battery Level (read, notify) │ └── Battery Status (read) └── Generic Access ├── Device Name: "PulseOx-ABC123" └── Appearance: 0x0C41 (Pulse Oximeter) ``` ### TinyGo Bluetooth Example ```go package main import ( "github.com/tinygo-org/bluetooth" "encoding/binary" ) func main() { adapter := bluetooth.DefaultAdapter adapter.Enable() // Define GATT characteristics spo2Char := bluetooth.NewCharacteristic("SpO2", bluetooth.CharacteristicNotifyPermission, bluetooth.CharacteristicReadPermission) adapter.AddService(&bluetooth.Service{ UUID: bluetooth.New16BitUUID(0x180D), // Pulse Oximetry Characteristics: []*bluetooth.Characteristic{spo2Char}, }) // Advertise adv := adapter.StartAdvertisement(&bluetooth.AdvertisementOptions{ LocalName: "PulseOx-001", ServiceUUIDs: []bluetooth.UUID{ bluetooth.New16BitUUID(0x180D), }, }) // Notify client of SpO2 change (97%) spo2 := uint8(97) data := []byte{spo2} spo2Char.Notify(data) } ``` ### Bridging to FHIR (on gateway) For edge processing, the gateway (RP2040 or STM32+bridge) converts IEEE 11073 to FHIR: ```json { "resourceType": "Observation", "code": { "coding": [{ "system": "http://loinc.org", "code": "2708-6", "display": "Oxygen saturation in arterial blood" }] }, "valueQuantity": { "value": 97, "unit": "%", "system": "http://unitsofmeasure.org", "code": "%" }, "device": { "reference": "Device/PulseOx-ABC123", "identifier": { "system": "urn:oid:1.2.840.113556.4.5", "value": "ABC123" // from secure element serial } } } ``` --- ## Part 3: Secure Element Integration (ATECC608A/B) **Why hardware crypto**: Software crypto in TinyGo has failing test suites due to reflect limitations. FDA and IEC 62443 require certified, audited cryptography. ### Wiring (I2C) ``` nRF52840 Feather ATECC608A (Adafruit Breakout) ├── GPIO 26 (SDA) -------> SDA ├── GPIO 27 (SCL) -------> SCL ├── GND ----------------> GND └── 3.3V ----------------> VCC ``` ### TinyGo Code ```go package main import ( "github.com/waj334/tinygo-cryptoauthlib" "machine" ) func main() { // Initialize I2C i2c := machine.I2C0 i2c.Configure(machine.I2CConfig{ Frequency: 100_000, SCL: machine.GPIO27, SDA: machine.GPIO26, }) // Connect to secure element device, err := cryptoauthlib.NewATECC608A(i2c, cryptoauthlib.DefaultAddress) if err != nil { panic(err) } // SHA256 via hardware (faster, certified) data := []byte("patient_id_12345") hash, err := device.SHA256(data) if err != nil { panic(err) } // hash is now [32]byte // Sign challenge for device attestation challenge := [32]byte{} // received from medical gateway signature, err := device.Sign(challenge[:]) if err != nil { panic(err) } // signature is ECDSA signature [64]byte } ``` ### FDA Compliance Path 1. **ATECC608A** is pre-certified for cryptographic operations (FIPS 140-2 candidate) 2. **TinyGo binary** compiled with `-no-debug` and hashing logic is auditable and small 3. **Device attestation** via ECDSA signature chain: Secure Element → Gateway → EHR 4. **Tamper-resistant storage**: ATECC608A stores root key securely, never transmitted This satisfies **21 CFR Part 11** (electronic records, electronic signatures) and **IEC 62443-4-2** (secure development practices). --- ## Part 4: Skill Validation on Embedded Devices The `embedded.go` skill validation subsystem provides capability checking without reflection or standard library bloat. ### Compact Skill Registry (for firmware capabilities) ```go package main import ( "github.com/bmorphism/boxxy/internal/skill" ) func main() { // Initialize registry registry := skill.NewRegistry() // Register firmware capabilities as skills pulseox := &skill.EmbeddedSkill{ Name: "pulse-oximetry", Description: "Read SpO2 and HR via MAX30102 sensor over I2C", Trit: 1, // Generator (+1) role } registry.Register(pulseox) tempsensor := &skill.EmbeddedSkill{ Name: "temperature-monitor", Description: "Monitor body temperature via DS18B20 1-wire sensor", Trit: 0, // Coordinator role } registry.Register(tempsensor) // Check if capabilities are balanced (GF(3) conservation) if registry.IsBalanced() { println("Device capabilities balanced") } // Serialize to EEPROM for capability advertisement over BLE compact := registry.SerializeCompact() // Send `compact` string to mobile app or medical gateway } ``` ### Over-the-Wire Capability Announcement (BLE) ```go // Advertise firmware capabilities to connected gateway via characteristic capabilitiesChar := bluetooth.NewCharacteristic( "FirmwareCapabilities", bluetooth.CharacteristicReadPermission, )
GitHubで見る
この SKILL.md は非常に大きいため、SkillsMP では最初のセクションだけを表示しています。 GitHubで見る