File size: 43,208 Bytes
d2f6397
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4f58d84
d2f6397
 
4f58d84
d2f6397
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
293982b
d2f6397
 
4f58d84
d2f6397
4f58d84
 
d2f6397
4f58d84
 
d2f6397
4f58d84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
<!doctype html><html lang="en"><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>DeviceTree Config Audit - 23 dtc-style rules for .dts, .overlay, TOML, .properties</title>
<meta name="description" content="Paste a .dts, .dtsi, .overlay, TOML or .properties file and get the line numbers back. 23 rules for the spellings the compiler accepts and the build ignores - status = &quot;ok&quot; is not in the Devicetree Specification v0.4 list, and Zephyr marks a node present only for the exact value &quot;okay&quot;.">
<link rel="canonical" href="https://getreadystack.com/tools/devicetree-config-language-pack">
<style>
:root{color-scheme:light dark}
*{box-sizing:border-box}
body{margin:0;font:16px/1.6 system-ui,-apple-system,"Segoe UI",sans-serif;
 background:#fbfbfa;color:#16161d}
@media(prefers-color-scheme:dark){body{background:#14141a;color:#e8e8ea}}
.wrap{max-width:900px;margin:0 auto;padding:26px 20px 64px}
h1{font-size:1.65rem;line-height:1.22;margin:.1em 0 .35em;letter-spacing:-.02em}
p.sub{margin:0 0 1.2em;opacity:.82}
.grid{display:grid;grid-template-columns:1fr 1fr;gap:16px}
@media(max-width:760px){.grid{grid-template-columns:1fr}}
label{display:block;font-size:13px;font-weight:600;opacity:.7;margin:0 0 6px;
 text-transform:uppercase;letter-spacing:.06em}
textarea{width:100%;min-height:290px;font:13px/1.5 ui-monospace,Menlo,Consolas,monospace;
 padding:12px;border:1px solid #c9c9d1;border-radius:10px;background:transparent;color:inherit}
button{font:600 15px/1 inherit;padding:12px 22px;border:0;border-radius:10px;
 background:#1d4ed8;color:#fff;cursor:pointer;margin:12px 8px 12px 0}
button:hover{background:#1a43bd}
button.ghost{background:transparent;color:inherit;border:1px solid #c9c9d1}
#out{min-height:290px;border:1px solid #d8d8e0;border-radius:10px;padding:4px 12px 12px;
 overflow:auto;max-height:420px}
table{border-collapse:collapse;width:100%;font-size:14px}
th,td{border-bottom:1px solid #d8d8e0;padding:8px 6px;text-align:left;vertical-align:top}
th{font-weight:600;opacity:.75;position:sticky;top:0;background:inherit}
td.n{width:56px;font:13px ui-monospace,monospace;opacity:.7}
.ok{padding:14px;border-radius:10px;background:#e8f5ec;color:#14532d;margin-top:10px}
@media(prefers-color-scheme:dark){.ok{background:#15321f;color:#bbf7d0}}
.count{font:600 13px/1 inherit;opacity:.7;margin:10px 0 2px}
.next{margin-top:18px;padding:18px 20px;border:1px solid #d8d8e0;border-radius:12px}
.next h2{font-size:1.05rem;margin:0 0 .2em}
.next p.axis{margin:.2em 0 .8em;opacity:.8;font-size:14px}
.next ul{margin:.3em 0 1em 1.1em;padding:0}
.next li{margin:.25em 0}
a.buy{display:inline-block;background:#111827;color:#fff;text-decoration:none;
 padding:12px 20px;border-radius:10px;font-weight:600}
@media(prefers-color-scheme:dark){a.buy{background:#e8e8ea;color:#14141a}}
.fine{font-size:13px;opacity:.7;margin:.7em 0 0}
.faq{margin-top:34px}
.faq h3{font-size:1rem;margin:1.2em 0 .2em}
.faq p{margin:.2em 0;opacity:.85}
code{font:13px ui-monospace,Menlo,Consolas,monospace;
 background:rgba(127,127,127,.14);padding:1px 5px;border-radius:4px}
</style>
<div class="wrap">
<h1>The devicetree line that compiles clean and boots wrong</h1>
<p class="sub"><code>status = "ok"</code> is not one of the five values in the Devicetree Specification v0.4
(<code>okay</code>, <code>disabled</code>, <code>reserved</code>, <code>fail</code>, <code>fail-sss</code>).
<code>dtc</code> has no opinion about it - it is just a string. Zephyr marks the node present only for the exact
value <code>okay</code>, so the sensor quietly leaves the build and you debug the driver instead of the line.
23 rules, 50 snippets. This page runs the same 23 rules the extension runs, in your browser, on nothing you upload.</p>

<div class="grid">
  <div>
    <label for="src">Your file (a sample is loaded)</label>
    <textarea id="src" spellcheck="false">/dts-v1/;
/ {
    compatible = "acme-controller";
    address-cells = &lt;1>;

    i2c1: i2c@40005400 {
        status = "ok";
        interrupt-parent = &lt;2>;
        phandle = &lt;1>;

        sensor@48 {
            compatible = "bosch,bme280";
            status = "enabled";
            reg = &lt;0x48>;
        };
    };
};</textarea>
    <button id="go">Check again</button>
    <button id="clr" class="ghost">Clear</button>
  </div>
  <div>
    <label>Findings</label>
    <div id="out"></div>
  </div>
</div>

<div class="next">
  <h2>The whole repo, not the open file</h2>
  <p class="axis">Everything above is free and needs no key, no account and no network - every one of the
  23 rules and all 50 snippets run on the file you have open, for as long as you like.
  The licence buys <strong>scale, a file you can hand over, and repetition</strong>:</p>
  <ul>
    <li><strong>Every file in the board repo at once</strong> - one command walks the workspace and runs the same 23 rules on each file, with the paths and line numbers in one list.</li>
    <li><strong>The findings as a file you can attach</strong> - written into the workspace as CSV, JSON or HTML for a review comment or a bring-up checklist.</li>
    <li><strong>Re-checked on every save</strong> - a toggle; after that the findings refresh as you type and save, instead of when you remember to look.</li>
    <li><strong>A fix list</strong> - the lines that have a documented correct value, counted and named so you can work down them. It reports; it does not rewrite your file.</li>
  </ul>
  <a class="buy" href="https://getreadystack.com/api/buy/cl/polar_cl_CFCuxNMjv5zsartvO10MlY2XKN142StTkIxHL43Dlqa">Get the licence - $29</a>
  <p class="fine">One-time, $29. A freelance embedded software engineer bills about $103 an hour
  (contractrates.fyi, 2026); a staff embedded firmware engineer's hour averages $58.66 (ZipRecruiter, June 2026).
  Works offline; the key is checked once, then every 7 days.</p>
</div>

<div class="faq">
  <h2>Questions</h2>
  <h3>What does it actually do?</h3>
  <p>It reads a config file line by line and reports the spellings that parse but do not mean what you
  wrote - <code>status = "ok"</code>, a <code>compatible</code> with no comma, <code>address-cells</code>
  without the <code>#</code>, an unquoted TOML <code>edition</code>. 23 rules over seven languages, plus
  50 snippets. No toolchain, no build context, no network.</p>
  <h3>Do the free devicetree extensions not already do this?</h3>
  <p>They highlight and complete, and inside a configured Zephyr or nRF context they resolve bindings -
  that part they do better than this pack. They do not grade a bare <code>.overlay</code> pasted out of a
  vendor forum, and they say nothing about the TOML, <code>.properties</code>, <code>.ahk</code>,
  <code>.rpy</code> or <code>.ink</code> files sitting in the same repo.</p>
  <h3>Why does an AI assistant get this wrong?</h3>
  <p>Because <code>enabled</code> is the English word and every other config format in the repo uses it.
  Devicetree does not: the value that turns a node on is <code>okay</code> and nothing else. It is the exact
  shape of mistake that reads correct and builds clean.</p>
</div>
</div>
<script>
var RULES=[{"pattern": "status\\s*=\\s*\"ok\"", "flags": "i", "message": "status = \"ok\" is not in the Devicetree Specification v0.4 status list (\"okay\", \"disabled\", \"reserved\", \"fail\", \"fail-sss\"). Zephyr marks the node present only for the exact value \"okay\".", "fix": "status = \"okay\""}, {"pattern": "status\\s*=\\s*\"disable\"", "flags": "i", "message": "The disabled state is spelled \"disabled\". \"disable\" is not a defined status value.", "fix": "status = \"disabled\""}, {"pattern": "status\\s*=\\s*\"enabled?\"", "flags": "i", "message": "There is no \"enable\"/\"enabled\" status in devicetree. The value that turns a node on is \"okay\".", "fix": "status = \"okay\""}, {"pattern": "compatible\\s*=\\s*\"[^\",]*\"", "flags": "i", "message": "A compatible string is written \"vendor,device\". Without the comma it matches no binding and the driver never probes.", "fix": ""}, {"pattern": "^\\s*address-cells\\s*=", "flags": "im", "message": "The property is #address-cells, with the leading hash. Written without it, the parent supplies no address cell count and every child reg is read wrong.", "fix": "#address-cells ="}, {"pattern": "^\\s*[a-z][a-z0-9_-]*_[a-z0-9_-]*@[0-9a-f]+\\s*\\{", "flags": "im", "message": "Underscores in a node name are flagged by dtc -Wnode_name_chars_strict. Node names use lowercase letters, digits and hyphens; keep underscores for the label before the colon.", "fix": ""}, {"pattern": "@0x[0-9a-f]+\\s*\\{", "flags": "im", "message": "A unit address is written without the 0x prefix, for example serial@40011000. dtc compares it against the first reg cell as plain hex.", "fix": ""}, {"pattern": "interrupt-parent\\s*=\\s*<\\s*[0-9]", "flags": "i", "message": "interrupt-parent takes a phandle reference such as <&intc>. A literal number here only works if it happens to match a generated phandle value.", "fix": ""}, {"pattern": "^\\s*phandle\\s*=\\s*<", "flags": "im", "message": "dtc generates phandle values itself. Setting one by hand can collide with a generated value and silently rewire an interrupt or clock.", "fix": ""}, {"pattern": "gpios\\s*=\\s*<\\s*&[a-z0-9_]+\\s+[0-9]+\\s*>", "flags": "i", "message": "A GPIO specifier on these bindings has two cells: pin and flags, as in <&gpio0 13 GPIO_ACTIVE_LOW>. With the flags cell missing the polarity defaults and the LED or button reads inverted.", "fix": ""}, {"pattern": "^\\s*version\\s*=\\s*[0-9]+\\.[0-9]+", "flags": "im", "message": "TOML has no bare version literal. 1.0.0 is not a number, so the key must be quoted: version = \"1.0.0\".", "fix": ""}, {"pattern": "^\\s*edition\\s*=\\s*[0-9]{4}\\s*$", "flags": "im", "message": "The edition key is a string in TOML: edition = \"2021\". An unquoted year parses as an integer and the manifest is rejected.", "fix": ""}, {"pattern": "^\\s*requires-python\\s*=\\s*[^\"'\\s]", "flags": "im", "message": "PEP 621 requires-python is a quoted string: requires-python = \">=3.9\". An unquoted specifier is not valid TOML.", "fix": ""}, {"pattern": "^\\s*mp\\.jwt\\.verify\\.publickey\\.location\\s*=\\s*http:", "flags": "im", "message": "mp.jwt.verify.publickey.location is being fetched over plain http, so the verification key can be swapped in transit. Use https, classpath: or file:.", "fix": ""}, {"pattern": "^\\s*%[a-z0-9]+\\s*=", "flags": "im", "message": "A MicroProfile config profile prefix must be followed by the property name: %dev.my.property=value. On its own, %dev is not a property key.", "fix": ""}, {"pattern": "/mp-rest/(uri|baseurl|base-url)\\s*=", "flags": "i", "message": "The MicroProfile Rest Client key is /mp-rest/url. Any other spelling is ignored and the client falls back to the annotation value.", "fix": ""}, {"pattern": "^\\s*(MsgBox|SetTimer|StringReplace|WinActivate|Gui|FileAppend)\\s*,", "flags": "im", "message": "This is AutoHotkey v1 command syntax. v2 uses function calls with parentheses, for example MsgBox(\"text\") and SetTimer(callback, 1000).", "fix": ""}, {"pattern": "^\\s*#(NoEnv|Persistent|EscapeChar)\\b", "flags": "im", "message": "This directive was removed in AutoHotkey v2. #NoEnv and #EscapeChar are gone, and #Persistent became the Persistent function.", "fix": ""}, {"pattern": ":=\\s*[^%\\n]*%[a-z_][a-z0-9_]*%", "flags": "i", "message": "Percent dereferencing inside an expression was removed in AutoHotkey v2. Write the variable name on its own, or use %name% only in a double-deref such as %varName%.", "fix": ""}, {"pattern": "\\bim\\.(Scale|FactorScale|Composite|Crop|Grayscale)\\(", "flags": "i", "message": "The im.* image manipulators are deprecated in Ren'Py. Use a Transform with zoom, xysize or crop instead; im.* results are not cached the same way and cost memory on Android.", "fix": ""}, {"pattern": "^\\s*(label\\s+[a-z_][a-z0-9_]*|menu)\\s*$", "flags": "im", "message": "A Ren'Py block statement ends with a colon: label start: or menu:. Without it the parser stops on this line.", "fix": ""}, {"pattern": "\\b(try|as)!\\s", "flags": "i", "message": "try! and as! crash the process on failure. Use try?/do-catch or as? with a guard so a malformed board profile does not take the tool down.", "fix": ""}, {"pattern": "^\\s*inkling\\s+\"1\\.[0-9]+\"", "flags": "im", "message": "The Inkling 1.x version declaration is not accepted by the 2.0 toolchain. The first line must read inkling \"2.0\".", "fix": "inkling \"2.0\""}];
function scan(t){var L=String(t).split(/\r?\n/),h=[],i,k,r,re;
 for(i=0;i<L.length;i++){for(k=0;k<RULES.length;k++){r=RULES[k];
  try{re=new RegExp(r.pattern,r.flags||'')}catch(e){continue}
  if(re.test(L[i]))h.push({line:i+1,msg:r.message,fix:r.fix||''})}}
 return h}
function esc(s){return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')}
function run(){
 var t=document.getElementById('src').value,o=document.getElementById('out');
 if(!t.trim()){o.innerHTML='<p class="count">Nothing to check.</p>';return}
 var h=scan(t);
 if(!h.length){o.innerHTML='<div class="ok">No findings. This file passes all '+RULES.length+' rules.</div>';return}
 var s='<p class="count">'+h.length+' finding'+(h.length===1?'':'s')+' in '+
   String(t).split(/\r?\n/).length+' lines</p><table><tr><th>Line</th><th>Finding</th></tr>';
 for(var i=0;i<h.length;i++){s+='<tr><td class="n">'+h[i].line+'</td><td>'+esc(h[i].msg)+
   (h[i].fix?' <code>'+esc(h[i].fix)+'</code>':'')+'</td></tr>'}
 o.innerHTML=s+'</table>'}
document.getElementById('go').onclick=run;
document.getElementById('clr').onclick=function(){
 document.getElementById('src').value='';run()};
document.getElementById('src').addEventListener('input',run);
run();
</script>
</html>


<section data-yj-install="free" style="margin:2rem auto 1rem;max-width:46rem;padding:1.25rem 1.25rem;border:1px solid #cfe3d6;border-radius:12px;background:#f6fbf8;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .4rem;font-size:1.2rem">Install free</h2><p style="margin:0 0 .8rem;color:#41505f">Free for the file open in your editor - no key, no limit. The workspace sweep and the report ask for a key.</p><a href="https://www.npmjs.com/package/@readystack/devicetree-config-language-pack" rel="noopener" data-yj-install-door="npm" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'devicetree-config-language-pack',src:'npm',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">npm</a><a href="https://www.npmjs.com/package/@readystack/devicetree-config-language-pack" rel="noopener" data-yj-install-door="mcp" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'devicetree-config-language-pack',src:'mcp',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">MCP server (npx)</a><a href="https://hub.docker.com/r/getreadystack/devicetree-config-language-pack" rel="noopener" data-yj-install-door="docker" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'devicetree-config-language-pack',src:'docker',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">Docker Hub</a><pre style="margin:.5rem 0 0;padding:.6rem .8rem;background:#f3f5f8;border-radius:8px;font-size:.9rem;overflow:auto">npx @readystack/devicetree-config-language-pack &lt;file&gt;
npx @readystack/devicetree-config-language-pack --mcp
docker run --rm -v &quot;$PWD:/w&quot; getreadystack/devicetree-config-language-pack /w</pre><p style="margin:.6rem 0 0;font-size:.92rem;color:#41505f"><a href="https://getreadystack.com/api/buy/cl/polar_cl_l6iN1uWt0FwWu7tBsczD0jWpP2vxFM54Wdwqb3KPi1G" rel="nofollow" style="color:#0f7b3f;text-decoration:underline">Team? One key for every ReadyStack linter, 5 seats, $149 once</a></p></section>
<section data-yj-alert="rule" style="margin:1rem auto 1.5rem;max-width:46rem;padding:1.1rem 1.25rem;border:1px solid #d9dee6;border-radius:12px;background:#fbfcfd;font:15px/1.55 system-ui,-apple-system,Segoe UI,sans-serif"><b style="font-size:1.05rem">Get the full rule table as a PDF</b><div style="opacity:.78;margin:.35rem 0 .8rem">All 23 rules DeviceTree Config Audit: 23 dtc-Style Rules, 50 Snippets checks, each with its source and date, on printable pages you can hand to your team or auditor. We email it now, and once more only if a rule changes. No newsletter.</div><div style="display:flex;gap:8px;flex-wrap:wrap"><input id="yjae" type="email" placeholder="you@example.com" style="flex:1;min-width:210px;padding:11px 13px;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:#fff;color:inherit"><button id="yjab" style="padding:11px 18px;border-radius:8px;border:0;cursor:pointer;background:#0f7b3f;color:#fff;font:600 15px system-ui,sans-serif">Email me the PDF</button></div><div id="yjao" hidden style="margin-top:.6rem;color:#0f7b3f">Sent. It arrives within the hour - check spam too.</div><script>(function(){var b=document.getElementById("yjab"),e=document.getElementById("yjae");if(!b||!e)return;b.addEventListener("click",function(){var v=e.value.trim();if(!/.+@.+\..+/.test(v))return;try{localStorage.setItem("yj_em","1");}catch(_){}fetch(location.origin+"/api/subscribe",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:v,slug:"devicetree-config-language-pack",lang:"en",source:"rule_table"+((b.closest&&b.closest("section")&&b.closest("section").getAttribute("data-yj-moved"))?"_at_result":"")})}).then(function(r){var o=document.getElementById("yjao");o.hidden=false;if(!r.ok){o.textContent="Could not save - please try again.";}}).catch(function(){var o=document.getElementById("yjao");o.hidden=false;o.textContent="Could not save - please try again.";});});})();</script><script>(function(){var e=document.getElementById("yjae"),s=e&&e.closest?e.closest("section"):null,o=document.getElementById("out");if(!s||!o)return;var d=false;function mv(ev){if(d)return;if(ev&&ev.target&&s.contains(ev.target))return;d=true;var b=o;while(b.parentNode&&b.parentNode!==document.body&&b.parentNode.tagName!=="MAIN"&&b.parentNode.tagName!=="ARTICLE")b=b.parentNode;if(!b.parentNode||b===s||b.contains(s))return;try{b.parentNode.insertBefore(s,b.nextSibling);s.setAttribute("data-yj-moved","1");}catch(_){}}document.addEventListener("input",mv,true);document.addEventListener("change",mv,true);})();</script></section>

<section data-yj-cta="paid" style="margin:3rem auto;max-width:46rem;padding:1.5rem 1.25rem;border:1px solid #d8dee9;border-radius:12px;background:#fbfcfe;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .5rem;font-size:1.25rem">Get the complete version <span class="yj-price">$29</span></h2><p style="margin:.25rem 0 1rem;color:#41505f">This page is the working piece. The full pack has everything below.</p><p style="margin:0 0 1rem;color:#41505f">status = &quot;ok&quot; compiles clean and the node never appears. 23 rules over 7 config languages, on the file you have open.</p><p style="margin:0 0 1rem;color:#5b6b7c;font-size:.94rem">A freelance embedded software engineer bills about $103/hour (contractrates.fyi, 2026); a staff embedded firmware engineer's hour averages $58.66 in the US (ZipRecruiter, June 2026). One node silently dropped from a build costs an</p><a href="https://getreadystack.com/api/buy/cl/polar_cl_CFCuxNMjv5zsartvO10MlY2XKN142StTkIxHL43Dlqa" rel="nofollow" style="display:inline-block;padding:.7rem 1.3rem;border-radius:8px;background:#1b64f2;color:#fff;text-decoration:none;font-weight:600">Buy the full version — $29</a></section>
<!--yj-share-s101--><div style="margin:28px 0 8px;text-align:center"><button id="yjcp" type="button" style="font:inherit;padding:10px 18px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Copy link</button><button id="yjimg" type="button" style="font:inherit;padding:10px 18px;margin-left:8px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Save result as image</button></div><script>(function(){var b=document.getElementById("yjimg");if(!b)return;b.addEventListener("click",function(){var o=document.getElementById("out");var txt=(o&&(o.innerText||o.textContent)||"").trim();if(!txt){b.textContent="(no result yet)";setTimeout(function(){b.textContent="Save result as image";},1500);return;}var lines=txt.split(String.fromCharCode(10)).filter(function(x){return x.trim();}).slice(0,10);var W=1200,P=56,c=document.createElement("canvas");c.width=W;var lh=38,H=P*2+70+lines.length*lh+60;c.height=H;var x=c.getContext("2d");x.fillStyle="#1a1512";x.fillRect(0,0,W,H);x.fillStyle="#f3e9d2";x.font="600 34px system-ui,Segoe UI,Arial";var t=(document.title||"").split("|")[0].trim();x.fillText(t.slice(0,54),P,P+34);x.font="22px ui-monospace,Menlo,Consolas,monospace";x.fillStyle="#e8dcc4";for(var i=0;i<lines.length;i++){x.fillText(lines[i].slice(0,88),P,P+70+i*lh+22);}x.font="600 22px system-ui,Segoe UI,Arial";x.fillStyle="#c9a227";var d=location.hostname.replace("www.","");x.fillText(d,W-P-x.measureText(d).width,H-P+6);c.toBlob(function(bl){var u=URL.createObjectURL(bl),a=document.createElement("a");a.href=u;a.download=(t||"result").replace(/[^a-z0-9]+/gi,"-").toLowerCase()+"-"+d+".png";document.body.appendChild(a);a.click();setTimeout(function(){URL.revokeObjectURL(u);a.remove();},2000);},"image/png");});})();</script><script>(function(){var b=document.getElementById("yjcp");if(!b)return;var t=b.textContent;b.addEventListener("click",function(){var u=location.href.split("#")[0];function d(){b.textContent="Link copied";setTimeout(function(){b.textContent=t;},1800);}if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(u).then(d,function(){prompt("",u);});}else{prompt("",u);}});})();</script><div class="yj-home-find"><div class="yj-lgbar"><a href="/" class="yj-lg on">EN</a><a href="/de/" class="yj-lg">DE</a><a href="/ja/" class="yj-lg">JA</a><a href="/es/" class="yj-lg">ES</a><a href="/pt/" class="yj-lg">PT</a></div><section class="yj-find"><h2>Find a tool</h2><input id="yjq" type="search" autocomplete="off" placeholder="Type a product name, format or task"><div id="yjr"></div></section><style>.yj-lgbar{position:absolute;top:14px;right:18px;display:flex;gap:6px;z-index:60}.yj-lg{font:600 12px/1 system-ui,sans-serif;padding:6px 9px;border-radius:4px;text-decoration:none;color:#8b96a3;border:1px solid rgba(140,150,165,.28)}.yj-lg:hover{color:#e8eaed;border-color:rgba(160,175,195,.6)}.yj-lg.on{color:#0e1116;background:#cfd6de;border-color:#cfd6de}.yj-find{max-width:760px;margin:34px auto 8px;padding:0 20px}.yj-find h2{font:600 20px/1.3 system-ui,sans-serif;margin:0 0 10px}#yjq{width:100%;box-sizing:border-box;padding:13px 15px;font:400 15.5px system-ui,sans-serif;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:rgba(255,255,255,.04);color:inherit}#yjq:focus{outline:none;border-color:#7FD1C4}#yjr{margin-top:10px;display:flex;flex-direction:column;gap:6px}#yjr a{display:flex;justify-content:space-between;gap:12px;padding:11px 14px;border:1px solid rgba(140,150,165,.22);border-radius:6px;text-decoration:none;font:400 14.5px/1.4 system-ui,sans-serif;color:inherit}#yjr a:hover{border-color:#7FD1C4}#yjr .pr{font:600 13px system-ui,sans-serif;color:#5fbf9a;white-space:nowrap}</style><script>(function(){var q=document.getElementById("yjq"),r=document.getElementById("yjr"),D=null;function load(){if(D)return Promise.resolve(D);return fetch("/search-index.json").then(function(x){return x.json();}).then(function(j){D=j;return j;}).catch(function(){D=[];return D;});}function esc(t){return String(t).replace(/[&<>"]/g,function(c){return {"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;"}[c];});}function run(){var v=q.value.trim().toLowerCase();if(v.length<2){r.innerHTML="";return;}load().then(function(j){var w=v.split(/\s+/),o=[];for(var i=0;i<j.length&&o.length<12;i++){var t=j[i].t.toLowerCase();var ok=true;for(var k=0;k<w.length;k++){if(t.indexOf(w[k])<0){ok=false;break;}}if(ok)o.push(j[i]);}r.innerHTML=o.length?o.map(function(x){return "<a href=\""+esc(x.u)+"\">"+"<span>"+esc(x.t)+"</span>"+(x.p?"<span class=\"pr\">$"+x.p+"</span>":"")+"</a>";}).join(""):"";});}q.addEventListener("input",run);q.addEventListener("focus",load);})();</script></div>


<script data-yj="yj-view-beacon">(function(){try{var p=location.pathname;var k='yjv:'+p;if(sessionStorage.getItem(k))return;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",ref:(document.referrer||''),src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}catch(e){}})();</script>

<script data-yj="yj-use-beacon">(function(){try{var o=document.getElementById('out');if(!o)return;var p=location.pathname,k='yju:'+p,sent=false;function fire(){if(sent||sessionStorage.getItem(k))return;if(!(o.textContent||'').replace(/\s+/g,'').length)return;sent=true;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",t:'use',src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}var mo=new MutationObserver(function(){fire();if(sent)mo.disconnect();});mo.observe(o,{childList:true,characterData:true,subtree:true});}catch(e){}})();</script>
<section data-yj="yj-facts-v1" style="max-width:920px;margin:48px auto 0;padding:0 20px;font-family:system-ui,sans-serif"><style>.yj-article p{font:400 15.5px/1.7 system-ui,sans-serif;color:#26313b;margin:0 0 12px;max-width:72ch}.yj-article h2,.yj-article h3,.yj-article h4{font:600 17px/1.35 system-ui,sans-serif;color:#1b1f24;margin:22px 0 8px}.yj-article table{border-collapse:collapse;margin:10px 0 16px;font:14px/1.45 system-ui,sans-serif}.yj-article th,.yj-article td{border:1px solid #e2e6ea;padding:6px 10px;text-align:left}.yj-article th{background:#f4f6f8}.yj-article pre{background:#0f1720;color:#e6edf3;padding:12px 14px;border-radius:8px;overflow:auto;font:13px/1.5 ui-monospace,Menlo,monospace}.yj-article code{font:13px ui-monospace,Menlo,monospace;background:#f1f3f5;padding:1px 4px;border-radius:3px}.yj-article pre code{background:none;padding:0}.yj-article ul,.yj-article ol{font:15px/1.6 system-ui,sans-serif;color:#26313b}</style><p style="font:400 13px/1.5 system-ui,sans-serif;color:#6b7680;margin:0 0 14px"><time datetime="2026-09-08">Updated 2026-09-08</time> · ReadyStack</p><script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","dateModified":"2026-09-08","author":{"@type":"Organization","name":"ReadyStack"}}</script><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:0 0 6px;color:#1b1f24">Worked example</h2><p style="font:400 14.5px/1.5 system-ui,sans-serif;margin:0 0 16px;color:#5b6570">Real numbers from this tool, line by line.</p><div class="yj-article"><p><img src="https://getreadystack.com/img/promo/sku10770_result_card.jpg" alt="The devicetree line that compiles clean and boots wrong" loading="lazy" style="max-width:100%;border-radius:6px"></p>
<p>Your board comes up. The console prints. The I2C sensor you added last night is not there.</p>
<p>So you do what everyone does. You check the pull-ups. You scope SDA. You add a print to the driver&#x27;s init hook and it never fires, so you go and read the driver, and about two hours later you scroll past this:</p>
<pre><code>&amp;i2c1 {
    status = &quot;okay&quot;;

    bme280@76 {
        compatible = &quot;bosch,bme280&quot;;
        reg = &lt;0x76&gt;;
        status = &quot;ok&quot;;
    };
};</code></pre>
<p><code>status = &quot;ok&quot;</code>. Two letters short, and the build never said a word.</p>
<h3>The compiler has no opinion about it</h3>
<p><code>status</code> is a string property. <code>dtc</code> will compile any string you put there: <code>&quot;ok&quot;</code>, <code>&quot;yes&quot;</code>, <code>&quot;banana&quot;</code>. The value is not the compiler&#x27;s business.</p>
<p>It is the binding&#x27;s business. The Devicetree Specification v0.4 defines exactly five values for <code>status</code>: <code>okay</code>, <code>disabled</code>, <code>reserved</code>, <code>fail</code> and <code>fail-sss</code>. Zephyr&#x27;s generated headers mark a node as present only for the exact string <code>okay</code>. Anything else, including <code>&quot;ok&quot;</code>, <code>&quot;enable&quot;</code> and the very natural-looking <code>&quot;enabled&quot;</code>, is simply not <code>okay</code>, so the node is not enabled, the device entry is never emitted, and there is nothing on the bus to talk to.</p>
<p>No error. No warning. A clean build and a missing sensor.</p>
<h3>It has four cousins</h3>
<p>Once you start looking for this shape, a bring-up repo is full of it. Every line below compiles:</p>
<pre><code>compatible = &quot;acme-controller&quot;;  /* no comma, so it matches no binding and the driver never probes */
address-cells = &lt;1&gt;;             /* no leading #, so the parent supplies no address cell count */
interrupt-parent = &lt;2&gt;;          /* a literal where a phandle reference belongs */
phandle = &lt;1&gt;;                   /* hand-set, and free to collide with a generated value */
sensor@0x40005400 { };           /* a unit address written with 0x, compared as plain hex */</code></pre>
<p>None of these is a syntax error. They are all spelling mistakes in a language where the spelling is the semantics, and every one of them fails somewhere far away from the line that caused it: at probe time, at link time, or on the bench with a scope in your hand.</p>
<h3>Why your assistant writes it too</h3>
<p><code>enabled</code> is the English word for what you are trying to do, and every other config format in the same repository agrees with it:</p>
<pre><code>
mp.metrics.enabled=true</code></pre>
<pre><code># TOML - correct
enabled = true</code></pre>
<pre><code>// devicetree - wrong, and it compiles
status = &quot;enabled&quot;;</code></pre>
<p>A model generating an overlay is pattern-matching against a world where <code>enabled</code> is right almost everywhere. Devicetree is the exception, and the exception is not visible in the output. This is the category of mistake that reads correct, reviews correct and builds correct.</p>
<h3>The rest of the repo has the same disease</h3>
<p>The <code>.dts</code> file is rarely alone. The manifest next to it:</p>
<pre><code>[package]
edition = 2021           # rejected - the year is a string
version = 1.0.0          # not a number; TOML has no bare version literal
requires-python = &gt;=3.9  # PEP 621 wants a quoted specifier</code></pre>
<p>The service config next to that:</p>
<pre><code>com.acme.InventoryClient/mp-rest/uri=https://inventory.svc:8443</code></pre>
<p>The MicroProfile Rest Client key is <code>/mp-rest/url</code>. Any other spelling is not an error - it is ignored, and the client silently falls back to the value baked into the annotation. Then there is AutoHotkey v1 syntax in a v2 script, a Ren&#x27;Py <code>label</code> with no colon, an Inkling file still declaring <code>inkling &quot;1.0&quot;</code>. All of them plain text as far as the editor is concerned.</p>
<h3>What I ended up building</h3>
<p>A VS Code pack with 23 of these rules and 50 snippets, covering devicetree, TOML, MicroProfile <code>.properties</code>, AutoHotkey v2, Ren&#x27;Py, Swift and Inkling. Ten of the 23 rules are devicetree; the rest are the files that sit around it.</p>
<p>Run it on the file you have open and you get line numbers and a sentence explaining what the correct spelling is and why. That part is free: all 23 rules, all 50 snippets, no key, no account, no network call and no build context. It works on a bare <code>.overlay</code> you pasted out of a vendor forum, which is exactly where the free devicetree extensions stop, because they want a configured Zephyr or nRF context first.</p>
<p>The licence changes the scale rather than the rules. It runs the same 23 rules over every file in the workspace in one pass, writes the findings into the repo as CSV, JSON or HTML so you can attach them to a review, and re-runs the check on every save instead of when you remember to look.</p>
<p>There is a browser version that runs the same 23 rules on text you paste, with nothing uploaded, if you want to check one file before installing anything.</p>
<p>Two hours of driver debugging is worth more than a config linter. That is the whole argument.</p></div><h2 style="font:600 19px/1.3 system-ui,sans-serif;margin:30px 0 10px;color:#1b1f24">15 seconds — what it actually does</h2><video controls muted playsinline preload="none" poster="/img/promo/sku10770_result_card.jpg" style="width:100%;max-width:360px;border-radius:10px;display:block;margin:0 auto"><source src="/media/sku10770_short.mp4" type="video/mp4"></video><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:34px 0 6px;color:#1b1f24">Questions people ask</h2><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What does the DeviceTree Config Audit pack actually do?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">It reads a config file line by line and reports every spelling that parses but does not mean what you wrote: status = &quot;ok&quot;, a compatible string with no comma, address-cells without the leading hash, an unquoted TOML edition. Twenty-three rules across seven languages and fifty snippets, with line numbers. No toolchain, no build context, no network.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Who is this pack for?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Firmware and embedded engineers doing Zephyr or embedded Linux board bring-up inside VS Code. It is aimed at the repo where .dts, .dtsi and .overlay files sit beside a Cargo or pyproject TOML, MicroProfile .properties, AutoHotkey v2 bench scripts, Ren&#x27;Py or Inkling - the files the editor still renders as plain text.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Do the free devicetree extensions not already cover this?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">They highlight and complete, and inside a configured Zephyr or nRF context they resolve bindings better than this pack does. What they do not do is grade a bare .overlay pasted out of a vendor forum, or say anything about the TOML, .properties, .ahk and .rpy files in the same repo. A chatbot will hand you status = &quot;enabled&quot; without blinking.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What is free and what needs the licence key?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Free covers the file you have open, completely: all twenty-three rules run, all fifty snippets insert, no key is asked for and nothing expires. The licence changes scale, not rules - every file in the workspace at once, the findings exported as a CSV, JSON or HTML file, and a re-check that fires on every save.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">How does $29 compare to doing this by hand?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">A staff embedded firmware engineer&#x27;s hour averages $58.66 in the United States (ZipRecruiter, June 2026), and a freelance embedded software engineer bills about $103 (contractrates.fyi, 2026). One sensor missing from a build because of a four-letter status value costs an afternoon at the bench, not half an hour.</p></details><script type="application/ld+json" data-yj="yj-faq-ld">{"@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [{"@type": "Question", "name": "What does the DeviceTree Config Audit pack actually do?", "acceptedAnswer": {"@type": "Answer", "text": "It reads a config file line by line and reports every spelling that parses but does not mean what you wrote: status = \"ok\", a compatible string with no comma, address-cells without the leading hash, an unquoted TOML edition. Twenty-three rules across seven languages and fifty snippets, with line numbers. No toolchain, no build context, no network."}}, {"@type": "Question", "name": "Who is this pack for?", "acceptedAnswer": {"@type": "Answer", "text": "Firmware and embedded engineers doing Zephyr or embedded Linux board bring-up inside VS Code. It is aimed at the repo where .dts, .dtsi and .overlay files sit beside a Cargo or pyproject TOML, MicroProfile .properties, AutoHotkey v2 bench scripts, Ren'Py or Inkling - the files the editor still renders as plain text."}}, {"@type": "Question", "name": "Do the free devicetree extensions not already cover this?", "acceptedAnswer": {"@type": "Answer", "text": "They highlight and complete, and inside a configured Zephyr or nRF context they resolve bindings better than this pack does. What they do not do is grade a bare .overlay pasted out of a vendor forum, or say anything about the TOML, .properties, .ahk and .rpy files in the same repo. A chatbot will hand you status = \"enabled\" without blinking."}}, {"@type": "Question", "name": "What is free and what needs the licence key?", "acceptedAnswer": {"@type": "Answer", "text": "Free covers the file you have open, completely: all twenty-three rules run, all fifty snippets insert, no key is asked for and nothing expires. The licence changes scale, not rules - every file in the workspace at once, the findings exported as a CSV, JSON or HTML file, and a re-check that fires on every save."}}, {"@type": "Question", "name": "How does $29 compare to doing this by hand?", "acceptedAnswer": {"@type": "Answer", "text": "A staff embedded firmware engineer's hour averages $58.66 in the United States (ZipRecruiter, June 2026), and a freelance embedded software engineer bills about $103 (contractrates.fyi, 2026). One sensor missing from a build because of a four-letter status value costs an afternoon at the bench, not half an hour."}}]}</script><div id="yj-ask" style="margin:36px 0 0;padding:18px 18px 16px;border:1px solid #e2e6ea;border-radius:10px;background:#fbfbfc"><h2 style="font:600 19px/1.3 system-ui,sans-serif;margin:0 0 4px;color:#1b1f24">Ask about this tool</h2><p style="font:400 13.5px/1.5 system-ui,sans-serif;margin:0 0 12px;color:#5b6570">One question, answered by the person who built it. Your email only if you want the answer sent.</p><form onsubmit="return yjAsk(event)" style="display:grid;gap:8px"><textarea name="question" required minlength="10" maxlength="2000" rows="3" placeholder="Your question" style="font:14px/1.5 system-ui,sans-serif;padding:10px;border:1px solid #cfd6dd;border-radius:6px"></textarea><div style="display:flex;gap:8px;flex-wrap:wrap"><input type="email" name="email" placeholder="Email (optional)" style="flex:1;min-width:200px;font:14px system-ui,sans-serif;padding:9px 10px;border:1px solid #cfd6dd;border-radius:6px"><button type="submit" style="font:600 14px system-ui,sans-serif;padding:9px 18px;border:0;border-radius:6px;background:#1b1f24;color:#fff;cursor:pointer">Send</button></div><p id="yj-ask-msg" style="font:13px system-ui,sans-serif;margin:2px 0 0;color:#0a6238;min-height:1em"></p></form><script>function yjAsk(e){e.preventDefault();var f=e.target,m=document.getElementById("yj-ask-msg");m.style.color="#0a6238";fetch(location.origin+"/api/ask",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sku:10770,slug:"devicetree-config-language-pack",lang:"en",question:f.question.value,email:f.email.value,page:location.pathname})}).then(function(r){if(!r.ok)throw 0;m.textContent="Thanks \u2014 noted. Answers land on this page and, if you left an email, in your inbox.";f.question.value="";}).catch(function(){m.style.color="#a8551f";m.textContent="Could not send. Please try again in a minute.";});return false;}</script></div></section><section class="yj-related" style="max-width:920px;margin:56px auto 40px;padding:0 20px"><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:0 0 6px;color:#1b1f24">Same job, next tool</h2><p style="font:400 14.5px/1.5 system-ui,sans-serif;margin:0 0 20px;color:#5b6570">Free in the browser. The full version is a one-time licence.</p><div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:14px"><a class="yj-rel-c" href="https://getreadystack.com/tools/autohotkey-toml-devicetree-snippets"><span class="yj-rel-t">AutoHotkey v2, TOML and DeviceTree checks for VS Code</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/config-dsl-lint-snippet-pack"><span class="yj-rel-t">Config &amp; DSL Lint + Snippets — 9 Sets</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/spdx-license-field-lint"><span class="yj-rel-t">SPDX License Field Lint for package.json, pyproject.toml and Cargo.toml</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/bulk-sender-lint"><span class="yj-rel-t">Bulk Sender Lint - the Gmail, Yahoo and Outlook.com rules, checked in your mai</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/cargo-publish-gate"><span class="yj-rel-t">Cargo.toml Publish Gate - crates.io</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/en301549-lint"><span class="yj-rel-t">EN 301 549 Lint — European Accessibility Act rules, with the clause number, in</span><span class="yj-rel-p">$29</span></a></div><style>.yj-rel-c{display:flex;flex-direction:column;gap:8px;padding:15px 16px;border:1px solid #e2e6ea;border-radius:6px;text-decoration:none;background:#fff}.yj-rel-c:hover{border-color:#b9c2cb;background:#fafbfc}.yj-rel-t{font:500 14.5px/1.42 system-ui,sans-serif;color:#1b1f24}.yj-rel-p{font:600 13px system-ui,sans-serif;color:#0a6238}</style></section>