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
|
(post
:title "Disassembling the Wavedrum firmware"
:date (string->date* "2014-09-18 00:00")
:tags '("DIY" "electronics" "music" "hacking" "wavedrum" "SHARC")
(p [The Wavedrum’s processing unit is an ADSP-21375 by Analog Devices,
a member of the SHARC processor family. The firmware of the
Wavedrum, which is stored on a micro SD-card and, more
importantly, on the flash memory chip is loaded into the processor
during the boot process.])
(p [,(ref "2013-12-09-wavedrum-connectors.html" "Last time") I
confirmed by tracing the connections of the two boot pins that the
processor is wired to boot from EPROM/Flash (,(code [BOOT_CFG1-0 =
10])). I’m too lazy to try to verify that the firmware on the
micro SD-card is identical to the contents of the flash memory, so
I’ll just assume that this is the case.])
;; TODO: link to hardware reference is dead
(p [When the processor is initially powered on, the internal memory is
in an undefined state. According to the ,(ref
"http://www.analog.com/static/imported-files/processor_manuals/ADSP-21367_hwr_rev2-1.pdf"
"ADSP hardware reference") (section 17-7 ,(em [Processor
Booting])), the processor core is put into ,(code [IDLE]) mode
while loading the boot kernel from an external source (in our case
this is the flash memory) into the internal memory at address
0x90000 (,(code [IVT_START_ADDR])), and finally executes the boot
kernel code when a peripheral interrupt signals that the kernel
has been loaded. Then the application code is loaded from the
memory and finally the application’s Interrupt Vector Table (IVT)
is loaded. The boot kernel is 256 48-bit words long, as is the
IVT. The application code is of arbitrary length.])
(h2 [Word packing])
(p [The boot kernel is exactly 256 48-bit words long (shorter kernels
are padded with NOPs), but the words are not transferred as 48-bit
words. The boot kernel is transferred from the external memory as
a stream of 384 “packed” 32-bit words (see table 17-6 in the
hardware reference). To understand packing we have to know that
conceptionally the internal memory consists of many rows of four
columns, each of which is 16 bit wide. Accessing 48-bit words is
often referred to as 3-column access in the reference, whereas
accessing 32-bit words is called 2-column access. All of the
SHARC instructions are 48 bit wide. This means that any 32-bit
wide package never contains the full instruction. Dependent on
the order of the packages, the 48-bit words can be reconstructed
from a stream of 32-bit words.])
(p [Here’s the original explanation in the hardware reference on page
17-27:])
(blockquote (p [During the boot process, word packing (for example 8
to 32-bit) is performed over the SPI. In other words,
the kernel is not loaded directly with 256 x 48-bit
words, instead it is loaded with 384 x 32-bit ‘packed
words’ (2-column access). The same physical memory for
instruction boot is loaded via DMA in normal word (NW)
2 column. However, after booting the same physical
memory region is fetched by the sequencer in NW
3-column. For example the loader kernel itself has a
NW 2 columns count of 256 x 3/2 = 384 words but the
kernel is executed with 256 instruction fetches.]))
(p [When booting from external memory the bus width is set to 8 bits.
According to the ,(ref
"http://www.analog.com/static/imported-files/processor_manuals/ADSP-21367_hwr_rev2-1.pdf"
"ADSP hardware reference") (section “External Port Booting”), the
processor reads a stream of 8-bit words from the data port and
packs four of them into 32-bit words (LSB first) before storing
them into the internal memory.])
(p [Figure 17-5 in the hardware reference visualises this process
rather nicely. It shows how streams of different word sizes end
up being stored in the internal memory.])
(wide-img "2014/wavedrum-word-packing.png" "word packing")
(p [Once I understood that words are transferred from the memory in
8-bit chuncks with the LSB first, writing a disassembler that
would translate the binary boot kernel into assembly code was no
longer very challenging.])
(h2 [A free disassembler for ADSP-213xx])
(p [I implemented a simple tool in Haskell that takes a binary
firmware and spits out assembly code for the ADSP. At the moment
it only supports a limited set of instructions, just enough so
that I could translate the boot kernel. The remainder of the
instructions will be implemented later as I happen to encounter
them in the application code.])
(p [It currently only parses the first 256 words of the firmware,
i.e. only the boot kernel. Before I can parse the remainder I
need to figure out the memory layout.])
(p [The code is freely available under the ,(ref
"http://www.gnu.org/licenses/#GPL" "GPL") and can be ,(ref
"http://git.elephly.net/wavedrum/sharc-disassembler.git"
"downloaded here"). See the included instructions for assistance
in compiling and using the disassembler.])
(h2 [Next steps])
(p [My work isn’t over yet. Next I’ll focus on the following tasks:])
(ul
(li [figure out how the boot kernel loads the application code into
the processor])
(li [disassemble (parts of) the application code])
(li [look out for snippets that involve loading code from the
micro-SD card to the flash memory, because that’s our ticket to
upgrade the firmware easily]))
(p [If you want to help me, I’d be happy if you could send me a copy
of the Global Edition’s firmware. To do this you only need to
take out the micro SD-card and create a disk image of it. (On
GNU/Linux this can easily be done with ,(code [dd]) on the command
line; see ,(ref
"/posts/2013-08-11-hacking-the-wavedrum.html"
"my first post on hacking the Wavedrum") for more detailed
instructions.)])
(p [I would also be very grateful for code reviews and patches.
Translating the various specifications into executable code wasn’t
always easy and I’m sure there are bugs in the code here and
there.])
(p [Read ,(ref "/tags/wavedrum.html" "more posts
about the Wavedrum here").]))
|