Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
Nicolas Pennequin | 357ffb3 | 2008-05-05 10:32:46 +0000 | [diff] [blame] | 10 | * Copyright (C) 2003 by Jörg Hohensohn |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 11 | * |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 12 | * Second-level bootloader, with dual-boot feature by holding F1/Menu |
| 13 | * This is the image being descrambled and executed by the boot ROM. |
| 14 | * It's task is to copy Rockbox from Flash to DRAM. |
| 15 | * The image(s) in flash may optionally be compressed with UCL 2e |
| 16 | * |
Daniel Stenberg | 2acc0ac | 2008-06-28 18:10:04 +0000 | [diff] [blame] | 17 | * This program is free software; you can redistribute it and/or |
| 18 | * modify it under the terms of the GNU General Public License |
| 19 | * as published by the Free Software Foundation; either version 2 |
| 20 | * of the License, or (at your option) any later version. |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 21 | * |
| 22 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 23 | * KIND, either express or implied. |
| 24 | * |
| 25 | ****************************************************************************/ |
| 26 | |
| 27 | #include "sh7034.h" |
| 28 | #include "bootloader.h" |
| 29 | |
Jens Arnold | ca99f8e | 2008-10-12 22:10:22 +0000 | [diff] [blame] | 30 | // prototypes |
| 31 | static void PlatformInit(void); |
Jens Arnold | ca99f8e | 2008-10-12 22:10:22 +0000 | [diff] [blame] | 32 | static void DecompressStart(tImage* pImage); |
| 33 | #ifdef USE_ADC |
| 34 | static int ReadADC(int channel); |
| 35 | #endif |
| 36 | static int ButtonPressed(void); |
| 37 | static tImage* GetStartImage(int nPreferred); |
| 38 | // test functions |
| 39 | static void SetLed(BOOL bOn); |
| 40 | static void UartInit(void); |
| 41 | static UINT8 UartRead(void); |
| 42 | static void UartWrite(UINT8 byte); |
Jens Arnold | e13e318 | 2008-10-30 00:17:45 +0000 | [diff] [blame] | 43 | static void MiniMon(void); |
Jens Arnold | ca99f8e | 2008-10-12 22:10:22 +0000 | [diff] [blame] | 44 | |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 45 | |
| 46 | #ifdef NO_ROM |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 47 | /* start with the vector table */ |
| 48 | UINT32 vectors[] __attribute__ ((section (".vectors"))) = |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 49 | { |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 50 | (UINT32)_main, /* entry point, the copy routine */ |
| 51 | (UINT32)(end_stack - 1), /* initial stack pointer */ |
| 52 | FLASH_BASE + 0x200, /* source of image in flash */ |
| 53 | (UINT32)total_size, /* size of image */ |
| 54 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
| 55 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
| 56 | 0x03020080 /* mask and version (just as a suggestion) */ |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 57 | }; |
| 58 | #else |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 59 | /* our binary has to start with a vector to the entry point */ |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 60 | tpMain start_vector[] __attribute__ ((section (".startvector"))) = {main}; |
| 61 | #endif |
| 62 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 63 | #ifdef NO_ROM /* some code which is only needed for the romless variant */ |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 64 | void _main(void) |
| 65 | { |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 66 | UINT32* pSrc; |
| 67 | UINT32* pDest; |
| 68 | UINT32* pEnd; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 69 | /* |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 70 | asm volatile ("ldc %0,sr" : : "r"(0xF0)); // disable interrupts |
| 71 | asm volatile ("mov.l @%0,r15" : : "r"(4)); // load stack |
| 72 | asm volatile ("ldc %0,vbr" : : "r"(0)); // load vector base |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 73 | */ |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 74 | /* copy everything to IRAM and continue there */ |
| 75 | pSrc = begin_iramcopy; |
| 76 | pDest = begin_text; |
| 77 | pEnd = pDest + (begin_stack - begin_text); |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 78 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 79 | do |
| 80 | { |
| 81 | *pDest++ = *pSrc++; |
| 82 | } |
| 83 | while (pDest < pEnd); |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 84 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 85 | main(); /* jump to the real main() */ |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 86 | } |
| 87 | |
| 88 | |
Jens Arnold | ca99f8e | 2008-10-12 22:10:22 +0000 | [diff] [blame] | 89 | static void BootInit(void) |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 90 | { |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 91 | /* inits from the boot ROM, whether they make sense or not */ |
| 92 | PBDR &= 0xFFBF; /* LED off (0x131E) */ |
| 93 | PBCR2 = 0; /* all GPIO */ |
| 94 | PBIOR |= 0x0040; /* LED output */ |
| 95 | PBIOR &= 0xFFF1; /* LCD lines input */ |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 96 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 97 | /* init DRAM like the boot ROM does */ |
| 98 | PACR2 &= 0xFFFB; |
| 99 | PACR2 |= 0x0008; |
| 100 | CASCR = 0xAF; |
| 101 | BCR |= 0x8000; |
| 102 | WCR1 &= 0xFDFD; |
| 103 | DCR = 0x0E00; |
| 104 | RCR = 0x5AB0; |
| 105 | RTCOR = 0x9605; |
| 106 | RTCSR = 0xA518; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 107 | } |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 108 | #endif /* #ifdef NO_ROM */ |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 109 | |
| 110 | |
| 111 | int main(void) |
| 112 | { |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 113 | int nButton; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 114 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 115 | PlatformInit(); /* model-specific inits */ |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 116 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 117 | nButton = ButtonPressed(); |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 118 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 119 | if (nButton == 3) |
| 120 | { /* F3 means start monitor */ |
| 121 | MiniMon(); |
| 122 | } |
| 123 | else |
| 124 | { |
| 125 | tImage* pImage; |
| 126 | pImage = GetStartImage(nButton); /* which image */ |
| 127 | DecompressStart(pImage); /* move into place and start it */ |
| 128 | } |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 129 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 130 | return 0; /* I guess we won't return ;-) */ |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 131 | } |
| 132 | |
| 133 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 134 | /* init code that is specific to certain platform */ |
Jens Arnold | ca99f8e | 2008-10-12 22:10:22 +0000 | [diff] [blame] | 135 | static void PlatformInit(void) |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 136 | { |
| 137 | #ifdef NO_ROM |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 138 | BootInit(); /* if not started by boot ROM, we need to init what it did */ |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 139 | #endif |
| 140 | |
| 141 | #if defined PLATFORM_PLAYER |
Jens Arnold | 78acda2 | 2004-12-16 22:24:57 +0000 | [diff] [blame] | 142 | BRR1 = 0x19; /* 14400 Baud for monitor */ |
| 143 | PBDRL |= 0x10; /* set PB4 to 1 to power the hd early (and prepare for |
| 144 | * probing in case the charger is connected) */ |
| 145 | PBIORL |= 0x10; /* make PB4 an output */ |
| 146 | PACR2 &= 0xFFFC; /* GPIO for PA0 (charger detection, input by default) */ |
| 147 | if (!(PADRL & 0x01)) /* charger plugged? */ |
| 148 | { /* we need to probe whether the box is able to control hd power */ |
| 149 | int i; |
| 150 | |
| 151 | PBIORL &= ~0x10; /* set PB4 to input */ |
| 152 | /* wait whether it goes low, max. ~1 ms */ |
| 153 | for (i = 0; (PBDRL & 0x10) && i < 1000; i++); |
| 154 | |
| 155 | if (~(PBDRL & 0x10)) /* pulled low -> power controllable */ |
| 156 | PBDRL &= 0x10; /* set PB4 low */ |
| 157 | else /* still floating high -> not controllable */ |
| 158 | PBDRL |= 0x10; /* set PB4 high */ |
| 159 | PBIORL |= 0x10; /* ..and output again */ |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 160 | } |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 161 | #elif defined PLATFORM_RECORDER |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 162 | BRR1 = 0x02; /* 115200 Baud for monitor */ |
| 163 | if (ReadADC(7) > 0x100) /* charger plugged? */ |
| 164 | { /* switch off the HD, else a flat battery may not start */ |
| 165 | PACR2 &= 0xFBFF; /* GPIO for PA5 */ |
| 166 | PAIOR |= 0x0020; /* make PA5 an output (low by default) */ |
| 167 | } |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 168 | #elif defined PLATFORM_FM |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 169 | BRR1 = 0x02; /* 115200 Baud for monitor */ |
| 170 | PBDR |= 0x0020; /* set PB5 to keep power (fixes the ON-holding problem) */ |
| 171 | PBIOR |= 0x0020; /* make PB5 an output */ |
| 172 | if (ReadADC(0) < 0x1FF) /* charger plugged? */ |
| 173 | { /* switch off the HD, else a flat battery may not start */ |
| 174 | PACR2 &= 0xFBFF; /* GPIO for PA5 */ |
| 175 | PAIOR |= 0x0020; /* make PA5 an output (low by default) */ |
| 176 | } |
Jörg Hohensohn | 4e42310 | 2004-09-29 21:54:29 +0000 | [diff] [blame] | 177 | #elif defined PLATFORM_ONDIO |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 178 | BRR1 = 0x19; /* 14400 Baud for monitor */ |
| 179 | PBDR |= 0x0020; /* set PB5 to keep power (fixes the ON-holding problem) */ |
| 180 | PBIOR |= 0x0020; /* make PB5 an output */ |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 181 | #endif |
| 182 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 183 | /* platform-independent inits */ |
| 184 | DCR |= 0x1000; /* enable burst mode on DRAM */ |
| 185 | BCR |= 0x2000; /* activate Warp mode (simultaneous internal and external |
| 186 | * mem access) */ |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 187 | } |
| 188 | |
| 189 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 190 | /* move the image into place and start it */ |
Jens Arnold | ca99f8e | 2008-10-12 22:10:22 +0000 | [diff] [blame] | 191 | static void DecompressStart(tImage* pImage) |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 192 | { |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 193 | UINT32* pSrc; |
| 194 | UINT32* pDest; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 195 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 196 | pSrc = pImage->image; |
| 197 | pDest = pImage->pDestination; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 198 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 199 | if (pSrc != pDest) /* if not linked to that flash address */ |
| 200 | { |
| 201 | if (pImage->flags & IF_UCL_2E) |
| 202 | { /* UCL compressed, algorithm 2e */ |
| 203 | UINT32 dst_len; /* dummy */ |
| 204 | ucl_nrv2e_decompress_8((UINT8*)pSrc, (UINT8*)pDest, &dst_len); |
| 205 | } |
| 206 | else |
| 207 | { /* uncompressed, copy it */ |
| 208 | UINT32 size = pImage->size; |
| 209 | UINT32* pEnd; |
| 210 | size = (size + 3) / 4; /* round up to 32bit-words */ |
| 211 | pEnd = pDest + size; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 212 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 213 | do |
| 214 | { |
| 215 | *pDest++ = *pSrc++; |
| 216 | } |
| 217 | while (pDest < pEnd); |
| 218 | } |
| 219 | } |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 220 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 221 | pImage->pExecute(); |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 222 | } |
| 223 | |
Jens Arnold | b8b94f1 | 2004-11-19 23:49:21 +0000 | [diff] [blame] | 224 | #ifdef USE_ADC |
Jens Arnold | ca99f8e | 2008-10-12 22:10:22 +0000 | [diff] [blame] | 225 | static int ReadADC(int channel) |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 226 | { |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 227 | /* after channel 3, the ports wrap and get re-used */ |
| 228 | volatile UINT16* pResult = (UINT16*)(ADDRAH_ADDR + 2 * (channel & 0x03)); |
| 229 | int timeout = 266; /* conversion takes 266 clock cycles */ |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 230 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 231 | ADCSR = 0x20 | channel; /* start single conversion */ |
| 232 | while (((ADCSR & 0x80) == 0) && (--timeout)); /* 6 instructions per round*/ |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 233 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 234 | return (timeout == 0) ? -1 : *pResult>>6; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 235 | } |
Jens Arnold | b8b94f1 | 2004-11-19 23:49:21 +0000 | [diff] [blame] | 236 | #endif |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 237 | |
| 238 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 239 | /* This function is platform-dependent, |
| 240 | * until I figure out how to distinguish at runtime. */ |
Jens Arnold | ca99f8e | 2008-10-12 22:10:22 +0000 | [diff] [blame] | 241 | static int ButtonPressed(void) /* return 1,2,3 for F1,F2,F3, 0 if none pressed */ |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 242 | { |
Jens Arnold | b8b94f1 | 2004-11-19 23:49:21 +0000 | [diff] [blame] | 243 | #ifdef USE_ADC |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 244 | int value = ReadADC(CHANNEL); |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 245 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 246 | if (value >= F1_LOWER && value <= F1_UPPER) /* in range */ |
| 247 | return 1; |
| 248 | else if (value >= F2_LOWER && value <= F2_UPPER) /* in range */ |
| 249 | return 2; |
| 250 | else if (value >= F3_LOWER && value <= F3_UPPER) /* in range */ |
| 251 | return 3; |
Jens Arnold | b8b94f1 | 2004-11-19 23:49:21 +0000 | [diff] [blame] | 252 | #else |
| 253 | int value = PCDR; |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 254 | |
Jens Arnold | b8b94f1 | 2004-11-19 23:49:21 +0000 | [diff] [blame] | 255 | if (!(value & F1_MASK)) |
| 256 | return 1; |
| 257 | else if (!(value & F2_MASK)) |
| 258 | return 2; |
| 259 | else if (!(value & F3_MASK)) |
| 260 | return 3; |
| 261 | #endif |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 262 | |
| 263 | return 0; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 264 | } |
| 265 | |
| 266 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 267 | /* Determine the image to be started */ |
Jens Arnold | ca99f8e | 2008-10-12 22:10:22 +0000 | [diff] [blame] | 268 | static tImage* GetStartImage(int nPreferred) |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 269 | { |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 270 | tImage* pImage1; |
| 271 | tImage* pImage2 = NULL; /* default to not present */ |
| 272 | UINT32 pos; |
| 273 | UINT32* pFlash = (UINT32*)FLASH_BASE; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 274 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 275 | /* determine the first image position */ |
| 276 | pos = pFlash[2] + pFlash[3]; /* position + size of the bootloader |
| 277 | * = after it */ |
| 278 | pos = (pos + 3) & ~3; /* be sure it's 32 bit aligned */ |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 279 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 280 | pImage1 = (tImage*)pos; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 281 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 282 | if (pImage1->size != 0) |
| 283 | { /* check for second image */ |
| 284 | pos = (UINT32)(&pImage1->image) + pImage1->size; |
| 285 | pImage2 = (tImage*)pos; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 286 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 287 | /* does it make sense? (not in FF or 00 erazed space) */ |
| 288 | if (pImage2->pDestination == (void*)0xFFFFFFFF |
| 289 | || pImage2->size == 0xFFFFFFFF |
| 290 | || pImage2->pExecute == (void*)0xFFFFFFFF |
| 291 | || pImage2->flags == 0xFFFFFFFF |
| 292 | || pImage2->pDestination == NULL) |
| 293 | /* size, execute and flags can legally be 0 */ |
| 294 | { |
| 295 | pImage2 = NULL; /* invalidate */ |
| 296 | } |
| 297 | } |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 298 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 299 | if (pImage2 == NULL || nPreferred == 1) |
| 300 | { /* no second image or overridden: return the first */ |
| 301 | return pImage1; |
| 302 | } |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 303 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 304 | return pImage2; /* return second image */ |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 305 | } |
| 306 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 307 | /* diagnostic functions */ |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 308 | |
Jens Arnold | ca99f8e | 2008-10-12 22:10:22 +0000 | [diff] [blame] | 309 | static void SetLed(BOOL bOn) |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 310 | { |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 311 | if (bOn) |
| 312 | PBDR |= 0x0040; |
| 313 | else |
| 314 | PBDR &= ~0x0040; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 315 | } |
| 316 | |
| 317 | |
Jens Arnold | ca99f8e | 2008-10-12 22:10:22 +0000 | [diff] [blame] | 318 | static void UartInit(void) |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 319 | { |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 320 | PBIOR &= 0xFBFF; /* input: RXD1 remote pin */ |
| 321 | PBCR1 |= 0x00A0; /* set PB11+PB10 to UART */ |
| 322 | PBCR1 &= 0xFFAF; /* clear bits 6, 4 -> UART */ |
| 323 | SMR1 = 0x00; /* async format 8N1, baud generator input is CPU clock */ |
| 324 | SCR1 = 0x30; /* transmit+receive enable */ |
| 325 | PBCR1 &= 0x00FF; /* set bit 12...15 as GPIO */ |
| 326 | SSR1 &= 0xBF; /* clear bit 6 (RDRF, receive data register full) */ |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 327 | } |
| 328 | |
| 329 | |
Jens Arnold | ca99f8e | 2008-10-12 22:10:22 +0000 | [diff] [blame] | 330 | static UINT8 UartRead(void) |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 331 | { |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 332 | UINT8 byte; |
| 333 | while (!(SSR1 & SCI_RDRF)); /* wait for char to be available */ |
| 334 | byte = RDR1; |
| 335 | SSR1 &= ~SCI_RDRF; |
| 336 | return byte; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 337 | } |
| 338 | |
| 339 | |
Jens Arnold | ca99f8e | 2008-10-12 22:10:22 +0000 | [diff] [blame] | 340 | static void UartWrite(UINT8 byte) |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 341 | { |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 342 | while (!(SSR1 & SCI_TDRE)); /* wait for transmit buffer empty */ |
| 343 | TDR1 = byte; |
| 344 | SSR1 &= ~SCI_TDRE; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 345 | } |
| 346 | |
| 347 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 348 | /* include the mini monitor as a rescue feature, started with F3 */ |
Jens Arnold | ca99f8e | 2008-10-12 22:10:22 +0000 | [diff] [blame] | 349 | static void MiniMon(void) |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 350 | { |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 351 | UINT8 cmd; |
| 352 | UINT32 addr; |
| 353 | UINT32 size; |
| 354 | UINT32 content; |
| 355 | volatile UINT8* paddr = NULL; |
| 356 | volatile UINT8* pflash = NULL; /* flash base address */ |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 357 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 358 | UartInit(); |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 359 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 360 | while (1) |
| 361 | { |
| 362 | cmd = UartRead(); |
| 363 | switch (cmd) |
| 364 | { |
| 365 | case BAUDRATE: |
| 366 | content = UartRead(); |
| 367 | UartWrite(cmd); /* acknowledge by returning the command value */ |
| 368 | while (!(SSR1 & SCI_TEND)); /* wait for empty shift register, |
| 369 | * before changing baudrate */ |
| 370 | BRR1 = content; |
| 371 | break; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 372 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 373 | case ADDRESS: |
| 374 | addr = (UartRead() << 24) | (UartRead() << 16) |
| 375 | | (UartRead() << 8) | UartRead(); |
| 376 | paddr = (UINT8*)addr; |
| 377 | pflash = (UINT8*)(addr & 0xFFF80000); /* round down to 512k align*/ |
| 378 | UartWrite(cmd); /* acknowledge by returning the command value */ |
| 379 | break; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 380 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 381 | case BYTE_READ: |
| 382 | content = *paddr++; |
| 383 | UartWrite(content); /* the content is the ack */ |
| 384 | break; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 385 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 386 | case BYTE_WRITE: |
| 387 | content = UartRead(); |
| 388 | *paddr++ = content; |
| 389 | UartWrite(cmd); /* acknowledge by returning the command value */ |
| 390 | break; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 391 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 392 | case BYTE_READ16: |
| 393 | size = 16; |
| 394 | while (size--) |
| 395 | { |
| 396 | content = *paddr++; |
| 397 | UartWrite(content); /* the content is the ack */ |
| 398 | } |
| 399 | break; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 400 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 401 | case BYTE_WRITE16: |
| 402 | size = 16; |
| 403 | while (size--) |
| 404 | { |
| 405 | content = UartRead(); |
| 406 | *paddr++ = content; |
| 407 | } |
| 408 | UartWrite(cmd); /* acknowledge by returning the command value */ |
| 409 | break; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 410 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 411 | case BYTE_FLASH: |
| 412 | content = UartRead(); |
| 413 | pflash[0x5555] = 0xAA; /* set flash to command mode */ |
| 414 | pflash[0x2AAA] = 0x55; |
| 415 | pflash[0x5555] = 0xA0; /* byte program command */ |
| 416 | *paddr++ = content; |
| 417 | UartWrite(cmd); /* acknowledge by returning the command value */ |
| 418 | break; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 419 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 420 | case BYTE_FLASH16: |
| 421 | size = 16; |
| 422 | while (size--) |
| 423 | { |
| 424 | content = UartRead(); |
| 425 | pflash[0x5555] = 0xAA; /* set flash to command mode */ |
| 426 | pflash[0x2AAA] = 0x55; |
| 427 | pflash[0x5555] = 0xA0; /* byte program command */ |
| 428 | *paddr++ = content; |
| 429 | } |
| 430 | UartWrite(cmd); /* acknowledge by returning the command value */ |
| 431 | break; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 432 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 433 | case HALFWORD_READ: |
| 434 | content = *(UINT16*)paddr; |
| 435 | paddr += 2; |
| 436 | UartWrite(content >> 8); /* highbyte */ |
| 437 | UartWrite(content & 0xFF); /* lowbyte */ |
| 438 | break; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 439 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 440 | case HALFWORD_WRITE: |
| 441 | content = UartRead() << 8 | UartRead(); |
| 442 | *(UINT16*)paddr = content; |
| 443 | paddr += 2; |
| 444 | UartWrite(cmd); /* acknowledge by returning the command value */ |
| 445 | break; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 446 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 447 | case EXECUTE: |
| 448 | { |
| 449 | tpFunc pFunc = (tpFunc)paddr; |
| 450 | pFunc(); |
| 451 | UartWrite(cmd); /* acknowledge by returning the command value*/ |
| 452 | } |
| 453 | break; |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 454 | |
Jens Arnold | 4b3501f | 2004-12-03 21:43:21 +0000 | [diff] [blame] | 455 | case VERSION: |
| 456 | UartWrite(1); /* return our version number */ |
| 457 | break; |
| 458 | |
| 459 | default: |
| 460 | { |
| 461 | SetLed(TRUE); |
| 462 | UartWrite(~cmd); /* error acknowledge */ |
| 463 | } |
| 464 | |
| 465 | } /* case */ |
| 466 | } /* while (1) */ |
Jörg Hohensohn | 6a4e4c8 | 2003-11-30 11:37:43 +0000 | [diff] [blame] | 467 | } |