-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
400 lines (359 loc) · 25.4 KB
/
atom.xml
File metadata and controls
400 lines (359 loc) · 25.4 KB
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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[Four Bits Per Nybble]]></title>
<link href="http://chris.elledge.org/atom.xml" rel="self"/>
<link href="http://chris.elledge.org/"/>
<updated>2014-02-20T22:12:03-05:00</updated>
<id>http://chris.elledge.org/</id>
<author>
<name><![CDATA[Chris Elledge]]></name>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[Usefully Random]]></title>
<link href="http://chris.elledge.org/blog/2014/02/20/usefully-random/"/>
<updated>2014-02-20T21:17:00-05:00</updated>
<id>http://chris.elledge.org/blog/2014/02/20/usefully-random</id>
<content type="html"><![CDATA[<p>Some microcontroller projects require the generation of random
numbers. The first thought is to simply use the random() call provided
by the compiler libraries. That function provides psuedorandom
numbers which will probably seem random enough at first pass.</p>
<p>Unfortunately, you may realize that after some usage, the random
numbers generated by this function always gives the same sequence of
results. This is caused by the microcontroller always using the same
seed for the generator. If you want the numbers to no longer be
completely deterministic, you will need to provide a seed to the
random number library. This is typically done with
srandom(uint32_t). By providing a seed, you can initialize the random
library with a different state.</p>
<p>The question becomes, “what can you use as a seed?” If all your
devices have unique serial numbers, those could be used. Then at least
each of your devices should have a different sequence of random
numbers. Unfortunately, those sequences would still be the same on
each reboot for a single devices. Below I will present a method for
getting enough entropyon an Atmel AVR to seed the generator for what I
call “usefully random.”</p>
<p>The Atmel AVR Mega series has several different oscilators which are
not phase locked. This means that you can use the interference between
these oscilators to provide some variability. The easiest way to do
this is to setup an interrupt off of one oscillator and count the
ticks of another oscillator. For example you can setup a Timer/Counter
to run from the main high speed oscillator, and have the Watchdog
Timer running from the 128kHz oscillator trigger an interrupt. From
the interrupt the counter can be queried. There is quite a bit of
jitter between the oscillators which means that the lowest few bits in
the counter can be used for entropy. Just do this a few times and
rotate in the bits to a 32 bit value. Then that value can be used as the
seed.</p>
<p>An additional source of entropy can be obtained by sampling a floating
analog pin repeatedly. The bottom couple of bits can be used as noise
measurement. By mixing both approaches, it is pretty easy to have
enough entropy to seed the generator in less than 100ms after booting,
allowing for use of the ADC and Timer/Counter for other application
purposes.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Linux on H87M-E & Haswell]]></title>
<link href="http://chris.elledge.org/blog/2013/09/21/linux-on-h87m-e-and-haswell/"/>
<updated>2013-09-21T09:55:00-04:00</updated>
<id>http://chris.elledge.org/blog/2013/09/21/linux-on-h87m-e-and-haswell</id>
<content type="html"><![CDATA[<p>I wanted to write down my notes for getting Ubuntu Linux fully
running on an Asus H87M-E with a Intel Haswell processor. I use this
on a media center, so I needed HDMI video and audio support.</p>
<ul>
<li>Ubuntu 13.04 is required for support of the Haswell GPU.</li>
<li>Linux kernel 3.10 is required for HDMI audio support.</li>
<li>I used Upubuntu to install 3.10.7 for my system.</li>
<li><a href="http://www.ocztechnologyforum.com/forum/showthread.php?111964-Vertex-2-Agility-2-and-Haswell">Never use an older (1200/1500 series) Sandforce Controller SSD with Haswell Motherboards</a>.</li>
<li>The hardware controller is a NCT6791D. You will need a very recent
version of the <a href="https://github.com/groeck/nct6775">nct6775 driver</a>. It will probably be merged in
Linux 3.12.</li>
<li>If you use Western Digital Green Drives on Linux be sure to look at
<a href="http://idle3-tools.sourceforge.net/">idle3-tools</a>.</li>
</ul>
<p>Here is a script that I wrote to setup the fans in a way useful for my
system. One fan sits on my HDs, so I wanted to regulate it based on
their temperature.</p>
<!-- more -->
<figure class='code'><figcaption><span>H87M-E Fan Controller - fanctl.py </span></figcaption>
<div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
</pre></td><td class='code'><pre><code class='py'><span class='line'><span class="c">#!/usr/bin/python</span>
</span><span class='line'>
</span><span class='line'><span class="kn">import</span> <span class="nn">daemon</span>
</span><span class='line'><span class="kn">import</span> <span class="nn">time</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">subprocess</span> <span class="kn">import</span> <span class="n">check_output</span>
</span><span class='line'>
</span><span class='line'><span class="n">fan_driver</span> <span class="o">=</span> <span class="s">'/sys/devices/platform/nct6775.656/'</span>
</span><span class='line'>
</span><span class='line'><span class="n">fan_setup</span> <span class="o">=</span> <span class="p">[</span>
</span><span class='line'> <span class="p">(</span><span class="s">'pwm1_enable'</span><span class="p">,</span><span class="mi">5</span><span class="p">),</span>
</span><span class='line'> <span class="p">(</span><span class="s">'pwm1_temp_sel'</span><span class="p">,</span><span class="mi">2</span><span class="p">),</span>
</span><span class='line'> <span class="p">(</span><span class="s">'pwm1_auto_point1_temp'</span><span class="p">,</span><span class="mi">39000</span><span class="p">),</span>
</span><span class='line'> <span class="p">(</span><span class="s">'pwm1_auto_point1_pwm'</span><span class="p">,</span><span class="mi">0</span><span class="p">),</span>
</span><span class='line'> <span class="p">(</span><span class="s">'pwm1_auto_point2_temp'</span><span class="p">,</span><span class="mi">41000</span><span class="p">),</span>
</span><span class='line'> <span class="p">(</span><span class="s">'pwm1_auto_point2_pwm'</span><span class="p">,</span><span class="mi">110</span><span class="p">),</span>
</span><span class='line'> <span class="p">(</span><span class="s">'pwm1_auto_point4_temp'</span><span class="p">,</span><span class="mi">75000</span><span class="p">),</span>
</span><span class='line'> <span class="p">(</span><span class="s">'pwm1_auto_point4_pwm'</span><span class="p">,</span><span class="mi">255</span><span class="p">),</span>
</span><span class='line'> <span class="p">(</span><span class="s">'pwm3_enable'</span><span class="p">,</span><span class="mi">1</span><span class="p">),</span>
</span><span class='line'> <span class="p">(</span><span class="s">'pwm3'</span><span class="p">,</span><span class="mi">90</span><span class="p">),</span>
</span><span class='line'><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">fan_setup</span><span class="p">:</span>
</span><span class='line'> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">fan_driver</span><span class="o">+</span><span class="n">s</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="s">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">fdf</span><span class="p">:</span>
</span><span class='line'> <span class="n">fdf</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="mi">1</span><span class="p">]))</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">get_hdd_temp</span><span class="p">(</span><span class="n">hdd</span><span class="p">):</span>
</span><span class='line'> <span class="n">temp_lines</span> <span class="o">=</span> <span class="n">check_output</span><span class="p">([</span><span class="s">'smartctl'</span><span class="p">,</span><span class="s">'-A'</span><span class="p">,</span> <span class="n">hdd</span><span class="p">])</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
</span><span class='line'> <span class="n">temp_line</span> <span class="o">=</span> <span class="nb">filter</span><span class="p">(</span><span class="k">lambda</span> <span class="n">l</span><span class="p">:</span> <span class="s">'Temperature'</span> <span class="ow">in</span> <span class="n">l</span><span class="p">,</span> <span class="n">temp_lines</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
</span><span class='line'> <span class="n">temp</span> <span class="o">=</span> <span class="n">temp_line</span><span class="o">.</span><span class="n">split</span><span class="p">()[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
</span><span class='line'> <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">temp</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">get_hdd_max_temp</span><span class="p">():</span>
</span><span class='line'> <span class="n">drives</span> <span class="o">=</span> <span class="p">[</span><span class="s">'/dev/sdb'</span><span class="p">,</span> <span class="s">'/dev/sdc'</span><span class="p">]</span>
</span><span class='line'> <span class="n">temps</span> <span class="o">=</span> <span class="nb">map</span><span class="p">((</span><span class="k">lambda</span> <span class="n">l</span><span class="p">:</span> <span class="n">get_hdd_temp</span><span class="p">(</span><span class="n">l</span><span class="p">)),</span><span class="n">drives</span><span class="p">)</span>
</span><span class='line'> <span class="k">return</span> <span class="nb">max</span><span class="p">(</span><span class="n">temps</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">hdd_temp_to_pwm</span><span class="p">(</span><span class="n">t</span><span class="p">):</span>
</span><span class='line'> <span class="k">if</span> <span class="n">t</span><span class="o"><=</span><span class="mi">31</span><span class="p">:</span>
</span><span class='line'> <span class="k">return</span> <span class="mi">0</span>
</span><span class='line'> <span class="k">elif</span> <span class="n">t</span><span class="o"><=</span><span class="mi">48</span><span class="p">:</span>
</span><span class='line'> <span class="k">return</span> <span class="mi">110</span><span class="o">+</span><span class="p">(</span><span class="n">t</span><span class="o">-</span><span class="mi">34</span><span class="p">)</span><span class="o">*</span><span class="mi">10</span>
</span><span class='line'> <span class="k">else</span><span class="p">:</span>
</span><span class='line'> <span class="k">return</span> <span class="mi">255</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">hdd_fan_loop</span><span class="p">():</span>
</span><span class='line'> <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
</span><span class='line'> <span class="n">t</span> <span class="o">=</span> <span class="n">get_hdd_max_temp</span><span class="p">()</span>
</span><span class='line'> <span class="n">pwm</span> <span class="o">=</span> <span class="n">hdd_temp_to_pwm</span><span class="p">(</span><span class="n">t</span><span class="p">)</span>
</span><span class='line'> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">fan_driver</span><span class="o">+</span><span class="s">'pwm3'</span><span class="p">,</span><span class="s">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">fdf</span><span class="p">:</span>
</span><span class='line'> <span class="n">fdf</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">pwm</span><span class="p">))</span>
</span><span class='line'> <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
</span><span class='line'> <span class="k">try</span><span class="p">:</span>
</span><span class='line'> <span class="n">hdd_fan_loop</span><span class="p">()</span>
</span><span class='line'> <span class="k">finally</span><span class="p">:</span>
</span><span class='line'> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">fan_driver</span><span class="o">+</span><span class="s">'pwm3'</span><span class="p">,</span><span class="s">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">fdf</span><span class="p">:</span>
</span><span class='line'> <span class="n">fdf</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">'170'</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">with</span> <span class="n">daemon</span><span class="o">.</span><span class="n">DaemonContext</span><span class="p">():</span>
</span><span class='line'> <span class="n">main</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[ARM & von Neumann]]></title>
<link href="http://chris.elledge.org/blog/2013/09/09/arm-and-von-neumann/"/>
<updated>2013-09-09T19:56:00-04:00</updated>
<id>http://chris.elledge.org/blog/2013/09/09/arm-and-von-neumann</id>
<content type="html"><![CDATA[<p>When the ARM architecture made its way into micro-controllers it also
made the von Neumann architecture more common in firmware
development. The main effect that this has is allowing execution of
instructions from memory. The unified memory model allows jumping into
Flash or RAM. Some processors even load the entire Flash into RAM
before on boot and execute only from RAM. This allows for the
potential to have self modifying code. Which while dangerous from a
safety standpoint, allows for some cool tricks. Sometimes the RAM and
Flash are different speeds which allows either faster execution when
code is in RAM or a shallower pipeline to flush on branches. This
architecture also means that data in Flash can be read as easily and
often as quickly as from RAM and constant structures compile cleanly.</p>
<p>Most ARM micro-controllers support using the ARM Thumb instruction set
which is a subset of the ARM opcodes which only use 16 bits instead of
the normal 32 bits. The reduced instruction set still provides all
operations but limits the number of registers that can be accessed. It
does sometimes require more instructions to do the same work, but for
the most part the code density is much higher in Thumb mode. ARM thumb
instructions can often have even higher density than 8 bit
micro-controllers due to the ability to handle 32 bit math operations
with a single operation.</p>
<p>The addition of ARM also brings lots of options for compilers. GCC,
LLVM, IAR, and several others provide varying levels of support for
micro-controllers and various levels of optimization for the Thumb
instruction set.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Micro-Controller Architecture 102]]></title>
<link href="http://chris.elledge.org/blog/2013/09/08/micro-controller-architecture-102/"/>
<updated>2013-09-08T08:37:00-04:00</updated>
<id>http://chris.elledge.org/blog/2013/09/08/micro-controller-architecture-102</id>
<content type="html"><![CDATA[<p>In addition to the Flash and RAM on the micro-controller, there is a
chunk of address space dedicated to the peripheral registers. These
registers provide the interface to all the peripherals which are
probably the reason that you chose the mirco-controller. There are two
ways that the peripheral registers can be addressed. The first is via
memory access. Usually there is a dedicated hole in the memory space
which addresses these registers instead of RAM. That means that load
and store instructions to these addresses will handle reading and
writing to the peripheral registers.</p>
<p>The second approach is via special instructions. The AVR uses this
approach to access the lowest registers. The intention is for these to
be the most commonly used ones, but it never seems to work out that
way. The limited number of registers that can be accessed this way is
because there are only a few bits available in the opcode to act as
addressing for the instruction. In order to access all the other
registers, they must be addressed by the first approach. On the AVR
this method only take one instruction while the first can take 3. Two
instructions to setup an address pointer and one for the load or store
immediate. Thankfully, the gcc compiler will handle figuring this one
out for you.</p>
<p>The small PICs have their own oddities as well. Instead of using 16
bit addresses to access RAM, they rely on a concept of memory
banks. In order to access memory, a bank has to be set which
determines what memory can be addressed using the load and store
instructions. For each bank, there is a chunk of addresses devoted to
registers, followed by RAM, and a small chunk of common RAM. The
common RAM is the only part that is the same no matter which bank is
selected. Accessing memory that is all in the same bank is compact,
but if several items need to be transfered between pages then a lot of
instructions are wasted shuttling the values between banks.</p>
<p>Typically Flash is read only by the instruction fetcher based off of
the program counter. However when writing to Flash you often need to
consider that it is composed of what are known as blocks and pages. A
block is a chunk of Flash memory which has to be erased as one unit. A
page is a piece of Flash which has to be written as one
unit. Typically a block contains more than one page. If you never plan
on writing self modifying code (bootloaders) then you will probably
never need to worry about this. But if you need to change portions of
the Flash you will need to handle erasing at the block level and
writing at the page level. If you wish to modify only parts of the
Flash, then you will have to store the previous values, erase the
block, and rewrite all the pages.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Micro-Controller Architecture 101]]></title>
<link href="http://chris.elledge.org/blog/2013/09/05/micro-controller-architecture-101/"/>
<updated>2013-09-05T21:35:00-04:00</updated>
<id>http://chris.elledge.org/blog/2013/09/05/micro-controller-architecture-101</id>
<content type="html"><![CDATA[<p>Modern micro-controllers are basically Systems on a Chip (SOC) with
memory integrated into the package as well. The lack of external
memory buses allows for smaller packages and pin counts. It also
greatly simplifies the use of these parts.</p>
<p>Many smaller micros (PIC16, PIC24, AVR) are setup in what is known as
the Harvard Architecture. This means that the executable memory and
data memory are completely separated. Instructions cannot be executed
from the data memory, and the different memory sections can be
addressed in completely different ways.</p>
<p>Usually the executable memory is on Flash or ROM (rarely now
days). While the processor is able to directly fetch instructions from
Flash, there is typically no way to directly read variables from
it. Usually special retrieval instructions or address remapping are
needed. Some compilers will automatically use the constructs for any
constant variable reads.</p>
<p>Furthermore, Flash and RAM don’t even need to have the same line
size. The PIC16F series has 14 bit instruction lines and 8 bit data
lines. The PIC24F series has 24 bit instruction lines and 16 bit data
lines. The AVR has 16 bit instruction lines and 8 bit data lines. The
odd flash word sizes can often make constant storage complicated. The
compilers for the two PICs usually store constants in just the bottom
8 or 16 bits of a line thus wasting big chunks of Flash if you use
lots of constants. If you want to make full use of the storage, you
must use the Flash peripheral registers instead of the simpler address
remapping that the compiler uses. While the alignments are much
cleaner on the AVR, all Flash data reads have to be done with a
special load instruction. So it falls in between the two PIC methods in
complexity.</p>
<p>Details on these operations are a topic for a future post. Next time I will cover Peripheral Registers, Flash Pages, and Memory Banks.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[A Treatise on Firmare Development]]></title>
<link href="http://chris.elledge.org/blog/2013/09/04/a-treatise-on-firmare-development/"/>
<updated>2013-09-04T21:29:00-04:00</updated>
<id>http://chris.elledge.org/blog/2013/09/04/a-treatise-on-firmare-development</id>
<content type="html"><![CDATA[<p>I plan to write several articles on the core concepts of firmware
development and move into more advanced topics. For the simple
concepts I will probably be mostly referring to AVR processors due to
Atmel’s freely available toolchain and their common use in Arduino
designs. As I move into the more advanced concepts I will probably
move on to other processors including various ARM processors.</p>
<h3>Planned Core Concepts</h3>
<ul>
<li>Micro-controller Architectures</li>
<li>Assembly and C Compilers</li>
<li>Registers</li>
<li>Common Peripherals</li>
<li>Interrupts</li>
</ul>
<h3>Planned Advanced Topics</h3>
<ul>
<li>Direct Memory Access</li>
<li>Asynchronous Programming</li>
<li>Real Time Operating Systems</li>
<li>Power Management</li>
<li>Fixed Point Math</li>
</ul>
<p>There are plenty of other resources for getting started with
micro-controller programming for all kinds of chips, so I plan to skip
any kind of introduction to coding in C and examples on getting
started with a particular micro-controller. Instead I will mainly be
going into the theory of operation on these topics in the hope that
with that knowledge it will be easier to take the examples available
in the wild and tame them to your needs. The intended audience is
expected to have a software engineering background.</p>
]]></content>
</entry>
</feed>