Page heading
Headline
upgrade files mappings in flash
unicode.sys contains fonts bitmaps (bytes are swapped) - low byte goes to page, high byte goes to page-1. On coldstart this file is loaded to 0x30E00000
HD200TBL.sys - not present in upgrade files archives but there are routines to write content of this file to 0x00105000 - 0x00144FFF in flash
HD200ICON.sys contains icons (small one and fullscreen frames). This file is copied to flash 0x00145000 - 0x001F4FFF.
HD200_UPG.SYS is the main firmware file. During upgrade it is written to flash 0x00000000 - 0x000FFFFF
Looking at flash write routines there is "memory hole" in flash 0x100000 - 0x104A00 - there is no routine writing to this location. However string printing routines reads fonts bitmaps for wchar less than 0x24F there so this must be programmed in factory and never touched.
Last two sectors of flash are used to save some config settings (and resume data)
Start sequence
I have started the dissasembly of firmware upgrade files. The file HD200_UPG.SYS (1.30.05) looks promising. After short initialization routines the code from flash is copied to dram and sram according to the table below. Then program jumps to the entry point located in dram.
source |
destination |
length (words) |
0xb0a-0xf09 |
0x10000000-0x100003FF |
0x200 |
0xf0a-0x16a1 |
0x10000400-0x10000b97 |
0x3cc |
0x16a2-0x1b6b |
0x10000ba0-0x10001069 |
0x265 |
0x1b6c-0x1fcf |
0x100010f0-0x10001553 |
0x232 |
0x1fd0-0x6b9b |
0x100066e0-0x1000b2ab |
0x25e6 |
0x6b9c-0xa6d3 |
0x1000b2ac-0x1000ede3 |
0x1d9c |
|
|
|
0xa6d4-0xc3eb |
0x30BE3C20-0x30BE5937 |
0xe8c |
0xC3EC-0x4b1f7 |
0x30BE5938-0x30c24743 |
0x1f706 |
0x4B1F8-0x6c6e3 |
0x30C24744-0x30C45c2f |
0x10a76 |
0x6C6E4-0x6d503 |
0x30C45C30-0x30C46a4f |
0x710 |
0x6D504-0x6f01b |
0x30C46A50-0x30c48567 |
0xd8c |
0x6f01c-0x72561 |
0x30c48a70-0x30c4bfb5 |
0x1aa3 |
0x72562-0x7a0dc |
0x30c4e361-0x30c55eda |
0x3dbd + 1byte |
0x7a0dd-0x7af14 |
0x30c55ee0-0x30c56d17 |
0x71c |
0x7af15-0x7bc78 |
0x30c56d20-0x30c57a83 |
0x6b2 |
0x7bc79-0x7e78a |
0x30c57a90-0x30c5a5a1 |
0x1589 |
0x7e78b-0x807e2 |
0x30c5a5b0-0x30c5c607 |
0x102c |
0x807e3-0x81bfa |
0x30c5c610-0x30c5da27 |
0xa0c |
0x81bfb-0x82d3e |
0x30c5da30-0x30c5eb73 |
0x8a2 |
0x82d3f-0x86c3e |
0x30c5eb80-0x30c62a7f |
0x1f80 |
0x86c3f-0x93ace |
0x30c62a80-0x30c6e40f |
0x6748 |
0x92e33-0xb1d20 |
0x30c6e410-0x30c70afd |
0xf777 |
0x95921-0x963f4 |
0x30c70b00-0x30c715d3 |
0x56a |
|
|
|
0x95ff5-0x9a002 |
0x100066e0-0x1000a6ed |
0x2007 |
0x9a003-0x9b0da |
0x1000f60c-0x100106e3 |
0x86c |
|
|
|
0x980db-0xaf016 |
0x30c75b80-0x30c8cabb |
0xb79e |
0xb2017-0xb25e2 |
0x30c8cac0-0x30c8d08b |
0x2e6 |
Memory map
address range |
length (bytes) |
description |
0x00000000-0x001FFFFF |
0x200000 |
chip select 0 (2MB Flash) |
0x10000000-0x1000FFFF |
0x10000 |
sram1 64k |
0x10010000-0x10017FFF |
0x8000 |
sram0 32k |
0x30000000-0x30FFFFFF |
0x1000000 |
sdram 16M |
0x40000000 |
|
mbar |
0x50000000 |
|
chip select 3 (LCD) |
0x60000000 |
|
chip select 2 (IDE) |
0x80000000 |
|
mbar2 |
exception vector table is located in sram 0x10000000-0x100003FF
LCD initialization
The LCD initialization routine (0x30BF81A0) looks consistent with datasheet: First we have setting GPO34 low, delay, setting GPO34 high which I think is hardware reset sequence. Than we write to CS3
opcode |
description |
0xE2 |
reset |
0x48 0x80 |
duty ratio 1/128 |
0xA0 |
select ADC normal |
0xC0 |
select SHL normal |
0x44 0x00 |
set COM0 = 0x00 |
0xAB |
osc. on |
0x67 |
DC-DC boost 6x |
0x27 |
select regulator resistor 7.2 |
0x81 0x1B |
select volume 0x1B |
0x56 |
select LCD bias 1/11 |
0x96 |
select 3 FRC, 12 PWM |
0x34 0x00 |
??? |
0x1A |
??? |
0x88 0x00 |
set gray 0 |
0x89 0x00 |
set gray 1 |
0x8A 0x0C |
set gray 2 |
0x8B 0x00 |
set gray 3 |
0x8C 0xC4 |
set gray 4 |
0x8D 0x00 |
set gray 5 |
0x8E 0xCC |
set gray 6 |
0x8F 0x00 |
set gray 7 |
0x2F |
power on all circuits |
0xAF |
display on |
display is flipped i.e page 0x0f column 0 is left upper corner
GPIOs
GPIO0 |
GPIO1 |
Port pin |
I/O/F |
E |
Description |
Port pin |
I/O/F |
E |
Description |
0 |
F |
0 |
DDATA0 |
32 (0) |
F |
0 |
Unassigned |
1 |
F |
0 |
DDATA1 |
33 (1) |
F* |
0 |
TIN0/TOUT0 |
2 |
F |
0 |
DDATA2 |
34 (2) |
O |
1 |
LCD Reset line (goes low on line in jack insert?) T |
3 |
F |
0 |
SCL1 (second I2C clock) |
35 (3) |
F |
0 |
TOUT1/ADOUT |
4 |
F |
0 |
DDATA3 |
36 (4) |
I/O* |
1 |
in: main hold (active high) out: reset of the GL811E usb bridge (low = reset state) |
5 |
I/O |
0 |
|
37 (5) |
I/O* |
0 |
ATA_BSY line??? |
6 |
F |
0 |
|
38 (6) |
F* |
0 |
ADC input0 (remote keys) (goes low on headphone insert) T |
7 |
F |
0 |
SDRAMCS2 |
39 (7) |
F* |
0 |
in: ADC input1 (internal keys) out: MCLK1 |
8 |
F |
0 |
A[25] |
40 (8) |
F |
0 |
/OE |
9 |
I |
0 |
Battery fault (low) (TLC1733 /FAULT) |
41 (9) |
F* |
0 |
in: remote key PLAY out: Audio Serial Data |
10 |
F |
0 |
SCLK (SDRAM clock output) |
42 (10) |
F* |
0 |
in: USB connect (active low) T out: MCLK2 (delivered to WM8750) |
11 |
F |
0 |
CS3 |
43 (11) |
F |
0 |
Unassigned |
12 |
F |
0 |
/SWE |
44 (12) |
F |
0 |
Audio Word Clock |
13 |
F |
0 |
IDE-DIOR |
45 (13) |
F |
0 |
LRCK3 |
14 |
F |
0 |
IDE-DIOW |
46 (14) |
I |
0 |
Wall Charger connect (active low) (LTC1733 /ACPR) T |
15 |
O |
1 |
configures charging current limit (low = 100 mA, high = ?) |
47 (15) |
F |
0 |
Unassigned |
16 |
F |
0 |
IDE-IORDY |
48 (16) |
F |
0 |
Audio Serial Bit Clock |
17 |
F |
0 |
BUFENB2 |
49 (17) |
O |
1 |
FM power (low=ON) |
18 |
F |
0 |
CFLAG |
50 (18) |
O |
1 |
IDE power (low = ON) When on power consumption is increased by more than 100mA! |
19 |
O |
1 |
ATA reset line (with 10k pullup to ide power line). Connected also to GL811E GPIO7 pin which according to the docs is ATA reset input (whatever it means) |
51 (19) |
F |
0 |
RCK (subcode clock) |
20 |
F |
0 |
TA |
52 (20) |
F |
0 |
SFSY |
21 |
F |
0 |
QSPICS2 |
53 (21) |
O |
1 |
set high on startup, set low on shutdown |
22 |
O |
1 |
USB related - 0 - enter usb-bridge 1 - leave usb-bridge this is connected through buffer with GL811E DGND pin *** |
54 (22) |
I |
0 |
goes low on Wall Charger connect T |
23 |
O |
0/1 |
Connected to LTC1733 PROG pin. Pulling this up and then tristate restarts charging cycle |
55 (23) |
F |
0 |
SDA1 second I2C serial data line |
24 |
F |
0 |
QSPICS1 |
56 (24) |
I |
0 |
internal key PLAY (active high) T |
25 |
F |
0 |
SDATAO1 audio data serial out |
57 (25) |
F/O |
1 |
headphone out enable (active high) |
26 |
I |
0 |
? |
58 (26) |
F |
0 |
/CS1 |
27 |
F* |
0 |
TXD0 + RXD0 |
59 (27) |
F |
0 |
PST0 |
28 |
I/O* |
1 |
in: ADC input2 (battery level) out: backlight** |
60 (28) |
F |
0 |
PST1 |
29 |
O |
1 |
? |
61 (29) |
F |
0 |
PST2 |
30 |
I/O* |
1 |
in: Battery charging (high)/Battery full (low) (LTC1733 /CHRG) out: USB related? out pin is driving transistor which connects GL811E DVCC to power rail *** |
62 (30) |
F |
0 |
PST3 |
31 |
I/O* |
1 |
in: ADC input3 (this pin flips irregulary) T out: low is needed to ATA work properly (set once at startup) |
63 (31) |
F |
0 |
PSTCLK |
T means it was tested with simple code injected into test mode (assignment of F/I/O and E comes mostly from this readings also)
"*" indicates that this GPIO or function is actually implemented by two pins on the physical package -- one dedicated input pin and one dedicated output. This means that this logical bit can serve two functions simultaneously. There's only one bit that decides function vs. GPIO, so the composite pin must either both be function pins or a GPI and GPO pin.
Notes: pulling GPO53 low when on battery turns off device immediately (Like hardware reset button).
"**" - Pulling GPO28 low turns off backlight. To turn it on again it is necessary to produce some waveform. Basically it is GPO28 low, delay, n times (GPO28 high, GPO28 low), GPO28 high. I am unable to reproduce this correctly. If I use calls to OF functions toggling GPIO bits it works. Mybe this is some timing issue? The brightness of backlight is related to how many high to low transtions of GPO28 was made. OF firmware uses 20 transitions.Edit: running the same procedure in rockbox bootloader works.
"***" - checked after desoldering MCU and
LD245A buffer from defective HD300 mainboard. Dissasembly reveals that both players share the same code for USB handling
Battery charging
Charging is done by LTC1733 chip. It charges with 100mA current (15k Ohm PROG resistor) and with 6 hours timeout (0.2 uF TIME capacitor). GPIO23 is connected to the LTC1733 PROG pin and is high by default (which puts chip into shutdown mode). Charging cycle starts when GPIO23 is tristated. GPIO15 set charging current limit - low = 100mA, high = (The biggest reading I saw on multimeter was 180mA). End of charging condition is signaled by pulling high GPIO30. Error condition is signaled on GPIO9 pin.
Key reading
5249 ADC is used. Input1 is for internal buttons, and Input0 probably for remote. Below are values taken from dissasembly and crosschecked with "Test mode". The bitflag describes return value of the "read_keys()" subroutine in OF. One can see that flags for internal keys are in low word and for remote are in high word.
ADC1 values |
internal key |
bitflag |
200-500 |
REC |
0x00000020 |
550-850 |
VOL- |
0x00000010 |
900-1200 |
VOL+ |
0x00000008 |
1250-1550 |
NEXT |
0x00000002 |
1600-1900 |
PREV |
0x00000004 |
1950-2250 |
SELECT |
0x00002000 |
ADC0 values |
remote key |
bitflag |
230-370 |
VOL- |
0x00100000 |
480-620 |
VOL+ |
0x00080000 |
830-970 |
NEXT |
0x00020000 |
1230-1370 |
PREV |
0x00040000 |
1930-2070 |
SELECT |
0x80000000 |
44 |
HOLD |
? |
In the same routine GPIO56 high produces flag 0x00000001 and GPIO41 produces flag 0x00010000 which is PLAY signal (main and remote respectively).
battery level reading
ADC2 is related to battery level. In firmware there are some flags assigned based on reading from ADC. ADC is read 20 times, than we take mean value of 10 biggest readings and based on this battery level is determined. In other battery related subroutine moving average filter with 20 readings window and ramping is used. Voltages ware measured by hooking external power supply to the connector instead of the battery. Current draw is 70-80 mA for idle and 120-160 mA when playing music. Backlight contribution is about 20mA.
ADC2 values |
flag |
voltage [V] |
<2250 |
low battery |
<3.70 |
2250-2280 |
6 |
3.70 - 3.75 |
2280-2330 |
5 |
3.75 - 3.85 |
2330-2450 |
4 |
3.85 - 4.05 |
>2450 |
3 |
>4.05 |
Charger connected |
1 |
- |
USB sequence
This GPIO toggling sequence is present in a few subroutines in OF related to USB handling:
Enable USB brdge |
Disable USB bridge |
GPO 50 high |
GPO22 high |
GPO30 low |
GPO30 high |
GPO36 low |
GPO36 low |
delay 10ms |
GPO22 high |
GPO36 high |
GPO50 high |
GPO50 low |
|
GPO19 high |
|
GPO22 low |
|
running code
Today (13.11.2009) i fired up my first few lines of code on this device. This was simple 'Hello world'. I injected assembled code into TEST mode subroutines. I poked around and found out unfortunately that unicode.sys which is loaded on coldstart to 0x30E00000 is not preserved there or is not there yet (at least when entering TEST mode). This leaves only few kB of safe code space in TEST mode subroutines to inject my own code.
Debug port
There is unpopulated ZIF/FPC 20-pin connector between battery connector and headphones connector. It is probably BDM port. Here I will try to document my attempt to find proper wiring:
Pins |
Function |
Notes |
3,8,17 |
GND |
mulitmeter |
6, 19 |
VCCIO |
multimeter |
4 |
/RESET |
multimeter - hardware reset switch pulls this line down |
12,11,10,9 |
PST[0:3] |
osciloscope |
16,15,14,13 |
DDATA[0:3] |
run program which generate square wave on this pins and look with scope |
18 |
PSTCLK |
osciloscope |
1 |
/BKPT |
tested |
2 |
DSCLK |
tested |
5 |
DSI |
tested |
7 |
DSO |
tested |
20 |
TA |
last one left |
By trials I mean put CPU in HALT mode and than setup transmission for GO command and change lines until processor leaves HALT mode. In theory this should work.
edit: 13.01.2010 This works :-). I am able to HALT cpu and resume it. This is BIG step forward because this makes messing with bootloader quite safe.
edit: 19.02.2010 I finaly got PCB for tblcf pod. Thanks to the
http://bdm.sourceforge.net I was able to combine BDM and gdb together. Now I have to gain some more practice with gdb.
Tools
- hd200icon is small and dirty utility to examine HD200ICON.sys file. It displays graphics stored insied the file (using SDL), prints offset to the stdout and optionaly can save 'screenshot' of hd200 graphic. Fullscreen frames extracted with this utility are collected in hd200_icons.zip
- binpatch small utility to insert binary inside another binary at specified offset. Now obsoleted by mkmpioboot which automates patching firmware file
- flash2dram is utility which prints mappings flash<->dram/iram. It is handy in dissasembly to see where particular function from flash is loaded into ram.
Copyright © by the contributing authors.