[{"data":1,"prerenderedAt":1085},["ShallowReactive",2],{"navigation_docs_en":3,"-en-cloud-firmware-over-rdm-overview":317,"-en-cloud-firmware-over-rdm-overview-surround":1082},[4,19,74],{"title":5,"path":6,"stem":7,"children":8,"page":18},"Public","\u002Fen\u002Fpublic","en\u002F1.public",[9],{"title":10,"icon":11,"path":12,"stem":13,"children":14,"page":18},"Welcome","i-lucide-sparkles","\u002Fen\u002Fpublic\u002Fwelcome","en\u002F1.public\u002F1.welcome",[15],{"title":10,"path":16,"stem":17},"\u002Fen\u002Fpublic\u002Fwelcome\u002Foverview","en\u002F1.public\u002F1.welcome\u002F1.overview",false,{"title":20,"path":21,"stem":22,"children":23,"page":18},"Cloud","\u002Fen\u002Fcloud","en\u002F2.cloud",[24,33,48],{"title":10,"icon":25,"path":26,"stem":27,"children":28,"page":18},"i-lucide-lock","\u002Fen\u002Fcloud\u002Fwelcome","en\u002F2.cloud\u002F1.welcome",[29],{"title":30,"path":31,"stem":32},"Cloud Docs","\u002Fen\u002Fcloud\u002Fwelcome\u002Foverview","en\u002F2.cloud\u002F1.welcome\u002F1.overview",{"title":34,"icon":35,"path":36,"stem":37,"children":38,"page":18},"Firmware over RDM","i-lucide-radio-tower","\u002Fen\u002Fcloud\u002Ffirmware-over-rdm","en\u002F2.cloud\u002F2.firmware-over-rdm",[39,43],{"title":40,"path":41,"stem":42,"icon":35},"Firmware Update over RDM","\u002Fen\u002Fcloud\u002Ffirmware-over-rdm\u002Foverview","en\u002F2.cloud\u002F2.firmware-over-rdm\u002F1.overview",{"title":44,"path":45,"stem":46,"icon":47},"Implementation Guide","\u002Fen\u002Fcloud\u002Ffirmware-over-rdm\u002Fimplementation-guide","en\u002F2.cloud\u002F2.firmware-over-rdm\u002F2.implementation-guide","i-lucide-list-checks",{"title":49,"icon":50,"path":51,"stem":52,"children":53,"page":18},"KLSTR.rdm","i-lucide-cable","\u002Fen\u002Fcloud\u002Fklstr-rdm","en\u002F2.cloud\u002F3.klstr-rdm",[54,59,64,69],{"title":55,"path":56,"stem":57,"icon":58},"Introduction","\u002Fen\u002Fcloud\u002Fklstr-rdm\u002Fintroduction","en\u002F2.cloud\u002F3.klstr-rdm\u002F1.introduction","i-lucide-circuit-board",{"title":60,"path":61,"stem":62,"icon":63},"Use KLSTR.dev hardware","\u002Fen\u002Fcloud\u002Fklstr-rdm\u002Fuse-klstr-dev-hardware","en\u002F2.cloud\u002F3.klstr-rdm\u002F2.use-klstr-dev-hardware","i-lucide-wrench",{"title":65,"path":66,"stem":67,"icon":68},"Special firmware","\u002Fen\u002Fcloud\u002Fklstr-rdm\u002Fspecial-firmware","en\u002F2.cloud\u002F3.klstr-rdm\u002F3.special-firmware","i-lucide-download",{"title":70,"path":71,"stem":72,"icon":73},"RDM-Compliance Testing","\u002Fen\u002Fcloud\u002Fklstr-rdm\u002Frdm-compliance-testing","en\u002F2.cloud\u002F3.klstr-rdm\u002F4.rdm-compliance-testing","i-lucide-clipboard-check",{"title":75,"path":76,"stem":77,"children":78,"page":18},"Internal","\u002Fen\u002Finternal","en\u002F3.internal",[79,250,264,278],{"title":80,"icon":81,"path":82,"stem":83,"children":84,"page":18},"Review (ex-public)","i-lucide-inbox","\u002Fen\u002Finternal\u002Freview","en\u002F3.internal\u002F0.review",[85,102,120,138,187,205],{"title":86,"icon":87,"path":88,"stem":89,"children":90,"page":18},"Getting Started","i-lucide-rocket","\u002Fen\u002Finternal\u002Freview\u002Ftutorials","en\u002F3.internal\u002F0.review\u002F1.tutorials",[91,94,98],{"title":86,"path":92,"stem":93},"\u002Fen\u002Finternal\u002Freview\u002Ftutorials\u002Fgetting-started","en\u002F3.internal\u002F0.review\u002F1.tutorials\u002F1.getting-started",{"title":95,"path":96,"stem":97},"Setup KLSTR.one","\u002Fen\u002Finternal\u002Freview\u002Ftutorials\u002Fsetup-klstr-one","en\u002F3.internal\u002F0.review\u002F1.tutorials\u002F2.setup-klstr-one",{"title":99,"path":100,"stem":101},"Setup KLSTR.nano","\u002Fen\u002Finternal\u002Freview\u002Ftutorials\u002Fsetup-klstr-nano","en\u002F3.internal\u002F0.review\u002F1.tutorials\u002F3.setup-klstr-nano",{"title":103,"icon":104,"path":105,"stem":106,"children":107,"page":18},"KLSTR.one","i-lucide-cpu","\u002Fen\u002Finternal\u002Freview\u002Fklstr-one","en\u002F3.internal\u002F0.review\u002F2.klstr-one",[108,112,116],{"title":109,"path":110,"stem":111},"KLSTR.one Overview","\u002Fen\u002Finternal\u002Freview\u002Fklstr-one\u002Foverview","en\u002F3.internal\u002F0.review\u002F2.klstr-one\u002F1.overview",{"title":113,"path":114,"stem":115},"KLSTR.one Installation","\u002Fen\u002Finternal\u002Freview\u002Fklstr-one\u002Finstallation","en\u002F3.internal\u002F0.review\u002F2.klstr-one\u002F2.installation",{"title":117,"path":118,"stem":119},"KLSTR.one Specifications","\u002Fen\u002Finternal\u002Freview\u002Fklstr-one\u002Fspecifications","en\u002F3.internal\u002F0.review\u002F2.klstr-one\u002F3.specifications",{"title":121,"icon":122,"path":123,"stem":124,"children":125,"page":18},"KLSTR.nano","i-lucide-microchip","\u002Fen\u002Finternal\u002Freview\u002Fklstr-nano","en\u002F3.internal\u002F0.review\u002F4.klstr-nano",[126,130,134],{"title":127,"path":128,"stem":129},"KLSTR.nano Overview","\u002Fen\u002Finternal\u002Freview\u002Fklstr-nano\u002Foverview","en\u002F3.internal\u002F0.review\u002F4.klstr-nano\u002F1.overview",{"title":131,"path":132,"stem":133},"KLSTR.nano Installation","\u002Fen\u002Finternal\u002Freview\u002Fklstr-nano\u002Finstallation","en\u002F3.internal\u002F0.review\u002F4.klstr-nano\u002F2.installation",{"title":135,"path":136,"stem":137},"KLSTR.nano Specifications","\u002Fen\u002Finternal\u002Freview\u002Fklstr-nano\u002Fspecifications","en\u002F3.internal\u002F0.review\u002F4.klstr-nano\u002F3.specifications",{"title":139,"icon":140,"path":141,"stem":142,"children":143,"page":18},"Developer Guide","i-lucide-code","\u002Fen\u002Finternal\u002Freview\u002Fdeveloper","en\u002F3.internal\u002F0.review\u002F5.developer",[144,147,151,155,159,175],{"title":139,"path":145,"stem":146},"\u002Fen\u002Finternal\u002Freview\u002Fdeveloper\u002Foverview","en\u002F3.internal\u002F0.review\u002F5.developer\u002F0.overview",{"title":148,"path":149,"stem":150},"Choosing a Module","\u002Fen\u002Finternal\u002Freview\u002Fdeveloper\u002Fchoosing-a-module","en\u002F3.internal\u002F0.review\u002F5.developer\u002F1.choosing-a-module",{"title":152,"path":153,"stem":154},"Dual-Mode Operation","\u002Fen\u002Finternal\u002Freview\u002Fdeveloper\u002Fdual-mode","en\u002F3.internal\u002F0.review\u002F5.developer\u002F2.dual-mode",{"title":156,"path":157,"stem":158},"Fleet Management","\u002Fen\u002Finternal\u002Freview\u002Fdeveloper\u002Ffleet-management","en\u002F3.internal\u002F0.review\u002F5.developer\u002F3.fleet-management",{"title":103,"path":160,"stem":161,"children":162,"page":18},"\u002Fen\u002Finternal\u002Freview\u002Fdeveloper\u002Fklstr-one","en\u002F3.internal\u002F0.review\u002F5.developer\u002F4.klstr-one",[163,167,171],{"title":164,"path":165,"stem":166},"KLSTR.one: Hardware Integration","\u002Fen\u002Finternal\u002Freview\u002Fdeveloper\u002Fklstr-one\u002Fhardware-integration","en\u002F3.internal\u002F0.review\u002F5.developer\u002F4.klstr-one\u002F1.hardware-integration",{"title":168,"path":169,"stem":170},"KLSTR.one: Provisioning","\u002Fen\u002Finternal\u002Freview\u002Fdeveloper\u002Fklstr-one\u002Fprovisioning","en\u002F3.internal\u002F0.review\u002F5.developer\u002F4.klstr-one\u002F2.provisioning",{"title":172,"path":173,"stem":174},"KLSTR.one: RDM Protocol","\u002Fen\u002Finternal\u002Freview\u002Fdeveloper\u002Fklstr-one\u002Frdm-protocol","en\u002F3.internal\u002F0.review\u002F5.developer\u002F4.klstr-one\u002F3.rdm-protocol",{"title":121,"path":176,"stem":177,"children":178,"page":18},"\u002Fen\u002Finternal\u002Freview\u002Fdeveloper\u002Fklstr-nano","en\u002F3.internal\u002F0.review\u002F5.developer\u002F5.klstr-nano",[179,183],{"title":180,"path":181,"stem":182},"KLSTR.nano: Hardware Integration","\u002Fen\u002Finternal\u002Freview\u002Fdeveloper\u002Fklstr-nano\u002Fhardware-integration","en\u002F3.internal\u002F0.review\u002F5.developer\u002F5.klstr-nano\u002F1.hardware-integration",{"title":184,"path":185,"stem":186},"KLSTR.nano: Provisioning","\u002Fen\u002Finternal\u002Freview\u002Fdeveloper\u002Fklstr-nano\u002Fprovisioning","en\u002F3.internal\u002F0.review\u002F5.developer\u002F5.klstr-nano\u002F2.provisioning",{"title":188,"icon":189,"path":190,"stem":191,"children":192,"page":18},"FAQ","i-lucide-circle-help","\u002Fen\u002Finternal\u002Freview\u002Ffaq","en\u002F3.internal\u002F0.review\u002F6.faq",[193,197,201],{"title":194,"path":195,"stem":196},"General Questions","\u002Fen\u002Finternal\u002Freview\u002Ffaq\u002Fgeneral","en\u002F3.internal\u002F0.review\u002F6.faq\u002F1.general",{"title":198,"path":199,"stem":200},"Connectivity","\u002Fen\u002Finternal\u002Freview\u002Ffaq\u002Fconnectivity","en\u002F3.internal\u002F0.review\u002F6.faq\u002F2.connectivity",{"title":202,"path":203,"stem":204},"Troubleshooting","\u002Fen\u002Finternal\u002Freview\u002Ffaq\u002Ftroubleshooting","en\u002F3.internal\u002F0.review\u002F6.faq\u002F3.troubleshooting",{"title":206,"icon":207,"path":208,"stem":209,"children":210,"page":18},"Articles","i-lucide-newspaper","\u002Fen\u002Finternal\u002Freview\u002Farticles","en\u002F3.internal\u002F0.review\u002F7.articles",[211,215,219,223,227,231,235,239,243,247],{"title":212,"path":213,"stem":214},"Overview","\u002Fen\u002Finternal\u002Freview\u002Farticles\u002Foverview","en\u002F3.internal\u002F0.review\u002F7.articles\u002F0.overview",{"title":216,"path":217,"stem":218},"KLSTR Integration Guide for Fixture Manufacturers","\u002Fen\u002Finternal\u002Freview\u002Farticles\u002Fintegration-guide","en\u002F3.internal\u002F0.review\u002F7.articles\u002F1.integration-guide",{"title":220,"path":221,"stem":222},"RDM Protocol Reference for KLSTR.one","\u002Fen\u002Finternal\u002Freview\u002Farticles\u002Frdm-protocol","en\u002F3.internal\u002F0.review\u002F7.articles\u002F2.rdm-protocol",{"title":224,"path":225,"stem":226},"KLSTR.one Provisioning Guide","\u002Fen\u002Finternal\u002Freview\u002Farticles\u002Fklstr-one-provisioning","en\u002F3.internal\u002F0.review\u002F7.articles\u002F3.klstr-one-provisioning",{"title":228,"path":229,"stem":230},"KLSTR.one Integration Guide","\u002Fen\u002Finternal\u002Freview\u002Farticles\u002Fklstr-one-plug-in-integration","en\u002F3.internal\u002F0.review\u002F7.articles\u002F4.klstr-one-plug-in-integration",{"title":232,"path":233,"stem":234},"KLSTR.nano Provisioning Guide","\u002Fen\u002Finternal\u002Freview\u002Farticles\u002Fklstr-nano-provisioning","en\u002F3.internal\u002F0.review\u002F7.articles\u002F5.klstr-nano-provisioning",{"title":236,"path":237,"stem":238},"KLSTR.nano Plug-In Integration","\u002Fen\u002Finternal\u002Freview\u002Farticles\u002Fklstr-nano-plug-in-integration","en\u002F3.internal\u002F0.review\u002F7.articles\u002F6.klstr-nano-plug-in-integration",{"title":240,"path":241,"stem":242},"Hello","\u002Fen\u002Finternal\u002Freview\u002Farticles\u002Fhello","en\u002F3.internal\u002F0.review\u002F7.articles\u002F7.hello",{"title":244,"path":245,"stem":246},"TestNew file","\u002Fen\u002Finternal\u002Freview\u002Farticles\u002Fiwantmd","en\u002F3.internal\u002F0.review\u002F7.articles\u002Fiwantmd",{"title":244,"path":248,"stem":249},"\u002Fen\u002Finternal\u002Freview\u002Farticles\u002Ftestnew","en\u002F3.internal\u002F0.review\u002F7.articles\u002Ftestnew",{"title":251,"icon":252,"path":253,"stem":254,"children":255,"page":18},"Admin","i-lucide-shield-check","\u002Fen\u002Finternal\u002Fadmin","en\u002F3.internal\u002F3.admin",[256,260],{"title":257,"path":258,"stem":259},"Admin Dashboard","\u002Fen\u002Finternal\u002Fadmin\u002Fdashboard","en\u002F3.internal\u002F3.admin\u002F1.dashboard",{"title":261,"path":262,"stem":263},"Internal Release Notes","\u002Fen\u002Finternal\u002Fadmin\u002Frelease-notes","en\u002F3.internal\u002F3.admin\u002F2.release-notes",{"title":265,"path":266,"stem":267,"children":268,"page":18},"Developer","\u002Fen\u002Finternal\u002Fdeveloper","en\u002F3.internal\u002F5.developer",[269],{"title":270,"path":271,"stem":272,"children":273,"page":18},"Klstr One","\u002Fen\u002Finternal\u002Fdeveloper\u002Fklstr-one","en\u002F3.internal\u002F5.developer\u002F4.klstr-one",[274],{"title":275,"path":276,"stem":277},"Internal (Partner Only)","\u002Fen\u002Finternal\u002Fdeveloper\u002Fklstr-one\u002Finternal","en\u002F3.internal\u002F5.developer\u002F4.klstr-one\u002F4.internal",{"title":279,"icon":280,"path":281,"stem":282,"children":283,"page":18},"Authoring Guide","i-lucide-pen-line","\u002Fen\u002Finternal\u002Fauthoring","en\u002F3.internal\u002F9.authoring",[284,288,293,297,302,307,312],{"title":285,"path":286,"stem":287,"icon":11},"Overview & MDC Basics","\u002Fen\u002Finternal\u002Fauthoring\u002Foverview","en\u002F3.internal\u002F9.authoring\u002F1.overview",{"title":289,"path":290,"stem":291,"icon":292},"Text & Prose","\u002Fen\u002Finternal\u002Fauthoring\u002Ftext-and-prose","en\u002F3.internal\u002F9.authoring\u002F2.text-and-prose","i-lucide-type",{"title":294,"path":295,"stem":296,"icon":140},"Code Blocks","\u002Fen\u002Finternal\u002Fauthoring\u002Fcode","en\u002F3.internal\u002F9.authoring\u002F3.code",{"title":298,"path":299,"stem":300,"icon":301},"Callouts & Cards","\u002Fen\u002Finternal\u002Fauthoring\u002Fcallouts-and-cards","en\u002F3.internal\u002F9.authoring\u002F4.callouts-and-cards","i-lucide-message-square-warning",{"title":303,"path":304,"stem":305,"icon":306},"Layout & Interactivity","\u002Fen\u002Finternal\u002Fauthoring\u002Flayout-and-interactivity","en\u002F3.internal\u002F9.authoring\u002F5.layout-and-interactivity","i-lucide-layout-panel-left",{"title":308,"path":309,"stem":310,"icon":311},"Visuals — Images, Icons & Diagrams","\u002Fen\u002Finternal\u002Fauthoring\u002Fvisuals","en\u002F3.internal\u002F9.authoring\u002F6.visuals","i-lucide-image",{"title":313,"path":314,"stem":315,"icon":316},"Design System & Configuration","\u002Fen\u002Finternal\u002Fauthoring\u002Fdesign-system","en\u002F3.internal\u002F9.authoring\u002F7.design-system","i-lucide-palette",{"id":318,"title":40,"body":319,"description":1075,"extension":1076,"links":1077,"meta":1078,"navigation":1079,"path":41,"seo":1080,"stem":42,"__hash__":1081},"docs_en\u002Fen\u002F2.cloud\u002F2.firmware-over-rdm\u002F1.overview.md",{"type":320,"value":321,"toc":1061},"minimark",[322,335,341,349,354,371,375,389,393,404,625,637,641,644,725,732,736,810,829,832,836,842,860,864,871,899,906,910,916,933,941,948,952,963,967,1034,1045,1049],[323,324,325,326,330,331,334],"p",{},"Every KLSTR.nano device can be flashed over SWD\u002FSWIM. But in the field the device is\noften tucked inside a fixture with only ",[327,328,329],"strong",{},"DMX\u002FRDM"," as a communication option -\nthat's why KLSTR.nano also supports ",[327,332,333],{},"Firmware Updates over RDM",".",[323,336,337,338,340],{},"This page explains the protocol, MCU-agnostically. The reference implementation is\nthe ",[327,339,121],{}," (STM32F103); a second runs on the ESP32-S3 (KLSTR.fixture).",[342,343,344,345,334],"note",{},"Building this on a new MCU? Read this page for the mental model, then follow the\nstep-by-step ",[346,347,44],"a",{"href":348},"\u002Fen\u002Ffirmware-over-rdm\u002Fimplementation-guide",[350,351,353],"h2",{"id":352},"the-idea-in-one-picture","The idea in one picture",[323,355,356,357,360,361,365,366,370],{},"The controller streams the firmware as a sequence of small ",[327,358,359],{},"chunks",", each carried\nin one RDM ",[362,363,364],"code",{},"SET",". The device writes each chunk to its ",[367,368,369],"em",{},"inactive"," flash slot,\naccumulates a checksum, and - once the image lands and verifies - flips a boot flag\nand reboots into it.",[372,373],"mermaid",{"code":374},"graph LR\n  A[Controller\u003Cbr\u002F>klstr.ctrl] -->|Art-Net \u002F ELC-Net\u003Cbr\u002F>UDP| B[DMX gateway node]\n  B -->|XLR · DMX-512 + RDM| C[Device 1]\n  C -->|cut-through\u003Cbr\u002F>forwarding| D[Device 2]\n  D -->|...| E[Device N]\n  style A fill:#6366f1,color:#fff\n  style C fill:#0ea5e9,color:#fff\n  style D fill:#0ea5e9,color:#fff\n  style E fill:#0ea5e9,color:#fff\n",[323,376,377,378,381,382,385,386,388],{},"Two properties make this practical on a daisy chain: ",[327,379,380],{},"cut-through forwarding","\n(every device re-emits RDM bytes port-to-port, so a broadcast chunk reaches all 32\ndevices deep) and ",[327,383,384],{},"manufacturer broadcast"," (one ",[362,387,364],{}," to a manufacturer's\nbroadcast UID flashes every device of that manufacturer at once, leaving others\nuntouched).",[350,390,392],{"id":391},"the-protocol-a-manufacturer-specific-pid-set","The protocol: a manufacturer-specific PID set",[323,394,395,396,399,400,403],{},"The transfer is driven by six ",[327,397,398],{},"manufacturer-specific RDM parameters"," (PIDs) in the\n",[362,401,402],{},"0xc8xx"," range - not standard E1.20\u002FE1.37-2 PIDs, since RDM has none for firmware.\nBoth ends must speak the same PID numbers.",[405,406,407,429],"table",{},[408,409,410],"thead",{},[411,412,413,417,420,423,426],"tr",{},[414,415,416],"th",{},"PID",[414,418,419],{},"Name",[414,421,422],{},"Class",[414,424,425],{},"Payload",[414,427,428],{},"Role",[430,431,432,468,497,533,564,599],"tbody",{},[411,433,434,440,445,449,458],{},[435,436,437],"td",{},[362,438,439],{},"0xc8d7",[435,441,442],{},[362,443,444],{},"file_setup",[435,446,447],{},[362,448,364],{},[435,450,451,454,455],{},[362,452,453],{},"{u32 flags}"," → ",[362,456,457],{},"{u32 status}",[435,459,460,461,464,465,334],{},"Arm the receiver before streaming. ",[362,462,463],{},"flags"," bit 0 = ",[367,466,467],{},"listen to broadcast chunks",[411,469,470,475,480,484,491],{},[435,471,472],{},[362,473,474],{},"0xc8cf",[435,476,477],{},[362,478,479],{},"file_chunk",[435,481,482],{},[362,483,364],{},[435,485,486,454,489],{},[362,487,488],{},"{u32 chunk_nb}{≤128 B data}",[362,490,457],{},[435,492,493,494],{},"One block of the image. ",[327,495,496],{},"chunk 0 is a self-describing header.",[411,498,499,504,509,514,522],{},[435,500,501],{},[362,502,503],{},"0xc8cd",[435,505,506],{},[362,507,508],{},"file_report",[435,510,511],{},[362,512,513],{},"GET",[435,515,516,454,519],{},[362,517,518],{},"{}",[362,520,521],{},"{u32 status, u32 crc}",[435,523,524,525,528,529,532],{},"End-of-transfer check. ",[362,526,527],{},"status == 0"," ⇒ device believes the image is valid; ",[362,530,531],{},"crc"," = accumulated CRC32.",[411,534,535,540,545,549,557],{},[435,536,537],{},[362,538,539],{},"0xc8ce",[435,541,542],{},[362,543,544],{},"partition_info",[435,546,547],{},[362,548,513],{},[435,550,551,454,554],{},[362,552,553],{},"{u32 part_nb}",[362,555,556],{},"{u32 addr, u32 crc_fw, u32 crc_ctrl}",[435,558,559,560,563],{},"A\u002FB slot introspection. ",[362,561,562],{},"addr == 0"," ⇒ slot invalid.",[411,565,566,571,576,580,588],{},[435,567,568],{},[362,569,570],{},"0xc8c8",[435,572,573],{},[362,574,575],{},"control",[435,577,578],{},[362,579,364],{},[435,581,582,585,586],{},[362,583,584],{},"{u16 index, u32 value}"," (stackable) → ",[362,587,457],{},[435,589,590,591,594,595,598],{},"Device control. ",[362,592,593],{},"index 0x0019"," = ",[362,596,597],{},"reset_device"," → reboot into the new image.",[411,600,601,606,611,615,622],{},[435,602,603],{},[362,604,605],{},"0xc8f9",[435,607,608],{},[362,609,610],{},"firmware_state",[435,612,613],{},[362,614,513],{},[435,616,617,454,619],{},[362,618,518],{},[362,620,621],{},"{string}",[435,623,624],{},"Human-readable state (silicon vendor \u002F flash size \u002F partition \u002F linker).",[626,627,628,629,632,633,636],"tip",{},"Manufacturer PIDs are ",[327,630,631],{},"namespaced by manufacturer ID",", so reusing these exact\nnumbers under a ",[367,634,635],{},"different"," manufacturer is spec-clean with zero collision. This is\nwhat lets one controller driver flash multiple device families.",[350,638,640],{"id":639},"how-a-transfer-runs","How a transfer runs",[372,642],{"code":643},"sequenceDiagram\n  participant C as Controller\n  participant D as Device (responder)\n  C->>D: file_setup {flags: listen=1}   (unicast)\n  D-->>C: status = 0\n  C->>D: file_chunk {nb: 0, header}\n  Note over D: parse header, pick inactive slot, reset stream\n  C->>D: file_chunk {nb: 1, data}\n  Note over D: write to flash, fold CRC32\n  C->>D: file_chunk {nb: 2..N, data}\n  Note over D: (55 ms between chunks, no ACK on broadcast)\n  C->>D: file_report {}   (unicast)\n  D-->>C: status = 0, crc = 0x....\n  C->>D: control {reset_device}\n  Note over D: trampoline validates image, boots new slot\n",[645,646,647,663,686,703],"ol",{},[648,649,650,655,656,658,659,662],"li",{},[327,651,652,653],{},"Arm - ",[362,654,444],{}," (unicast). The controller names each target once, with\n",[362,657,463],{}," bit 0 set so it will accept the ",[367,660,661],{},"broadcast"," chunks that follow.",[648,664,665,670,671,674,675,678,679,682,683,334],{},[327,666,667,668],{},"Stream - ",[362,669,479],{},". The image is sliced into fixed ",[327,672,673],{},"128-byte"," chunks,\nnumbered from zero. ",[327,676,677],{},"Chunk 0 is a header, not data"," - it carries where in flash\nthe image belongs, where its control block lives, and (if encrypted) the\ndecryption seed; the device uses it to pick the inactive partition and reset its\nstream state. Real data starts at chunk 1, and the flash offset is computed as\n",[362,680,681],{},"start + 128 × chunk_nb"," - ",[327,684,685],{},"sequence-addressed, not offset-addressed",[648,687,688,693,694,696,697,699,700,702],{},[327,689,690,691],{},"Confirm - ",[362,692,508],{}," (must be unicast - it's a ",[362,695,513],{},"). Returns\n",[362,698,527],{}," if the on-device CRC32 matched, plus the ",[362,701,531],{}," itself so the\ncontroller can cross-check against its own. A mismatch means a chunk was dropped.",[648,704,705,711,712,715,716,719,720,724],{},[327,706,707,708],{},"Reboot - ",[362,709,710],{},"control{reset_device}",". The device replies first, ",[367,713,714],{},"then"," reboots,\nso the ACK is never lost. On the way up, the ",[327,717,718],{},"trampoline"," independently\nre-validates the image before jumping into it (see ",[346,721,723],{"href":722},"#fail-safe-ab-boot","Fail-safe A\u002FB\nboot",").",[342,726,728,731],{"icon":727},"i-lucide-hash",[327,729,730],{},"Why 128 bytes?"," The largest power of two that comfortably fits an RDM parameter\npayload (232-byte cap). Smaller works but is slower; untested below.",[350,733,735],{"id":734},"delivery-broadcast-fast-path-vs-unicast","Delivery: broadcast fast-path vs. unicast",[737,738,739,789],"tabs",{},[740,741,743,758],"tabs-item",{"label":742},"Vendorcast (default)",[323,744,745,746,749,750,753,754,757],{},"Chunks broadcast to the ",[327,747,748],{},"manufacturer's broadcast UID"," (",[362,751,752],{},"mmmm:FFFFFFFF","), fixed\ninter-chunk delay, ",[327,755,756],{},"no per-chunk ACK"," - flashes the whole rig in one pass.",[759,760,761,770,780],"ul",{},[648,762,763,766,767,769],{},[327,764,765],{},"Spec-legal",": ANSI E1.20 §5.3 permits ",[362,768,364],{}," to a manufacturer-specific\nbroadcast; responders must not reply.",[648,771,772,775,776,779],{},[327,773,774],{},"Fire-and-forget",": pacing is time-based. The nano uses ",[327,777,778],{},"55 ms"," between\nchunks - enough for the slowest device to finish its blocking flash write.",[648,781,782,785,786,788],{},[327,783,784],{},"The catch",": no ACK, no retransmit. A dropped chunk fails the final CRC; catch\nit per-device via unicast ",[362,787,508],{},", then fall back to unicast for stragglers.",[740,790,792,799],{"label":791},"Unicast (per device)",[323,793,794,795,798],{},"Each chunk addressed to one UID, ",[362,796,797],{},"status"," checked. Reliable but one device at a\ntime, and requires the controller to relax its RDM reply timeout (the device\nanswers late while erasing flash).",[323,800,801,802,805,806,809],{},"On the nano this path is kept alive but no longer the primary flow - reserved for\n",[327,803,804],{},"single-fixture targeting"," and ",[327,807,808],{},"retrying"," a device that failed its CRC after a\nbroadcast pass.",[811,812,813,822,823,825,826,828],"warning",{},[327,814,815,816,818,819,821],{},"Only ",[362,817,364],{}," can be broadcast; ",[362,820,513],{}," cannot"," - a broadcast may not be answered. So\n",[362,824,444],{}," and the chunk stream may be broadcast, but ",[362,827,508],{}," must always be\nunicast.",[323,830,831],{},"Each device family advertises its own RDM manufacturer ID, giving it a naturally\nisolated broadcast group - one family's stream can never touch another's devices,\nand each family keeps its own broadcast fast-path.",[350,833,835],{"id":834},"the-load-bearing-constraint-flash-writes-vs-the-rdm-deadline","The load-bearing constraint: flash writes vs. the RDM deadline",[323,837,838,839],{},"An RDM responder must answer within a few milliseconds, but a flash erase takes tens\nof milliseconds. ",[327,840,841],{},"You cannot both write flash and answer RDM on time.",[737,843,844,856],{},[740,845,847,848,851,852,855],{"label":846},"Blocking (reference model)","On the STM32F103 the CPU can't execute code while flash erases\u002Fwrites, so the nano\nsimply ",[327,849,850],{},"blocks",". It doesn't try to answer on time - the ",[367,853,854],{},"controller","\naccommodates it instead: the 55 ms vendorcast gap outlasts the write, and the\nunicast timeout is relaxed for the late ACK. Simplest correct model - build this\nfirst.",[740,857,859],{"label":858},"Decoupled (capable MCUs)","An MCU that can execute while flash erases (e.g. ESP32-S3) can do better: the RDM\ncallback only copies the chunk into a RAM ring buffer, folds the CRC32, and ACKs\nimmediately - always inside the deadline. A worker task drains the buffer into\nflash in the background. Lets you pace faster than the blocking model, at the cost\nof a ring buffer sized to absorb erase stalls. An optimization, not a requirement.",[350,861,863],{"id":862},"fail-safe-ab-boot","Fail-safe A\u002FB boot",[323,865,866,867,870],{},"The transfer is ",[327,868,869],{},"brick-safe by construction",":",[645,872,873,883,889],{},[648,874,875,882],{},[327,876,877,878,881],{},"Write the ",[367,879,880],{},"other"," slot."," The running firmware writes into the inactive\npartition only, so a failure mid-transfer leaves the running image intact.",[648,884,885,888],{},[327,886,887],{},"Bump the boot priority"," of the new slot to one above the running slot,\nemulating an in-place overwrite without the risk.",[648,890,891,894,895,898],{},[327,892,893],{},"Trampoline validates, then boots."," On reset, a small trampoline picks the\nhighest-priority ",[367,896,897],{},"valid"," partition - independently re-checking the image and\ncontrol-block CRCs before jumping. A half-written slot fails validation and is\nskipped; the device falls back to the previous good image.",[626,900,901,902,905],{},"The streamed CRC and the trampoline's CRC are ",[327,903,904],{},"two independent checks",": the\nstreamed one catches transport errors cheaply during transfer; the trampoline's is\nthe final gate that guarantees the device never boots a bad image.",[350,907,909],{"id":908},"integrity-security","Integrity & security",[323,911,912,913,915],{},"RDM is unauthenticated and unencrypted - any controller on the cable can ",[362,914,364],{},", and\na firmware push is the highest-privilege operation there is. The reference\nimplementation mitigates this two ways:",[759,917,918,927],{},[648,919,920,923,924,926],{},[327,921,922],{},"Integrity (CRC32)"," - accumulated on the fly, returned in ",[362,925,508],{},", and\nre-checked independently by the trampoline before boot. Catches corruption, not\ntampering.",[648,928,929,932],{},[327,930,931],{},"Confidentiality (encrypted images)"," - release images ship obfuscated\u002Fencrypted\nand are decrypted on-device in the chunk handler; the seed lives in the chunk-0\nheader.",[934,935,936,937,940],"caution",{},"The nano only accepts an ",[327,938,939],{},"encrypted"," image when its flash read-protection (SWD\nlock) is engaged - otherwise the just-written plaintext could be read back over the\ndebug port. If your platform ships encrypted images, gate acceptance on the\nequivalent read-out protection being locked.",[342,942,943,944,947],{},"CRC32 is integrity, not authenticity - it stops corruption, not a malicious image.\nIf authenticity matters, the long-term fix is transport-agnostic ",[327,945,946],{},"secure boot with\nsigned images",", so a forged image fails at boot regardless of how it arrived.",[350,949,951],{"id":950},"file-format","File format",[323,953,954,955,958,959,962],{},"A release file (",[362,956,957],{},".nano"," on the reference platform) is a ",[327,960,961],{},"ZIP of the two slot\nimages"," - one linked for partition A, one for B - each encrypted. The controller\npicks the image matching the slot the device will write, reads the embedded control\nblock (size, CRCs, SHA-1) for its own pre-flight check, and streams it.",[350,964,966],{"id":965},"throughput-is-it-practical","Throughput: is it practical?",[405,968,969,984],{},[408,970,971],{},[411,972,973,975,978,981],{},[414,974],{},[414,976,977],{},"Per 128 B chunk",[414,979,980],{},"Chunks",[414,982,983],{},"Wall-clock",[430,985,986,1002,1018],{},[411,987,988,991,993,996],{},[435,989,990],{},"~130 KB image, vendorcast @ 55 ms",[435,992,778],{},[435,994,995],{},"~1,000",[435,997,998,1001],{},[327,999,1000],{},"~1 minute"," (whole rig at once)",[411,1003,1004,1007,1010,1013],{},[435,1005,1006],{},"~1.5 MB image, vendorcast",[435,1008,1009],{},"~10–55 ms",[435,1011,1012],{},"~12,000",[435,1014,1015,1001],{},[327,1016,1017],{},"~2–11 minutes",[411,1019,1020,1023,1026,1028],{},[435,1021,1022],{},"~1.5 MB image, unicast (retry)",[435,1024,1025],{},"~20–55 ms",[435,1027,1012],{},[435,1029,1030,1031],{},"~4–11 minutes ",[327,1032,1033],{},"per device",[323,1035,1036,1037,1040,1041,1044],{},"Expect ",[327,1038,1039],{},"minutes, not seconds"," - RDM flashing is a deliberate ",[367,1042,1043],{},"recovery \u002F\nno-network fallback",", not a replacement for the faster network path. Vendorcast\ndoesn't scale with fixture count (the whole rig flashes in one pass); unicast does.\nPresent it to the operator as the fallback it is.",[350,1046,1048],{"id":1047},"next-steps","Next steps",[1050,1051,1052,1056],"card-group",{},[1053,1054,1055],"card",{"icon":47,"title":44,"to":348},"A single step-by-step build plan for the responder and controller on an arbitrary\nMCU.",[1053,1057,1060],{"icon":1058,"title":1059},"i-lucide-book-open","RDM basics","New to RDM? Brush up on discovery, UIDs and the request\u002Fresponse model before\ndiving in.",{"title":1062,"searchDepth":1063,"depth":1063,"links":1064},"",2,[1065,1066,1067,1068,1069,1070,1071,1072,1073,1074],{"id":352,"depth":1063,"text":353},{"id":391,"depth":1063,"text":392},{"id":639,"depth":1063,"text":640},{"id":734,"depth":1063,"text":735},{"id":834,"depth":1063,"text":835},{"id":862,"depth":1063,"text":863},{"id":908,"depth":1063,"text":909},{"id":950,"depth":1063,"text":951},{"id":965,"depth":1063,"text":966},{"id":1047,"depth":1063,"text":1048},"How KLSTR flashes a device's firmware over the DMX cable using the RDM bus - the protocol, the delivery model, and the safety mechanics, abstracted for any MCU.","md",null,{},{"icon":35},{"title":40,"description":1075},"XbSr40ZmTJlSwbRJyxiHpkVcF74i8mdP7g4kF5tfdl4",[1077,1083],{"title":44,"path":45,"stem":46,"description":1084,"icon":47,"children":-1},"A step-by-step, MCU-agnostic guide to implementing firmware update over RDM - the responder on your device and the streaming logic on the controller.",1787149428897]