forked from len0rd/rockbox
source code for all my flash stuff, now finally in cvs
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4083 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
014c4fa1f8
commit
6a4e4c87c2
29 changed files with 3349 additions and 1 deletions
|
|
@ -1 +1,7 @@
|
|||
Readme
|
||||
(c) 2003 by Jörg Hohensohn
|
||||
|
||||
Sourcecode for the flash "infrastructure"
|
||||
Please bear in mind that these are powerful tools, don't fool with them!
|
||||
|
||||
For most up-to-date info about flashing see:
|
||||
http://rockbox.haxx.se/docs/flash.html
|
||||
|
|
|
|||
78
flash/bootloader/Makefile
Normal file
78
flash/bootloader/Makefile
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
# __________ __ ___.
|
||||
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
# \/ \/ \/ \/ \/
|
||||
# $Id$
|
||||
#
|
||||
|
||||
CC = sh-elf-gcc
|
||||
LD = sh-elf-ld
|
||||
AR = sh-elf-ar
|
||||
AS = sh-elf-as
|
||||
OC = sh-elf-objcopy
|
||||
|
||||
FIRMWARE := ../../firmware
|
||||
TOOLSDIR=../../tools
|
||||
|
||||
TARGET = bootloader
|
||||
LDS := $(TARGET).lds
|
||||
|
||||
|
||||
ifndef PLATFORM
|
||||
not_configured:
|
||||
@echo "No platform given."
|
||||
@echo "Use make PLATFORM=PLAYER|RECORDER|RECORDER|FM {NO_ROM=1}"
|
||||
##else
|
||||
##configured:
|
||||
## @echo "Building bootloader for platform "$(PLATFORM)
|
||||
endif
|
||||
|
||||
|
||||
INCLUDES= -I$(FIRMWARE)/export -I. -I$(OBJDIR)
|
||||
DEFINES= -DPLATFORM_$(PLATFORM)
|
||||
|
||||
OBJDIR := .
|
||||
|
||||
CFLAGS = -O -W -Wall -m1 -nostdlib -ffreestanding -Wstrict-prototypes -fomit-frame-pointer -fschedule-insns $(INCLUDES) $(DEFINES)
|
||||
AFLAGS += -small -relax
|
||||
|
||||
|
||||
ifdef DEBUG
|
||||
DEFINES := -DDEBUG
|
||||
CFLAGS += -g
|
||||
endif
|
||||
|
||||
SRC := $(wildcard *.c)
|
||||
|
||||
OBJS := $(SRC:%.c=$(OBJDIR)/%.o)
|
||||
|
||||
ifdef NO_ROM
|
||||
LINKFILE = $(OBJDIR)/no_rom.lds
|
||||
ORIGIN = 0
|
||||
DEFINES += -DNO_ROM
|
||||
else
|
||||
LINKFILE = $(OBJDIR)/$(TARGET).lds
|
||||
ORIGIN = FFFF500
|
||||
endif
|
||||
|
||||
$(OBJDIR)/$(TARGET).bin : $(OBJDIR)/$(TARGET).elf
|
||||
$(OC) -O binary $(OBJDIR)/$(TARGET).elf $(OBJDIR)/$(TARGET).bin
|
||||
$(TOOLSDIR)/sh2d $(OBJDIR)/$(TARGET).bin -o $(ORIGIN) > $(OBJDIR)/$(TARGET).asm
|
||||
ifndef NO_ROM
|
||||
$(TOOLSDIR)/scramble $(OBJDIR)/$(TARGET).bin $(OBJDIR)/$(TARGET).ajz
|
||||
endif
|
||||
|
||||
$(OBJDIR)/$(TARGET).elf : $(OBJS)
|
||||
$(CC) -Os -nostdlib -o $(OBJDIR)/$(TARGET).elf -L$(OBJDIR) -T$(LINKFILE) -Wl,-Map,$(OBJDIR)/$(TARGET).map
|
||||
|
||||
|
||||
clean:
|
||||
-rm -f \
|
||||
$(OBJS) \
|
||||
$(OBJDIR)/$(TARGET).asm \
|
||||
$(OBJDIR)/$(TARGET).bin \
|
||||
$(OBJDIR)/$(TARGET).ajz \
|
||||
$(OBJDIR)/$(TARGET).elf \
|
||||
$(OBJDIR)/$(TARGET).map
|
||||
4
flash/bootloader/README
Normal file
4
flash/bootloader/README
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
(c) 2003 by Jörg Hohensohn
|
||||
|
||||
This is the source code for the flash bootloader.
|
||||
It give the dual boot feature, decompresses one of two software images.
|
||||
480
flash/bootloader/bootloader.c
Normal file
480
flash/bootloader/bootloader.c
Normal file
|
|
@ -0,0 +1,480 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2003 by Jörg Hohensohn
|
||||
*
|
||||
* Second-level bootloader, with dual-boot feature by holding F1/Menu
|
||||
* This is the image being descrambled and executed by the boot ROM.
|
||||
* It's task is to copy Rockbox from Flash to DRAM.
|
||||
* The image(s) in flash may optionally be compressed with UCL 2e
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "sh7034.h"
|
||||
#include "bootloader.h"
|
||||
|
||||
|
||||
#ifdef NO_ROM
|
||||
// start with the vector table
|
||||
UINT32 vectors[] __attribute__ ((section (".vectors"))) =
|
||||
{
|
||||
(UINT32)_main, // entry point, the copy routine
|
||||
(UINT32)(end_stack - 1), // initial stack pointer
|
||||
FLASH_BASE + 0x200, // source of image in flash
|
||||
(UINT32)total_size, // size of image
|
||||
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,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,
|
||||
0x03020080 // mask and version (just as a suggestion)
|
||||
};
|
||||
#else
|
||||
// our binary has to start with a vector to the entry point
|
||||
tpMain start_vector[] __attribute__ ((section (".startvector"))) = {main};
|
||||
#endif
|
||||
|
||||
#ifdef NO_ROM // some code which is only needed for the romless variant
|
||||
void _main(void)
|
||||
{
|
||||
UINT32* pSrc;
|
||||
UINT32* pDest;
|
||||
UINT32* pEnd;
|
||||
/*
|
||||
asm volatile ("ldc %0,sr" : : "r"(0xF0)); // disable interrupts
|
||||
asm volatile ("mov.l @%0,r15" : : "r"(4)); // load stack
|
||||
asm volatile ("ldc %0,vbr" : : "r"(0)); // load vector base
|
||||
*/
|
||||
// copy everything to IRAM and continue there
|
||||
pSrc = begin_iramcopy;
|
||||
pDest = begin_text;
|
||||
pEnd = pDest + (begin_stack - begin_text);
|
||||
|
||||
do
|
||||
{
|
||||
*pDest++ = *pSrc++;
|
||||
}
|
||||
while (pDest < pEnd);
|
||||
|
||||
main(); // jump to the real main()
|
||||
}
|
||||
|
||||
|
||||
void BootInit(void)
|
||||
{
|
||||
// inits from the boot ROM, whether they make sense or not
|
||||
PBDR &= 0xFFBF; // LED off (0x131E)
|
||||
PBCR2 = 0; // all GPIO
|
||||
PBIOR |= 0x40; // LED output
|
||||
PBIOR &= 0xFFF1; // LCD lines input
|
||||
|
||||
// init DRAM like the boot ROM does
|
||||
PACR2 &= 0xFFFB;
|
||||
PACR2 |= 0x0008;
|
||||
CASCR = 0xAF;
|
||||
BCR |= 0x8000;
|
||||
WCR1 &= 0xFDFD;
|
||||
DCR = 0x0E00;
|
||||
RCR = 0x5AB0;
|
||||
RTCOR = 0x9605;
|
||||
RTCSR = 0xA518;
|
||||
}
|
||||
#endif // #ifdef NO_ROM
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int nButton;
|
||||
|
||||
PlatformInit(); // model-specific inits
|
||||
|
||||
nButton = ButtonPressed();
|
||||
|
||||
if (nButton == 3)
|
||||
{ // F3 means start monitor
|
||||
MiniMon();
|
||||
}
|
||||
else
|
||||
{
|
||||
tImage* pImage;
|
||||
pImage = GetStartImage(nButton); // which image
|
||||
DecompressStart(pImage); // move into place and start it
|
||||
}
|
||||
|
||||
return 0; // I guess we won't return ;-)
|
||||
}
|
||||
|
||||
|
||||
// init code that is specific to certain platform
|
||||
void PlatformInit(void)
|
||||
{
|
||||
#ifdef NO_ROM
|
||||
BootInit(); // if not started by boot ROM, we need to init what it did
|
||||
#endif
|
||||
|
||||
#if defined PLATFORM_PLAYER
|
||||
BRR1 = 0x0019; // 14400 Baud for monitor
|
||||
if (FW_VERSION > 451) // "new" Player?
|
||||
{
|
||||
PBDR &= ~0x10; // set PB4 to 0 to power-up the harddisk early
|
||||
PBIOR |= 0x10; // make PB4 an output
|
||||
}
|
||||
#elif defined PLATFORM_RECORDER
|
||||
BRR1 = 0x0002; // 115200 Baud for monitor
|
||||
if (ReadADC(7) > 0x100) // charger plugged?
|
||||
{ // switch off the HD, else a flat battery may not start
|
||||
PACR2 &= 0xFBFF; // GPIO for PA5
|
||||
PAIOR |= 0x20; // make PA5 an output (low by default)
|
||||
}
|
||||
#elif defined PLATFORM_FM
|
||||
BRR1 = 0x0002; // 115200 Baud for monitor
|
||||
PBDR |= 0x20; // set PB5 to keep power (fixes the ON-holding problem)
|
||||
PBIOR |= 0x20; // make PB5 an output
|
||||
if (ReadADC(0) < 0x1FF) // charger plugged?
|
||||
{
|
||||
// how do we switch this off?
|
||||
}
|
||||
#endif
|
||||
|
||||
// platform-independent inits
|
||||
DCR |= 0x1000; // enable burst mode on DRAM
|
||||
BCR |= 0x2000; // activate Warp mode (simultaneous internal and external mem access)
|
||||
}
|
||||
|
||||
|
||||
// Thinned out version of the UCL 2e decompression sourcecode
|
||||
// Original (C) Markus F.X.J Oberhumer under GNU GPL license
|
||||
#define GETBIT(bb, src, ilen) \
|
||||
(((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1)
|
||||
|
||||
int ucl_nrv2e_decompress_8(
|
||||
const UINT8 *src, UINT8 *dst, UINT32* dst_len)
|
||||
{
|
||||
UINT32 bb = 0;
|
||||
unsigned ilen = 0, olen = 0, last_m_off = 1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
unsigned m_off, m_len;
|
||||
|
||||
while (GETBIT(bb,src,ilen))
|
||||
{
|
||||
dst[olen++] = src[ilen++];
|
||||
}
|
||||
m_off = 1;
|
||||
for (;;)
|
||||
{
|
||||
m_off = m_off*2 + GETBIT(bb,src,ilen);
|
||||
if (GETBIT(bb,src,ilen)) break;
|
||||
m_off = (m_off-1)*2 + GETBIT(bb,src,ilen);
|
||||
}
|
||||
if (m_off == 2)
|
||||
{
|
||||
m_off = last_m_off;
|
||||
m_len = GETBIT(bb,src,ilen);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_off = (m_off-3)*256 + src[ilen++];
|
||||
if (m_off == 0xffffffff)
|
||||
break;
|
||||
m_len = (m_off ^ 0xffffffff) & 1;
|
||||
m_off >>= 1;
|
||||
last_m_off = ++m_off;
|
||||
}
|
||||
if (m_len)
|
||||
m_len = 1 + GETBIT(bb,src,ilen);
|
||||
else if (GETBIT(bb,src,ilen))
|
||||
m_len = 3 + GETBIT(bb,src,ilen);
|
||||
else
|
||||
{
|
||||
m_len++;
|
||||
do {
|
||||
m_len = m_len*2 + GETBIT(bb,src,ilen);
|
||||
} while (!GETBIT(bb,src,ilen));
|
||||
m_len += 3;
|
||||
}
|
||||
m_len += (m_off > 0x500);
|
||||
{
|
||||
const UINT8 *m_pos;
|
||||
m_pos = dst + olen - m_off;
|
||||
dst[olen++] = *m_pos++;
|
||||
do dst[olen++] = *m_pos++; while (--m_len > 0);
|
||||
}
|
||||
}
|
||||
*dst_len = olen;
|
||||
|
||||
return ilen;
|
||||
}
|
||||
|
||||
|
||||
// move the image into place and start it
|
||||
void DecompressStart(tImage* pImage)
|
||||
{
|
||||
UINT32* pSrc;
|
||||
UINT32* pDest;
|
||||
|
||||
pSrc = pImage->image;
|
||||
pDest = pImage->pDestination;
|
||||
|
||||
if (pSrc != pDest) // if not linked to that flash address
|
||||
{
|
||||
if (pImage->flags & IF_UCL_2E)
|
||||
{ // UCL compressed, algorithm 2e
|
||||
UINT32 dst_len; // dummy
|
||||
ucl_nrv2e_decompress_8((UINT8*)pSrc, (UINT8*)pDest, &dst_len);
|
||||
}
|
||||
else
|
||||
{ // uncompressed, copy it
|
||||
UINT32 size = pImage->size;
|
||||
UINT32* pEnd;
|
||||
size = (size + 3) / 4; // round up to 32bit-words
|
||||
pEnd = pDest + size;
|
||||
|
||||
do
|
||||
{
|
||||
*pDest++ = *pSrc++;
|
||||
}
|
||||
while (pDest < pEnd);
|
||||
}
|
||||
}
|
||||
|
||||
pImage->pExecute();
|
||||
}
|
||||
|
||||
|
||||
int ReadADC(int channel)
|
||||
{
|
||||
// after channel 3, the ports wrap and get re-used
|
||||
volatile UINT16* pResult = (UINT16*)(ADDRAH_ADDR + 2 * (channel & 0x03));
|
||||
int timeout = 266; // conversion takes 266 clock cycles
|
||||
|
||||
ADCSR = 0x20 | channel; // start single conversion
|
||||
while (((ADCSR & 0x80) == 0) && (--timeout)); // 6 instructions per round
|
||||
|
||||
return (timeout == 0) ? -1 : *pResult>>6;
|
||||
}
|
||||
|
||||
|
||||
// This function is platform-dependent,
|
||||
// until I figure out how to distinguish at runtime.
|
||||
int ButtonPressed(void) // return 1,2,3 for F1,F2,F3, 0 if none pressed
|
||||
{
|
||||
int value = ReadADC(CHANNEL);
|
||||
|
||||
if (value >= F1_LOWER && value <= F1_UPPER) // in range
|
||||
return 1;
|
||||
else if (value >= F2_LOWER && value <= F2_UPPER) // in range
|
||||
return 2;
|
||||
else if (value >= F3_LOWER && value <= F3_UPPER) // in range
|
||||
return 3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Determine the image to be started
|
||||
tImage* GetStartImage(int nPreferred)
|
||||
{
|
||||
tImage* pImage1;
|
||||
tImage* pImage2 = NULL; // default to not present
|
||||
UINT32 pos;
|
||||
UINT32* pFlash = (UINT32*)FLASH_BASE;
|
||||
|
||||
// determine the first image position
|
||||
pos = pFlash[2] + pFlash[3]; // position + size of the bootloader = after it
|
||||
pos = (pos + 3) & ~3; // be shure it's 32 bit aligned
|
||||
|
||||
pImage1 = (tImage*)pos;
|
||||
|
||||
if (pImage1->size != 0)
|
||||
{ // check for second image
|
||||
pos = (UINT32)(&pImage1->image) + pImage1->size;
|
||||
pImage2 = (tImage*)pos;
|
||||
|
||||
// does it make sense? (not in FF or 00 erazed space)
|
||||
if (pImage2->pDestination == (void*)0xFFFFFFFF
|
||||
|| pImage2->size == 0xFFFFFFFF
|
||||
|| pImage2->pExecute == (void*)0xFFFFFFFF
|
||||
|| pImage2->flags == 0xFFFFFFFF
|
||||
|| pImage2->pDestination == NULL) // size, execute and flags can legally be 0
|
||||
{
|
||||
pImage2 = NULL; // invalidate
|
||||
}
|
||||
}
|
||||
|
||||
if (pImage2 == NULL || nPreferred == 1)
|
||||
{ // no second image or overridden: return the first
|
||||
return pImage1;
|
||||
}
|
||||
|
||||
return pImage2; // return second image
|
||||
}
|
||||
|
||||
// diagnostic functions
|
||||
|
||||
void SetLed(BOOL bOn)
|
||||
{
|
||||
if (bOn)
|
||||
PBDR |= 0x40;
|
||||
else
|
||||
PBDR &= ~0x40;
|
||||
}
|
||||
|
||||
|
||||
void UartInit(void)
|
||||
{
|
||||
PBIOR &= 0xFBFF; // input: RXD1 remote pin
|
||||
PBCR1 |= 0x00A0; // set PB3+PB2 to UART
|
||||
PBCR1 &= 0xFFAF; // clear bits 6, 4 -> UART
|
||||
SMR1 = 0x0000; // async format 8N1, baud generator input is CPU clock
|
||||
SCR1 = 0x0030; // transmit+receive enable
|
||||
PBCR1 &= 0x00FF; // set bit 12...15 as GPIO
|
||||
SSR1 &= 0x00BF; // clear bit 6 (RDRF, receive data register full)
|
||||
}
|
||||
|
||||
|
||||
UINT8 UartRead(void)
|
||||
{
|
||||
UINT8 byte;
|
||||
while (!(SSR1 & SCI_RDRF)); // wait for char to be available
|
||||
byte = RDR1;
|
||||
SSR1 &= ~SCI_RDRF;
|
||||
return byte;
|
||||
}
|
||||
|
||||
|
||||
void UartWrite(UINT8 byte)
|
||||
{
|
||||
while (!(SSR1 & SCI_TDRE)); // wait for transmit buffer empty
|
||||
TDR1 = byte;
|
||||
SSR1 &= ~SCI_TDRE;
|
||||
}
|
||||
|
||||
|
||||
// include the mini monitor as a rescue feature, started with F3
|
||||
void MiniMon(void)
|
||||
{
|
||||
UINT8 cmd;
|
||||
UINT32 addr;
|
||||
UINT32 size;
|
||||
UINT32 content;
|
||||
volatile UINT8* paddr = NULL;
|
||||
volatile UINT8* pflash = NULL; // flash base address
|
||||
|
||||
UartInit();
|
||||
|
||||
while (1)
|
||||
{
|
||||
cmd = UartRead();
|
||||
switch (cmd)
|
||||
{
|
||||
case BAUDRATE:
|
||||
content = UartRead();
|
||||
UartWrite(cmd); // acknowledge by returning the command value
|
||||
while (!(SSR1 & SCI_TEND)); // wait for empty shift register, before changing baudrate
|
||||
BRR1 = content;
|
||||
break;
|
||||
|
||||
case ADDRESS:
|
||||
addr = (UartRead() << 24) | (UartRead() << 16) | (UartRead() << 8) | UartRead();
|
||||
paddr = (UINT8*)addr;
|
||||
pflash = (UINT8*)(addr & 0xFFF80000); // round down to 512k align
|
||||
UartWrite(cmd); // acknowledge by returning the command value
|
||||
break;
|
||||
|
||||
case BYTE_READ:
|
||||
content = *paddr++;
|
||||
UartWrite(content); // the content is the ack
|
||||
break;
|
||||
|
||||
case BYTE_WRITE:
|
||||
content = UartRead();
|
||||
*paddr++ = content;
|
||||
UartWrite(cmd); // acknowledge by returning the command value
|
||||
break;
|
||||
|
||||
case BYTE_READ16:
|
||||
size = 16;
|
||||
while (size--)
|
||||
{
|
||||
content = *paddr++;
|
||||
UartWrite(content); // the content is the ack
|
||||
}
|
||||
break;
|
||||
|
||||
case BYTE_WRITE16:
|
||||
size = 16;
|
||||
while (size--)
|
||||
{
|
||||
content = UartRead();
|
||||
*paddr++ = content;
|
||||
}
|
||||
UartWrite(cmd); // acknowledge by returning the command value
|
||||
break;
|
||||
|
||||
case BYTE_FLASH:
|
||||
content = UartRead();
|
||||
pflash[0x5555] = 0xAA; // set flash to command mode
|
||||
pflash[0x2AAA] = 0x55;
|
||||
pflash[0x5555] = 0xA0; // byte program command
|
||||
*paddr++ = content;
|
||||
UartWrite(cmd); // acknowledge by returning the command value
|
||||
break;
|
||||
|
||||
case BYTE_FLASH16:
|
||||
size = 16;
|
||||
while (size--)
|
||||
{
|
||||
content = UartRead();
|
||||
pflash[0x5555] = 0xAA; // set flash to command mode
|
||||
pflash[0x2AAA] = 0x55;
|
||||
pflash[0x5555] = 0xA0; // byte program command
|
||||
*paddr++ = content;
|
||||
}
|
||||
UartWrite(cmd); // acknowledge by returning the command value
|
||||
break;
|
||||
|
||||
case HALFWORD_READ:
|
||||
content = *(UINT16*)paddr;
|
||||
paddr += 2;
|
||||
UartWrite(content >> 8); // highbyte
|
||||
UartWrite(content & 0xFF); // lowbyte
|
||||
break;
|
||||
|
||||
case HALFWORD_WRITE:
|
||||
content = UartRead() << 8 | UartRead();
|
||||
*(UINT16*)paddr = content;
|
||||
paddr += 2;
|
||||
UartWrite(cmd); // acknowledge by returning the command value
|
||||
break;
|
||||
|
||||
case EXECUTE:
|
||||
{
|
||||
tpFunc pFunc = (tpFunc)paddr;
|
||||
pFunc();
|
||||
UartWrite(cmd); // acknowledge by returning the command value
|
||||
}
|
||||
break;
|
||||
|
||||
case VERSION:
|
||||
UartWrite(1); // return our version number
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
SetLed(TRUE);
|
||||
UartWrite(~cmd); // error acknowledge
|
||||
}
|
||||
|
||||
} // case
|
||||
} // while (1)
|
||||
}
|
||||
111
flash/bootloader/bootloader.h
Normal file
111
flash/bootloader/bootloader.h
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
#ifndef NULL
|
||||
#define NULL ((void*)0)
|
||||
#endif
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
// scalar types
|
||||
typedef unsigned char UINT8;
|
||||
typedef unsigned short UINT16;
|
||||
typedef unsigned long UINT32;
|
||||
typedef int BOOL;
|
||||
|
||||
typedef void(*tpFunc)(void); // type for execute
|
||||
typedef int(*tpMain)(void); // type for start vector to main()
|
||||
|
||||
|
||||
// structure of an image in the flash
|
||||
typedef struct
|
||||
{
|
||||
UINT32* pDestination; // address to copy it to
|
||||
UINT32 size; // how many bytes of payload (to the next header)
|
||||
tpFunc pExecute; // entry point
|
||||
UINT32 flags; // uncompressed or compressed
|
||||
// end of header, now comes the payload
|
||||
UINT32 image[]; // the binary image starts here
|
||||
// after the payload, the next header may follow, all 0xFF if none
|
||||
} tImage;
|
||||
|
||||
// flags valid for image header
|
||||
#define IF_NONE 0x00000000
|
||||
#define IF_UCL_2E 0x00000001 // image is compressed with UCL, algorithm 2e
|
||||
|
||||
|
||||
// resolve platform dependency of F1 button check
|
||||
#if defined PLATFORM_PLAYER
|
||||
#define CHANNEL 1
|
||||
#define F1_LOWER 0 // this is the "Menu" key
|
||||
#define F1_UPPER 384
|
||||
#define F2_LOWER 1024 // not present
|
||||
#define F2_UPPER 1024
|
||||
#define F3_LOWER 1024
|
||||
#define F3_UPPER 1024
|
||||
#elif defined PLATFORM_RECORDER
|
||||
#define CHANNEL 4
|
||||
#define F1_LOWER 250
|
||||
#define F1_UPPER 499
|
||||
#define F2_LOWER 500
|
||||
#define F2_UPPER 699
|
||||
#define F3_LOWER 900
|
||||
#define F3_UPPER 1023
|
||||
#elif defined PLATFORM_FM
|
||||
#define CHANNEL 4
|
||||
#define F1_LOWER 150
|
||||
#define F1_UPPER 384
|
||||
#define F2_LOWER 385
|
||||
#define F2_UPPER 544
|
||||
#define F3_LOWER 700
|
||||
#define F3_UPPER 1023
|
||||
#else
|
||||
#error ("No platform given!")
|
||||
#endif
|
||||
|
||||
#define FLASH_BASE 0x02000000 // start of the flash memory
|
||||
#define FW_VERSION *(unsigned short*)(FLASH_BASE + 0xFE) // firmware version
|
||||
|
||||
|
||||
// prototypes
|
||||
void _main(void) __attribute__ ((section (".startup")));
|
||||
int main(void);
|
||||
void PlatformInit(void);
|
||||
void DramInit(void);
|
||||
int ucl_nrv2e_decompress_8(const UINT8 *src, UINT8 *dst, UINT32* dst_len);
|
||||
void DecompressStart(tImage* pImage);
|
||||
int ReadADC(int channel);
|
||||
int ButtonPressed(void);
|
||||
tImage* GetStartImage(int nPreferred);
|
||||
// test functions
|
||||
void SetLed(BOOL bOn);
|
||||
void UartInit(void);
|
||||
UINT8 UartRead(void);
|
||||
void UartWrite(UINT8 byte);
|
||||
void MiniMon(void);
|
||||
|
||||
|
||||
// minimon commands
|
||||
#define BAUDRATE 0x00 // followed by BRR value; response: command byte
|
||||
#define ADDRESS 0x01 // followed by 4 bytes address; response: command byte
|
||||
#define BYTE_READ 0x02 // response: 1 byte content
|
||||
#define BYTE_WRITE 0x03 // followed by 1 byte content; response: command byte
|
||||
#define BYTE_READ16 0x04 // response: 16 bytes content
|
||||
#define BYTE_WRITE16 0x05 // followed by 16 bytes; response: command byte
|
||||
#define BYTE_FLASH 0x06 // followed by 1 byte content; response: command byte
|
||||
#define BYTE_FLASH16 0x07 // followed by 16 bytes; response: command byte
|
||||
#define HALFWORD_READ 0x08 // response: 2 byte content
|
||||
#define HALFWORD_WRITE 0x09 // followed by 2 byte content; response: command byte
|
||||
#define EXECUTE 0x0A // response: command byte if call returns
|
||||
#define VERSION 0x0B // response: version
|
||||
|
||||
|
||||
// linker symbols
|
||||
extern UINT32 begin_text[];
|
||||
extern UINT32 end_text[];
|
||||
extern UINT32 begin_data[];
|
||||
extern UINT32 end_data[];
|
||||
extern UINT32 begin_bss[];
|
||||
extern UINT32 end_bss[];
|
||||
extern UINT32 begin_stack[];
|
||||
extern UINT32 end_stack[];
|
||||
extern UINT32 begin_iramcopy[];
|
||||
extern UINT32 total_size[];
|
||||
34
flash/bootloader/bootloader.lds
Normal file
34
flash/bootloader/bootloader.lds
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
OUTPUT_FORMAT(elf32-sh)
|
||||
INPUT(bootloader.o)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
/* the boot ROM uses IRAM at 400-430, stay away and start at 500 */
|
||||
IRAM : ORIGIN = 0x0FFFF500, LENGTH = 0xA00
|
||||
/* and leave some room for stack at the end */
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.startvector :
|
||||
{
|
||||
*(.startvector)
|
||||
. = ALIGN(0x4);
|
||||
} > IRAM
|
||||
|
||||
.text :
|
||||
{
|
||||
*(.text)
|
||||
. = ALIGN(0x4);
|
||||
} > IRAM
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
} > IRAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
*(.bss)
|
||||
} > IRAM
|
||||
}
|
||||
62
flash/bootloader/no_rom.lds
Normal file
62
flash/bootloader/no_rom.lds
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/* This is for the variant without boot ROM,
|
||||
where the flash ROM is mirrored to address zero */
|
||||
|
||||
OUTPUT_FORMAT(elf32-sh)
|
||||
INPUT(bootloader.o)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
IRAM : ORIGIN = 0x0FFFF000, LENGTH = 0x1000
|
||||
FLASH : ORIGIN = 0x00000000, LENGTH = 0x40000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.vectors :
|
||||
{
|
||||
*(.vectors)
|
||||
. = ALIGN(0x200);
|
||||
} > FLASH
|
||||
|
||||
.startup :
|
||||
{
|
||||
*(.startup)
|
||||
. = ALIGN(0x4);
|
||||
_begin_iramcopy = .;
|
||||
} > FLASH
|
||||
|
||||
.text : AT ( _begin_iramcopy )
|
||||
{
|
||||
_begin_text = .;
|
||||
*(.text)
|
||||
. = ALIGN(0x4);
|
||||
_end_text = .;
|
||||
} > IRAM
|
||||
|
||||
.data : AT ( _end_text )
|
||||
{
|
||||
_begin_data = .;
|
||||
*(.data)
|
||||
. = ALIGN(0x4);
|
||||
_end_data = .;
|
||||
} > IRAM
|
||||
|
||||
.bss : AT ( _end_data )
|
||||
{
|
||||
_begin_bss = .;
|
||||
*(.bss)
|
||||
. = ALIGN(0x4);
|
||||
_end_bss = .;
|
||||
} > IRAM
|
||||
|
||||
.stack :
|
||||
{
|
||||
_begin_stack = .;
|
||||
*(.stack)
|
||||
. = ALIGN(0x1000);
|
||||
_end_stack = .;
|
||||
} > IRAM
|
||||
|
||||
/* size of the program (without vectors) */
|
||||
_total_size = SIZEOF(.startup) + SIZEOF(.text) + SIZEOF(.data);
|
||||
}
|
||||
5
flash/extract/README
Normal file
5
flash/extract/README
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
(c) 2003 by Jörg Hohensohn
|
||||
|
||||
This tool extracts the firmware image out of an original Archos ROM dump,
|
||||
like created with the Rockbox debug->dump feature.
|
||||
The extracted image can then be used to compose a dual-boot firmware.
|
||||
140
flash/extract/extract.c
Normal file
140
flash/extract/extract.c
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2003 by Jörg Hohensohn
|
||||
*
|
||||
* Tool to extract the scrambled image out of an Archos flash ROM dump
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
|
||||
#define UINT8 unsigned char
|
||||
#define UINT16 unsigned short
|
||||
#define UINT32 unsigned long
|
||||
|
||||
#define IMAGE_HEADER 0x6000 // a 32 byte header in front of the software image
|
||||
#define IMAGE_START 0x6020 // software image position in Flash
|
||||
|
||||
|
||||
// place a 32 bit value into memory, big endian
|
||||
void Write32(UINT8* pByte, UINT32 value)
|
||||
{
|
||||
pByte[0] = (UINT8)(value >> 24);
|
||||
pByte[1] = (UINT8)(value >> 16);
|
||||
pByte[2] = (UINT8)(value >> 8);
|
||||
pByte[3] = (UINT8)(value);
|
||||
}
|
||||
|
||||
|
||||
// read a 32 bit value from memory, big endian
|
||||
UINT32 Read32(UINT8* pByte)
|
||||
{
|
||||
UINT32 value = 0;
|
||||
|
||||
value |= (UINT32)pByte[0] << 24;
|
||||
value |= (UINT32)pByte[1] << 16;
|
||||
value |= (UINT32)pByte[2] << 8;
|
||||
value |= (UINT32)pByte[3];
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
// entry point
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
FILE* pInFile;
|
||||
FILE* pOutFile;
|
||||
UINT8 aHeader[6];
|
||||
UINT8 aImage[256*1024];
|
||||
UINT32 i;
|
||||
UINT32 uiSize, uiStart;
|
||||
UINT16 usChecksum = 0;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
printf("Extract the software image out of an original Archos Flash ROM dump.\n");
|
||||
printf("Result is a scrambled file, use the descramble tool to get the binary,\n");
|
||||
printf(" always without the -fm option, even if processing an FM software.\n\n");
|
||||
printf("Usage: extract <flash dump file> <output file>\n");
|
||||
printf("Example: extract internal_rom_2000000-203FFFF.bin archos.ajz\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
pInFile = fopen(argv[1], "rb");
|
||||
if (pInFile == NULL)
|
||||
{
|
||||
printf("Error opening input file %s\n", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (fread(aImage, 1, sizeof(aImage), pInFile) != sizeof(aImage))
|
||||
{
|
||||
printf("Error reading input file %s, must be 256kB in size.\n", argv[1]);
|
||||
fclose(pInFile);
|
||||
exit(2);
|
||||
}
|
||||
fclose(pInFile);
|
||||
|
||||
// find out about the type
|
||||
uiStart = Read32(aImage + 8);
|
||||
uiSize = Read32(aImage + 12); // booted ROM image
|
||||
if (uiStart == 0x02000100 && uiSize > 20000)
|
||||
{ // Player has no loader, starts directly with the image
|
||||
uiStart = 0x0100;
|
||||
}
|
||||
else
|
||||
{ // Recorder / FM / V2 Recorder
|
||||
uiStart = IMAGE_START;
|
||||
uiSize = Read32(aImage + IMAGE_HEADER + 4); // size record of header
|
||||
}
|
||||
|
||||
// sanity check
|
||||
if (uiSize > sizeof(aImage) - uiStart || uiSize < 40000)
|
||||
{
|
||||
printf("Error: Impossible image size &d bytes.\n", uiSize);
|
||||
exit(3);
|
||||
}
|
||||
|
||||
// generate checksum
|
||||
for (i=0; i<uiSize; i++)
|
||||
usChecksum += aImage[uiStart + i];
|
||||
|
||||
// make header
|
||||
Write32(aHeader + 2, usChecksum); // checksum in 5th and 6th byte
|
||||
Write32(aHeader, uiSize); // size in first 4 bytes
|
||||
|
||||
pOutFile = fopen(argv[2], "wb");
|
||||
if (pOutFile == NULL)
|
||||
{
|
||||
printf("Error opening output file %s\n", argv[2]);
|
||||
exit(4);
|
||||
}
|
||||
|
||||
if (fwrite(aHeader, 1, sizeof(aHeader), pOutFile) != sizeof(aHeader)
|
||||
|| fwrite(aImage + uiStart, 1, uiSize, pOutFile) != uiSize)
|
||||
{
|
||||
printf("Write error\n");
|
||||
fclose(pOutFile);
|
||||
exit(5);
|
||||
}
|
||||
|
||||
fclose(pOutFile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
100
flash/extract/extract.dsp
Normal file
100
flash/extract/extract.dsp
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
# Microsoft Developer Studio Project File - Name="extract" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=extract - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "extract.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "extract.mak" CFG="extract - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "extract - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "extract - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "extract - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x407 /d "NDEBUG"
|
||||
# ADD RSC /l 0x407 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "extract - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x407 /d "_DEBUG"
|
||||
# ADD RSC /l 0x407 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "extract - Win32 Release"
|
||||
# Name "extract - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\extract.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
14
flash/make_firmware/README
Normal file
14
flash/make_firmware/README
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
(c) 2003 by Jörg Hohensohn
|
||||
|
||||
This tool composes a firmware file, out of:
|
||||
1. Template for the first Flash page
|
||||
2. Bootloader
|
||||
3. Archos image
|
||||
4. Rockbox image
|
||||
|
||||
Use with extreme caution, the components have to match!
|
||||
The aspects are:
|
||||
- Model (Player, Recorder, FM, V2)
|
||||
- boot type (standard boot ROM or ROMless)
|
||||
|
||||
Such a firmware file can then be programmed with "firmware_flash.rock".
|
||||
338
flash/make_firmware/make_firmware.c
Normal file
338
flash/make_firmware/make_firmware.c
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2003 by Jörg Hohensohn
|
||||
*
|
||||
* Autoring tool for the firmware image to be programmed into Flash ROM
|
||||
* It composes the flash content with header, bootloader and image(s)
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
|
||||
#define UINT8 unsigned char
|
||||
#define UINT16 unsigned short
|
||||
#define UINT32 unsigned long
|
||||
#define BOOL int
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
// size of one flash sector, the granularity with which it can be erased
|
||||
#define SECTORSIZE 4096
|
||||
|
||||
#define BOOTLOAD_DEST 0x0FFFF500 // for the "normal" one
|
||||
#define BOOTLOAD_SCR 0x02000100
|
||||
#define ROCKBOX_DEST 0x09000000
|
||||
#define ROCKBOX_EXEC 0x09000200
|
||||
|
||||
|
||||
// place a 32 bit value into memory, big endian
|
||||
void Write32(UINT8* pByte, UINT32 value)
|
||||
{
|
||||
pByte[0] = (UINT8)(value >> 24);
|
||||
pByte[1] = (UINT8)(value >> 16);
|
||||
pByte[2] = (UINT8)(value >> 8);
|
||||
pByte[3] = (UINT8)(value);
|
||||
}
|
||||
|
||||
|
||||
// read a 32 bit value from memory, big endian
|
||||
UINT32 Read32(UINT8* pByte)
|
||||
{
|
||||
UINT32 value = 0;
|
||||
|
||||
value |= (UINT32)pByte[0] << 24;
|
||||
value |= (UINT32)pByte[1] << 16;
|
||||
value |= (UINT32)pByte[2] << 8;
|
||||
value |= (UINT32)pByte[3];
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
UINT32 CalcCRC32 (const UINT8* buf, UINT32 len)
|
||||
{
|
||||
static const UINT32 crc_table[256] =
|
||||
{ // CRC32 lookup table for polynomial 0x04C11DB7
|
||||
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B,
|
||||
0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
|
||||
0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, 0x4C11DB70, 0x48D0C6C7,
|
||||
0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75,
|
||||
0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3,
|
||||
0x709F7B7A, 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
|
||||
0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58, 0xBAEA46EF,
|
||||
0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D,
|
||||
0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB,
|
||||
0xCEB42022, 0xCA753D95, 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1,
|
||||
0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0,
|
||||
0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072,
|
||||
0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4,
|
||||
0x0808D07D, 0x0CC9CDCA, 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE,
|
||||
0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08,
|
||||
0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
|
||||
0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC,
|
||||
0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6,
|
||||
0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, 0xE0B41DE7, 0xE4750050,
|
||||
0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2,
|
||||
0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34,
|
||||
0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637,
|
||||
0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, 0x4F040D56, 0x4BC510E1,
|
||||
0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53,
|
||||
0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5,
|
||||
0x3F9B762C, 0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
|
||||
0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E, 0xF5EE4BB9,
|
||||
0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B,
|
||||
0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD,
|
||||
0xCDA1F604, 0xC960EBB3, 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7,
|
||||
0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71,
|
||||
0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3,
|
||||
0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2,
|
||||
0x470CDD2B, 0x43CDC09C, 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8,
|
||||
0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E,
|
||||
0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
|
||||
0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A,
|
||||
0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0,
|
||||
0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, 0xE3A1CBC1, 0xE760D676,
|
||||
0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4,
|
||||
0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662,
|
||||
0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668,
|
||||
0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4
|
||||
};
|
||||
UINT32 i;
|
||||
UINT32 crc = 0xffffffff;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *buf++) & 0xFF];
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
UINT32 PlaceImage(char* filename, UINT32 pos, UINT8* pFirmware, UINT32 limit)
|
||||
{
|
||||
UINT32 size, read;
|
||||
FILE* pFile;
|
||||
UINT32 align;
|
||||
UINT32 flags;
|
||||
|
||||
// magic file header for compressed files
|
||||
static const UINT8 magic[8] = { 0x00,0xe9,0x55,0x43,0x4c,0xff,0x01,0x1a };
|
||||
UINT8 ucl_header[26];
|
||||
|
||||
pFile = fopen(filename, "rb"); // open the current image
|
||||
if (pFile == NULL)
|
||||
{
|
||||
printf("Image file %s not found!\n", filename);
|
||||
exit(5);
|
||||
}
|
||||
|
||||
fseek(pFile, 0, SEEK_END);
|
||||
size = ftell(pFile);
|
||||
fseek(pFile, 0, SEEK_SET);
|
||||
|
||||
// determine if compressed
|
||||
flags = 0x00000000; // default: flags for uncompressed
|
||||
fread(ucl_header, 1, sizeof(ucl_header), pFile);
|
||||
if (memcmp(magic, ucl_header, sizeof(magic)) == 0)
|
||||
{
|
||||
if (ucl_header[12] != 0x2E) // check algorithm
|
||||
{
|
||||
printf("UCL compressed files must use algorithm 2e, not %d\n", ucl_header[12]);
|
||||
printf("Generate with: uclpack --best --2e rockbox.bin %s\n", filename);
|
||||
exit(6);
|
||||
}
|
||||
|
||||
size = Read32(ucl_header + 22); // compressed size
|
||||
if (Read32(ucl_header + 18) > size) // compare with uncompressed size
|
||||
{ // normal case
|
||||
flags = 0x00000001; // flags for UCL compressed
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fseek(pFile, 0, SEEK_SET); // go back
|
||||
}
|
||||
|
||||
if (pos + 16 + size > limit) // enough space for all that?
|
||||
{
|
||||
printf("Exceeding maximum image size %d\n", limit);
|
||||
exit(7);
|
||||
}
|
||||
|
||||
// write header
|
||||
align = (pos + 16 + size + SECTORSIZE-1) & ~(SECTORSIZE-1); // round up to next flash sector
|
||||
Write32(pFirmware + pos, ROCKBOX_DEST); // load address
|
||||
Write32(pFirmware + pos + 4, align - (pos + 16)); // image size
|
||||
Write32(pFirmware + pos + 8, ROCKBOX_EXEC); // execution address
|
||||
Write32(pFirmware + pos + 12, flags); // compressed or not
|
||||
pos += 16;
|
||||
|
||||
// load image
|
||||
read = fread(pFirmware + pos, 1, size, pFile);
|
||||
if (read != size)
|
||||
{
|
||||
printf("Read error, expecting %d bytes, got only %d\n", size, read);
|
||||
exit(8);
|
||||
}
|
||||
fclose (pFile);
|
||||
|
||||
pos += size;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
static UINT8 aFirmware[512*1024]; // maximum with exchanged chip
|
||||
FILE* pFile;
|
||||
UINT32 size; // size of loaded item
|
||||
UINT32 pos; // current position in firmware
|
||||
UINT32 crc32; // checksum of "payload"
|
||||
BOOL hasBootRom; // flag if regular boot ROM or directly starts from flash
|
||||
UINT32 template_F8, template_FC; // my platform ID, mask and version
|
||||
|
||||
int i;
|
||||
|
||||
if (argc <= 4)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf("make_firmware <output> <template.bin> <bootloader.ajz> <image1.ucl> {image2.ucl}\n");
|
||||
printf("<template.bin> is the original firmware from your box\n");
|
||||
printf("<bootloader.ajz> is the scrambled bootloader\n");
|
||||
printf("<image1.ucl> is the first image, compressed (recommended) or uncompressed\n");
|
||||
printf("<image1.ucl> is the second image, compressed (recommended) or uncompressed\n");
|
||||
printf("More images may follow, but keep the flash size in mind!\n");
|
||||
printf("Compression must be UCL, algorithm 2e.\n");
|
||||
printf("Generated with: uclpack --best --2e rockbox.bin imageN.ucl\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
memset(aFirmware, 0xFF, sizeof(aFirmware));
|
||||
|
||||
/******* process template *******/
|
||||
|
||||
pFile = fopen(argv[2], "rb"); // open the template
|
||||
if (pFile == NULL)
|
||||
{
|
||||
printf("Template file %s not found!\n", argv[2]);
|
||||
exit(1);
|
||||
}
|
||||
size = fread(aFirmware, 1, 256, pFile); // need only the header
|
||||
fclose(pFile);
|
||||
if (size < 256) // need at least the firmware header
|
||||
{
|
||||
printf("Template file %s too small, need at least the header!\n", argv[2]);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (strncmp(aFirmware, "ARCH", 4) == 0)
|
||||
{
|
||||
hasBootRom = TRUE;
|
||||
pos = 256; // place bootloader after this "boot block"
|
||||
}
|
||||
else if (Read32(aFirmware) == 0x0200)
|
||||
{
|
||||
hasBootRom = FALSE;
|
||||
pos = 0; // directly start with the bootloader
|
||||
template_F8 = Read32(aFirmware + 0xF8); // my platform ID and future info
|
||||
template_FC = Read32(aFirmware + 0xFC); // use mask+version from template
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Template file %s invalid!\n", argv[2]);
|
||||
exit(3);
|
||||
}
|
||||
|
||||
/******* process bootloader *******/
|
||||
|
||||
pFile = fopen(argv[3], "rb"); // open the bootloader
|
||||
if (pFile == NULL)
|
||||
{
|
||||
printf("Bootloader file %s not found!\n", argv[3]);
|
||||
exit(4);
|
||||
}
|
||||
if (hasBootRom && fseek(pFile, 6, SEEK_SET)) // skip the ajz header
|
||||
{
|
||||
printf("Bootloader file %s too short!\n", argv[3]);
|
||||
exit(5);
|
||||
}
|
||||
|
||||
// place bootloader after header
|
||||
size = fread(aFirmware + pos, 1, sizeof(aFirmware) - pos, pFile);
|
||||
fclose(pFile);
|
||||
|
||||
if (hasBootRom)
|
||||
{
|
||||
Write32(aFirmware + 4, BOOTLOAD_DEST); // boot code destination address
|
||||
|
||||
for (i=0x08; i<=0x28; i+=8)
|
||||
{
|
||||
Write32(aFirmware + i, BOOTLOAD_SCR); // boot code source address
|
||||
Write32(aFirmware + i + 4, size); // boot code size
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Write32(aFirmware + 0xF8, template_F8); // values from template
|
||||
Write32(aFirmware + 0xFC, template_FC); // mask and version
|
||||
}
|
||||
|
||||
size = (size + 3) & ~3; // make shure it's 32 bit aligned
|
||||
pos += size; // prepare position for first image
|
||||
|
||||
/******* process images *******/
|
||||
for (i = 4; i < argc; i++)
|
||||
{
|
||||
pos = PlaceImage(argv[i], pos, aFirmware, sizeof(aFirmware));
|
||||
|
||||
if (i < argc-1)
|
||||
{ // not the last: round up to next flash sector
|
||||
pos = (pos + SECTORSIZE-1) & ~(SECTORSIZE-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******* append CRC32 checksum *******/
|
||||
crc32 = CalcCRC32(aFirmware, pos);
|
||||
Write32(aFirmware + pos, crc32);
|
||||
pos += sizeof(crc32); // 4 bytes
|
||||
|
||||
|
||||
/******* save result to output file *******/
|
||||
|
||||
pFile = fopen(argv[1], "wb"); // open the output file
|
||||
if (pFile == NULL)
|
||||
{
|
||||
printf("Output file %s cannot be created!\n", argv[1]);
|
||||
exit(9);
|
||||
}
|
||||
size = fwrite(aFirmware, 1, pos, pFile);
|
||||
fclose(pFile);
|
||||
|
||||
if (size != pos)
|
||||
{
|
||||
printf("Error writing %d bytes to output file %s!\n", pos, argv[1]);
|
||||
exit(10);
|
||||
}
|
||||
|
||||
printf("Firmware file generated with %d bytes.\n", pos);
|
||||
|
||||
return 0;
|
||||
}
|
||||
96
flash/make_firmware/make_firmware.dsp
Normal file
96
flash/make_firmware/make_firmware.dsp
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
# Microsoft Developer Studio Project File - Name="make_firmware" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=make_firmware - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "make_firmware.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "make_firmware.mak" CFG="make_firmware - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "make_firmware - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "make_firmware - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "make_firmware - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX"stdafx.h" /FD /c
|
||||
# ADD BASE RSC /l 0x407 /d "NDEBUG"
|
||||
# ADD RSC /l 0x407 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "make_firmware - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX"stdafx.h" /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x407 /d "_DEBUG"
|
||||
# ADD RSC /l 0x407 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "make_firmware - Win32 Release"
|
||||
# Name "make_firmware - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\make_firmware.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
53
flash/minimon/Makefile
Normal file
53
flash/minimon/Makefile
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# __________ __ ___.
|
||||
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
# \/ \/ \/ \/ \/
|
||||
# $Id$
|
||||
#
|
||||
|
||||
CC = sh-elf-gcc
|
||||
LD = sh-elf-ld
|
||||
AR = sh-elf-ar
|
||||
AS = sh-elf-as
|
||||
OC = sh-elf-objcopy
|
||||
|
||||
FIRMWARE := ../../firmware
|
||||
TOOLSDIR=../../tools
|
||||
|
||||
TARGET = minimon
|
||||
LDS := $(TARGET).lds
|
||||
|
||||
INCLUDES= -I$(FIRMWARE)/export -I. -I$(OBJDIR)
|
||||
OBJDIR := .
|
||||
|
||||
CFLAGS = -fpic -O -W -Wall -m1 -nostdlib -ffreestanding -Wstrict-prototypes -fomit-frame-pointer -fschedule-insns $(INCLUDES) $(DEFINES)
|
||||
AFLAGS += -small -relax
|
||||
|
||||
|
||||
ifdef DEBUG
|
||||
DEFINES := -DDEBUG
|
||||
CFLAGS += -g
|
||||
endif
|
||||
|
||||
SRC := $(wildcard *.c)
|
||||
|
||||
OBJS := $(SRC:%.c=$(OBJDIR)/%.o)
|
||||
|
||||
LINKFILE = $(OBJDIR)/$(TARGET).lds
|
||||
|
||||
|
||||
$(OBJDIR)/$(TARGET).bin : $(OBJDIR)/$(TARGET).elf
|
||||
$(OC) -O binary $(OBJDIR)/$(TARGET).elf $(OBJDIR)/$(TARGET).bin
|
||||
$(TOOLSDIR)/sh2d $(OBJDIR)/$(TARGET).bin -o 0900000 > $(OBJDIR)/$(TARGET).asm
|
||||
|
||||
$(OBJDIR)/$(TARGET).elf : $(OBJS)
|
||||
$(CC) -Os -nostdlib -o $(OBJDIR)/$(TARGET).elf -L$(OBJDIR) -T$(LINKFILE) -Wl,-Map,$(OBJDIR)/$(TARGET).map
|
||||
|
||||
|
||||
clean:
|
||||
-rm -f $(OBJS) $(OBJDIR)/$(TARGET).asm \
|
||||
$(OBJDIR)/$(TARGET).bin \
|
||||
$(OBJDIR)/$(TARGET).elf \
|
||||
$(OBJDIR)/$(TARGET).map
|
||||
6
flash/minimon/README
Normal file
6
flash/minimon/README
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
(c) 2003 by Jörg Hohensohn
|
||||
|
||||
MiniMon is the tiny but powerful-enough piece of code that can be loaded
|
||||
with the UART boot mod.
|
||||
It allows to read and write memory, flash program, execute code.
|
||||
This is suitable to reflash the box, load Rockbox or the gdb stub, etc.
|
||||
156
flash/minimon/minimon.c
Normal file
156
flash/minimon/minimon.c
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
// minimalistic monitor
|
||||
// to be loaded with the UART boot feature
|
||||
// capable of reading and writing bytes, commanded by UART
|
||||
|
||||
#include "sh7034.h"
|
||||
#include "minimon.h"
|
||||
|
||||
// scalar types
|
||||
typedef unsigned char UINT8;
|
||||
typedef unsigned short UINT16;
|
||||
typedef unsigned long UINT32;
|
||||
|
||||
typedef void(*tpFunc)(void); // type for exec
|
||||
typedef int(*tpMain)(void); // type for start vector to main()
|
||||
|
||||
|
||||
// prototypes
|
||||
int main(void);
|
||||
|
||||
// our binary has to start with a vector to the entry point
|
||||
tpMain start_vector[] __attribute__ ((section (".startvector"))) = {main};
|
||||
|
||||
|
||||
UINT8 uart_read(void)
|
||||
{
|
||||
UINT8 byte;
|
||||
while (!(SSR1 & SCI_RDRF)); // wait for char to be available
|
||||
byte = RDR1;
|
||||
SSR1 &= ~SCI_RDRF;
|
||||
return byte;
|
||||
}
|
||||
|
||||
|
||||
void uart_write(UINT8 byte)
|
||||
{
|
||||
while (!(SSR1 & SCI_TDRE)); // wait for transmit buffer empty
|
||||
TDR1 = byte;
|
||||
SSR1 &= ~SCI_TDRE;
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
UINT8 cmd;
|
||||
UINT32 addr;
|
||||
UINT32 size;
|
||||
UINT32 content;
|
||||
volatile UINT8* paddr = 0;
|
||||
volatile UINT8* pflash; // flash base address
|
||||
|
||||
while (1)
|
||||
{
|
||||
cmd = uart_read();
|
||||
switch (cmd)
|
||||
{
|
||||
case BAUDRATE:
|
||||
content = uart_read();
|
||||
uart_write(cmd); // acknowledge by returning the command value
|
||||
while (!(SSR1 & SCI_TEND)); // wait for empty shift register, before changing baudrate
|
||||
BRR1 = content;
|
||||
break;
|
||||
|
||||
case ADDRESS:
|
||||
addr = (uart_read() << 24) | (uart_read() << 16) | (uart_read() << 8) | uart_read();
|
||||
paddr = (UINT8*)addr;
|
||||
pflash = (UINT8*)(addr & 0xFFF80000); // round down to 512k align
|
||||
uart_write(cmd); // acknowledge by returning the command value
|
||||
break;
|
||||
|
||||
case BYTE_READ:
|
||||
content = *paddr++;
|
||||
uart_write(content); // the content is the ack
|
||||
break;
|
||||
|
||||
case BYTE_WRITE:
|
||||
content = uart_read();
|
||||
*paddr++ = content;
|
||||
uart_write(cmd); // acknowledge by returning the command value
|
||||
break;
|
||||
|
||||
case BYTE_READ16:
|
||||
size = 16;
|
||||
while (size--)
|
||||
{
|
||||
content = *paddr++;
|
||||
uart_write(content); // the content is the ack
|
||||
}
|
||||
break;
|
||||
|
||||
case BYTE_WRITE16:
|
||||
size = 16;
|
||||
while (size--)
|
||||
{
|
||||
content = uart_read();
|
||||
*paddr++ = content;
|
||||
}
|
||||
uart_write(cmd); // acknowledge by returning the command value
|
||||
break;
|
||||
|
||||
case BYTE_FLASH:
|
||||
content = uart_read();
|
||||
pflash[0x5555] = 0xAA; // set flash to command mode
|
||||
pflash[0x2AAA] = 0x55;
|
||||
pflash[0x5555] = 0xA0; // byte program command
|
||||
*paddr++ = content;
|
||||
uart_write(cmd); // acknowledge by returning the command value
|
||||
break;
|
||||
|
||||
case BYTE_FLASH16:
|
||||
size = 16;
|
||||
while (size--)
|
||||
{
|
||||
content = uart_read();
|
||||
pflash[0x5555] = 0xAA; // set flash to command mode
|
||||
pflash[0x2AAA] = 0x55;
|
||||
pflash[0x5555] = 0xA0; // byte program command
|
||||
*paddr++ = content;
|
||||
}
|
||||
uart_write(cmd); // acknowledge by returning the command value
|
||||
break;
|
||||
|
||||
case HALFWORD_READ:
|
||||
content = *(UINT16*)paddr;
|
||||
paddr += 2;
|
||||
uart_write(content >> 8); // highbyte
|
||||
uart_write(content & 0xFF); // lowbyte
|
||||
break;
|
||||
|
||||
case HALFWORD_WRITE:
|
||||
content = uart_read() << 8 | uart_read();
|
||||
*(UINT16*)paddr = content;
|
||||
paddr += 2;
|
||||
uart_write(cmd); // acknowledge by returning the command value
|
||||
break;
|
||||
|
||||
case EXECUTE:
|
||||
{
|
||||
tpFunc pFunc = (tpFunc)paddr;
|
||||
pFunc();
|
||||
uart_write(cmd); // acknowledge by returning the command value
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
{
|
||||
volatile UINT16* pPortB = (UINT16*)0x05FFFFC2;
|
||||
*pPortB |= 1 << 6; // bit 6 is red LED on
|
||||
uart_write(~cmd); // error acknowledge
|
||||
}
|
||||
|
||||
} // case
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
24
flash/minimon/minimon.h
Normal file
24
flash/minimon/minimon.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef _MINIMON_H
|
||||
#define _MINIMON_H
|
||||
|
||||
|
||||
// Commands
|
||||
// all multibyte values (address, halfwords) are passed as big endian
|
||||
// (most significant of the bytes first)
|
||||
|
||||
// set the address (all read/write commands will auto-increment it)
|
||||
#define BAUDRATE 0x00 // followed by BRR value; response: command byte
|
||||
#define ADDRESS 0x01 // followed by 4 bytes address; response: command byte
|
||||
#define BYTE_READ 0x02 // response: 1 byte content
|
||||
#define BYTE_WRITE 0x03 // followed by 1 byte content; response: command byte
|
||||
#define BYTE_READ16 0x04 // response: 16 bytes content
|
||||
#define BYTE_WRITE16 0x05 // followed by 16 bytes; response: command byte
|
||||
#define BYTE_FLASH 0x06 // followed by 1 byte content; response: command byte
|
||||
#define BYTE_FLASH16 0x07 // followed by 16 bytes; response: command byte
|
||||
#define HALFWORD_READ 0x08 // response: 2 byte content
|
||||
#define HALFWORD_WRITE 0x09 // followed by 2 byte content; response: command byte
|
||||
#define EXECUTE 0x0A // response: command byte if call returns
|
||||
#define VERSION 0x0B // response: version
|
||||
|
||||
|
||||
#endif // _MINIMON_H
|
||||
60
flash/minimon/minimon.lds
Normal file
60
flash/minimon/minimon.lds
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
OUTPUT_FORMAT(elf32-sh)
|
||||
INPUT(minimon.o)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
DRAM : ORIGIN = 0x09000000, LENGTH = 0x200000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.startvector :
|
||||
{
|
||||
*(.startvector)
|
||||
. = ALIGN(0x4);
|
||||
} > DRAM
|
||||
|
||||
.got :
|
||||
{
|
||||
*(.got)
|
||||
} > DRAM
|
||||
|
||||
.got.plt :
|
||||
{
|
||||
*(.got.plt)
|
||||
} > DRAM
|
||||
|
||||
.rela.got :
|
||||
{
|
||||
*(.rela.got)
|
||||
} > DRAM
|
||||
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(0x200);
|
||||
*(.entry)
|
||||
*(.text)
|
||||
. = ALIGN(0x4);
|
||||
} > DRAM
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
} > DRAM
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata)
|
||||
. = ALIGN(0x4);
|
||||
} > DRAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
*(.bss)
|
||||
} > DRAM
|
||||
|
||||
.stack :
|
||||
{
|
||||
*(.stack)
|
||||
} > DRAM
|
||||
}
|
||||
8
flash/uart_boot/README
Normal file
8
flash/uart_boot/README
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
(c) 2003 by Jörg Hohensohn
|
||||
|
||||
This is the client side for MiniMon, a command line program that communicates with it.
|
||||
It can be used to reflash a box from ground up, load a program like gdb stub or Rockbox,
|
||||
and other diagnostics.
|
||||
|
||||
Current implementation is for Windows, but with a different UART implementation
|
||||
it should work for other platforms (Linux) as well.
|
||||
738
flash/uart_boot/client.c
Normal file
738
flash/uart_boot/client.c
Normal file
|
|
@ -0,0 +1,738 @@
|
|||
// client.cpp : functions for monitor download and communication.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "scalar_types.h" // (U)INT8/16/32
|
||||
#include "Uart.h" // platform abstraction for UART
|
||||
#include "minimon.h" // protocol of my little monitor
|
||||
|
||||
// do the baudrate configuration for the Player
|
||||
int ConfigFirstlevelPlayer (tUartHandle serial_handle)
|
||||
{
|
||||
UINT32 result_nbr;
|
||||
|
||||
if(!UartConfig(serial_handle, 4800, eMARKPARITY, eTWOSTOPBITS, 8))
|
||||
{
|
||||
UINT32 dwErr = GET_LAST_ERR();
|
||||
printf("Error %d setting up COM params for baudrate byte\n", dwErr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// this will read as 0x19 when viewed with 2300 baud like the player does
|
||||
result_nbr = UartWrite(serial_handle, (UINT8*)"\x86\xC0", 2);
|
||||
if (result_nbr != 2)
|
||||
{
|
||||
UINT32 dwErr = GET_LAST_ERR();
|
||||
printf("Error %d setting up COM params for baudrate byte\n", dwErr);
|
||||
}
|
||||
|
||||
SLEEP(100); // wait for the chars to be sent, is there a better way?
|
||||
|
||||
// the read 0x19 means 14423 baud with 12 MHz
|
||||
if(!UartConfig(serial_handle, 14400, eNOPARITY, eONESTOPBIT, 8))
|
||||
{
|
||||
printf("Error setting up COM params for 1st level loader\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// do the baudrate configuration for the Recoder/FM
|
||||
int ConfigFirstlevelRecorder (tUartHandle serial_handle)
|
||||
{
|
||||
UINT32 result_nbr;
|
||||
|
||||
if(!UartConfig(serial_handle, 4800, eNOPARITY, eTWOSTOPBITS, 8))
|
||||
{
|
||||
UINT32 dwErr = GET_LAST_ERR();
|
||||
printf("Error %d setting up COM params for baudrate byte\n", dwErr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// this will read as 0x08 when viewed with 2120 baud like the recorder does
|
||||
result_nbr = UartWrite(serial_handle, (UINT8*)"\x00\x00", 2);
|
||||
if(result_nbr != 2)
|
||||
{
|
||||
printf("Error transmitting baudrate byte\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
SLEEP(100); // wait for the chars to be sent, is there a better way?
|
||||
|
||||
// the read 0x08 means 38400 baud with 11.0592 MHz
|
||||
if(!UartConfig(serial_handle, 38400, eNOPARITY, eONESTOPBIT, 8))
|
||||
{
|
||||
UINT32 dwErr = GET_LAST_ERR();
|
||||
printf("Error %d setting up COM params for 1st level loader\n", dwErr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// transfer a byte for the monitor download, with or without acknowledge
|
||||
int DownloadByte(tUartHandle serial_handle, unsigned char byte, bool bAck)
|
||||
{
|
||||
unsigned char received;
|
||||
bool bRecorder = true; // false for player
|
||||
|
||||
while (1)
|
||||
{
|
||||
UartWrite(serial_handle, &byte, 1);
|
||||
if (bAck)
|
||||
{
|
||||
UartRead(serial_handle, &received, 1);
|
||||
if (received == byte)
|
||||
{
|
||||
UartWrite(serial_handle, (UINT8*)"\x01", 1); // ack success
|
||||
break; // exit the loop
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error transmitting monitor byte 0x%02X, got 0x%0X\n", byte, received);
|
||||
UartWrite(serial_handle, (UINT8*)"\x00", 1); // ack fail, try again
|
||||
}
|
||||
}
|
||||
else
|
||||
break; // no loop
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// download our little monitor, the box must have been just freshly switched on for this to work
|
||||
int DownloadMonitor(tUartHandle serial_handle, bool bRecorder, char* szFilename)
|
||||
{
|
||||
FILE* pFile;
|
||||
size_t filesize;
|
||||
UINT8 byte;
|
||||
unsigned i;
|
||||
|
||||
// hard-coded parameters
|
||||
bool bAck = true; // configure if acknowledged download (without useful for remote pin boot)
|
||||
UINT32 TargetLoad = 0x0FFFF000; // target load address
|
||||
|
||||
pFile = fopen(szFilename, "rb");
|
||||
if (pFile == NULL)
|
||||
{
|
||||
printf("\nMonitor file %s not found, exiting\n", szFilename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// determine file size
|
||||
fseek(pFile, 0, SEEK_END);
|
||||
filesize = ftell(pFile);
|
||||
fseek(pFile, 0, SEEK_SET);
|
||||
|
||||
// This is _really_ tricky! The box expects a BRR value in a nonstandard baudrate,
|
||||
// which a PC can't generate. I'm using a higher one with some wild settings
|
||||
// to generate a pulse series that:
|
||||
// 1) looks like a stable byte when sampled with the nonstandard baudrate
|
||||
// 2) gives a BRR value to the box which results in a baudrate the PC can also use
|
||||
if (bRecorder)
|
||||
{
|
||||
ConfigFirstlevelRecorder(serial_handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
ConfigFirstlevelPlayer(serial_handle);
|
||||
}
|
||||
|
||||
UartWrite(serial_handle, bAck ? (UINT8*)"\x01" : (UINT8*)"\x00", 1); // ACK mode
|
||||
|
||||
// transmit the size, little endian
|
||||
DownloadByte(serial_handle, (UINT8)( filesize & 0xFF), bAck);
|
||||
DownloadByte(serial_handle, (UINT8)((filesize>>8) & 0xFF), bAck);
|
||||
DownloadByte(serial_handle, (UINT8)((filesize>>16) & 0xFF), bAck);
|
||||
DownloadByte(serial_handle, (UINT8)((filesize>>24) & 0xFF), bAck);
|
||||
|
||||
// transmit the load address, little endian
|
||||
DownloadByte(serial_handle, (UINT8)( TargetLoad & 0xFF), bAck);
|
||||
DownloadByte(serial_handle, (UINT8)((TargetLoad>>8) & 0xFF), bAck);
|
||||
DownloadByte(serial_handle, (UINT8)((TargetLoad>>16) & 0xFF), bAck);
|
||||
DownloadByte(serial_handle, (UINT8)((TargetLoad>>24) & 0xFF), bAck);
|
||||
|
||||
// transmit the command byte
|
||||
DownloadByte(serial_handle, 0xFF, bAck); // 0xFF means execute the transferred image
|
||||
|
||||
// transmit the image
|
||||
for (i=0; i<filesize; i++)
|
||||
{
|
||||
fread(&byte, 1, 1, pFile);
|
||||
DownloadByte(serial_handle, byte, bAck);
|
||||
}
|
||||
|
||||
fclose (pFile);
|
||||
|
||||
// now the image should have been started, red LED off
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// wait for a fixed string to be received (no foolproof algorithm,
|
||||
// may overlook if the searched string contains repeatitions)
|
||||
int WaitForString(tUartHandle serial_handle, char* pszWait)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned char received;
|
||||
|
||||
while(pszWait[i] != '\0')
|
||||
{
|
||||
UartRead(serial_handle, &received, 1);
|
||||
|
||||
printf("%c", received); // debug
|
||||
|
||||
if (received == pszWait[i])
|
||||
i++; // continue
|
||||
else
|
||||
i=0; // mismatch, start over
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// send a sting and check the echo
|
||||
int SendWithEcho(tUartHandle serial_handle, char* pszSend)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned char received;
|
||||
|
||||
while(pszSend[i] != '\0')
|
||||
{
|
||||
UartWrite(serial_handle, (unsigned char*)(pszSend + i), 1); // send char
|
||||
do
|
||||
{
|
||||
UartRead(serial_handle, &received, 1); // receive echo
|
||||
printf("%c", received); // debug
|
||||
}
|
||||
while (received != pszSend[i]); // should normally be equal
|
||||
i++; // next char
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// rarely used variant: download our monitor using the built-in Archos monitor
|
||||
int DownloadArchosMonitor(tUartHandle serial_handle, char* szFilename)
|
||||
{
|
||||
FILE* pFile;
|
||||
size_t filesize;
|
||||
UINT8 byte;
|
||||
UINT16 checksum = 0;
|
||||
unsigned i;
|
||||
|
||||
// the onboard monitor uses 115200 baud
|
||||
if(!UartConfig(serial_handle, 115200, eNOPARITY, eONESTOPBIT, 8))
|
||||
{
|
||||
UINT32 dwErr = GET_LAST_ERR();
|
||||
printf("Error %d setting up COM params for baudrate %d\n", dwErr, 115200);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// wait for receiving "#SERIAL#"
|
||||
WaitForString(serial_handle, "#SERIAL#");
|
||||
|
||||
// send magic "SRL" command to get interactive mode
|
||||
SendWithEcho(serial_handle, "SRL\r");
|
||||
|
||||
// wait for menu completion: "ROOT>" at the end
|
||||
WaitForString(serial_handle, "ROOT>");
|
||||
|
||||
// send upload command "UP"
|
||||
SendWithEcho(serial_handle, "UP\r");
|
||||
|
||||
pFile = fopen(szFilename, "rb");
|
||||
if (pFile == NULL)
|
||||
{
|
||||
printf("\nMonitor file %s not found, exiting\n", szFilename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// determine file size
|
||||
fseek(pFile, 0, SEEK_END);
|
||||
filesize = ftell(pFile);
|
||||
fseek(pFile, 0, SEEK_SET);
|
||||
|
||||
// calculate checksum
|
||||
for (i=0; i<filesize; i++)
|
||||
{
|
||||
fread(&byte, 1, 1, pFile);
|
||||
checksum += byte;
|
||||
}
|
||||
fseek(pFile, 0, SEEK_SET);
|
||||
|
||||
// send header
|
||||
|
||||
// size as 32 bit little endian
|
||||
byte = (UINT8)( filesize & 0xFF);
|
||||
UartWrite(serial_handle, &byte, 1);
|
||||
byte = (UINT8)((filesize>>8) & 0xFF);
|
||||
UartWrite(serial_handle, &byte, 1);
|
||||
byte = (UINT8)((filesize>>16) & 0xFF);
|
||||
UartWrite(serial_handle, &byte, 1);
|
||||
byte = (UINT8)((filesize>>24) & 0xFF);
|
||||
UartWrite(serial_handle, &byte, 1);
|
||||
|
||||
// checksum as 16 bit little endian
|
||||
byte = (UINT8)( checksum & 0xFF);
|
||||
UartWrite(serial_handle, &byte, 1);
|
||||
byte = (UINT8)((checksum>>8) & 0xFF);
|
||||
UartWrite(serial_handle, &byte, 1);
|
||||
|
||||
UartWrite(serial_handle, (unsigned char*)"\x00", 1); // kind (3 means flash)
|
||||
UartWrite(serial_handle, (unsigned char*)"\x00", 1); // ignored byte
|
||||
|
||||
// wait for monitor to accept data
|
||||
WaitForString(serial_handle, "#OKCTRL#");
|
||||
|
||||
// transmit the image
|
||||
for (i=0; i<filesize; i++)
|
||||
{
|
||||
fread(&byte, 1, 1, pFile);
|
||||
UartWrite(serial_handle, &byte, 1); // payload
|
||||
}
|
||||
fclose (pFile);
|
||||
|
||||
UartWrite(serial_handle, (unsigned char*)"\x00", 1); // ignored byte
|
||||
|
||||
// wait for menu completion: "ROOT>" at the end
|
||||
WaitForString(serial_handle, "ROOT>");
|
||||
|
||||
// send start program command "SPRO"
|
||||
SendWithEcho(serial_handle, "SPRO\r");
|
||||
|
||||
SLEEP(100); // wait a little while for startup
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/********** Target functions using the Monitor Protocol **********/
|
||||
|
||||
// read a byte using the target monitor
|
||||
UINT8 ReadByte(tUartHandle serial_handle, UINT32 addr)
|
||||
{
|
||||
UINT8 send;
|
||||
UINT8 received;
|
||||
|
||||
// send the address command
|
||||
send = ADDRESS;
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
|
||||
// transmit the address, big endian
|
||||
send = (UINT8)((addr>>24) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)((addr>>16) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)((addr>>8) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)(addr & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
|
||||
UartRead(serial_handle, &received, 1); // response
|
||||
if (received != ADDRESS)
|
||||
{
|
||||
printf("Protocol error!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// send the read command
|
||||
send = BYTE_READ;
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
|
||||
UartRead(serial_handle, &received, 1); // response
|
||||
|
||||
return received;
|
||||
}
|
||||
|
||||
|
||||
// write a byte using the target monitor
|
||||
int WriteByte(tUartHandle serial_handle, UINT32 addr, UINT8 byte)
|
||||
{
|
||||
UINT8 send;
|
||||
UINT8 received;
|
||||
|
||||
// send the address command
|
||||
send = ADDRESS;
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
|
||||
// transmit the address, big endian
|
||||
send = (UINT8)((addr>>24) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)((addr>>16) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)((addr>>8) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)(addr & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
|
||||
UartRead(serial_handle, &received, 1); // response
|
||||
if (received != ADDRESS)
|
||||
{
|
||||
printf("Protocol error, receiced 0x%02X!\n", received);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// send the write command
|
||||
send = BYTE_WRITE;
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
|
||||
// transmit the data
|
||||
UartWrite(serial_handle, &byte, 1);
|
||||
|
||||
UartRead(serial_handle, &received, 1); // response
|
||||
|
||||
if (received != BYTE_WRITE)
|
||||
{
|
||||
printf("Protocol error!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// read many bytes using the target monitor
|
||||
int ReadByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer)
|
||||
{
|
||||
UINT8 send, received;
|
||||
|
||||
// send the address command
|
||||
send = ADDRESS;
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
|
||||
// transmit the address, big endian
|
||||
send = (UINT8)((addr>>24) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)((addr>>16) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)((addr>>8) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)(addr & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
|
||||
UartRead(serial_handle, &received, 1); // response
|
||||
if (received != ADDRESS)
|
||||
{
|
||||
printf("Protocol error!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (size)
|
||||
{
|
||||
if (size >= 16)
|
||||
{ // we can use a "burst" command
|
||||
send = BYTE_READ16;
|
||||
UartWrite(serial_handle, &send, 1); // send the read command
|
||||
UartRead(serial_handle, pBuffer, 16); // data response
|
||||
pBuffer += 16;
|
||||
size -= 16;
|
||||
}
|
||||
else
|
||||
{ // use single byte command
|
||||
send = BYTE_READ;
|
||||
UartWrite(serial_handle, &send, 1); // send the read command
|
||||
UartRead(serial_handle, pBuffer++, 1); // data response
|
||||
size--;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// write many bytes using the target monitor
|
||||
int WriteByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer)
|
||||
{
|
||||
UINT8 send, received;
|
||||
|
||||
// send the address command
|
||||
send = ADDRESS;
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
|
||||
// transmit the address, big endian
|
||||
send = (UINT8)((addr>>24) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)((addr>>16) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)((addr>>8) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)(addr & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
|
||||
UartRead(serial_handle, &received, 1); // response
|
||||
if (received != ADDRESS)
|
||||
{
|
||||
printf("Protocol error!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (size)
|
||||
{
|
||||
if (size >= 16)
|
||||
{ // we can use a "burst" command
|
||||
send = BYTE_WRITE16;
|
||||
UartWrite(serial_handle, &send, 1); // send the write command
|
||||
UartWrite(serial_handle, pBuffer, 16); // transmit the data
|
||||
UartRead(serial_handle, &received, 1); // response
|
||||
if (received != BYTE_WRITE16)
|
||||
{
|
||||
printf("Protocol error!\n");
|
||||
return 1;
|
||||
}
|
||||
pBuffer += 16;
|
||||
size -= 16;
|
||||
}
|
||||
else
|
||||
{ // use single byte command
|
||||
send = BYTE_WRITE;
|
||||
UartWrite(serial_handle, &send, 1); // send the write command
|
||||
UartWrite(serial_handle, pBuffer++, 1); // transmit the data
|
||||
UartRead(serial_handle, &received, 1); // response
|
||||
if (received != BYTE_WRITE)
|
||||
{
|
||||
printf("Protocol error!\n");
|
||||
return 1;
|
||||
}
|
||||
size--;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// write many bytes using the target monitor
|
||||
int FlashByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer)
|
||||
{
|
||||
UINT8 send, received;
|
||||
|
||||
// send the address command
|
||||
send = ADDRESS;
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
|
||||
// transmit the address, big endian
|
||||
send = (UINT8)((addr>>24) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)((addr>>16) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)((addr>>8) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)(addr & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
|
||||
UartRead(serial_handle, &received, 1); // response
|
||||
if (received != ADDRESS)
|
||||
{
|
||||
printf("Protocol error!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (size)
|
||||
{
|
||||
if (size >= 16)
|
||||
{ // we can use a "burst" command
|
||||
send = BYTE_FLASH16;
|
||||
UartWrite(serial_handle, &send, 1); // send the write command
|
||||
UartWrite(serial_handle, pBuffer, 16); // transmit the data
|
||||
UartRead(serial_handle, &received, 1); // response
|
||||
if (received != BYTE_FLASH16)
|
||||
{
|
||||
printf("Protocol error!\n");
|
||||
return 1;
|
||||
}
|
||||
pBuffer += 16;
|
||||
size -= 16;
|
||||
}
|
||||
else
|
||||
{ // use single byte command
|
||||
send = BYTE_FLASH;
|
||||
UartWrite(serial_handle, &send, 1); // send the write command
|
||||
UartWrite(serial_handle, pBuffer++, 1); // transmit the data
|
||||
UartRead(serial_handle, &received, 1); // response
|
||||
if (received != BYTE_FLASH)
|
||||
{
|
||||
printf("Protocol error!\n");
|
||||
return 1;
|
||||
}
|
||||
size--;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// read a 16bit halfword using the target monitor
|
||||
UINT16 ReadHalfword(tUartHandle serial_handle, UINT32 addr)
|
||||
{
|
||||
UINT8 send;
|
||||
UINT8 received;
|
||||
UINT16 halfword;
|
||||
|
||||
// send the address command
|
||||
send = ADDRESS;
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
|
||||
// transmit the address, big endian
|
||||
send = (UINT8)((addr>>24) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)((addr>>16) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)((addr>>8) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)(addr & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
|
||||
UartRead(serial_handle, &received, 1); // response
|
||||
if (received != ADDRESS)
|
||||
{
|
||||
printf("Protocol error!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// send the read command
|
||||
send = HALFWORD_READ;
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
|
||||
UartRead(serial_handle, &received, 1); // response
|
||||
halfword = received << 8; // highbyte
|
||||
UartRead(serial_handle, &received, 1);
|
||||
halfword |= received; // lowbyte
|
||||
|
||||
return halfword;
|
||||
}
|
||||
|
||||
|
||||
// write a 16bit halfword using the target monitor
|
||||
int WriteHalfword(tUartHandle serial_handle, UINT32 addr, UINT16 halfword)
|
||||
{
|
||||
UINT8 send;
|
||||
UINT8 received;
|
||||
|
||||
// send the address command
|
||||
send = ADDRESS;
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
|
||||
// transmit the address, big endian
|
||||
send = (UINT8)((addr>>24) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)((addr>>16) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)((addr>>8) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)(addr & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
|
||||
UartRead(serial_handle, &received, 1); // response
|
||||
if (received != ADDRESS)
|
||||
{
|
||||
printf("Protocol error!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// send the write command
|
||||
send = HALFWORD_WRITE;
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
|
||||
// transmit the data
|
||||
send = halfword >> 8; // highbyte
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = halfword & 0xFF; // lowbyte
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
|
||||
UartRead(serial_handle, &received, 1); // response
|
||||
|
||||
if (received != HALFWORD_WRITE)
|
||||
{
|
||||
printf("Protocol error!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// change baudrate using target monitor
|
||||
int SetTargetBaudrate(tUartHandle serial_handle, long lClock, long lBaudrate)
|
||||
{
|
||||
UINT8 send;
|
||||
UINT8 received;
|
||||
UINT8 brr;
|
||||
long lBRR;
|
||||
|
||||
lBRR = lClock / lBaudrate;
|
||||
lBRR = ((lBRR + 16) / 32) - 1; // with rounding
|
||||
brr = (UINT8)lBRR;
|
||||
|
||||
// send the command
|
||||
send = BAUDRATE;
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
UartWrite(serial_handle, &brr, 1); // send the BRR value
|
||||
UartRead(serial_handle, &received, 1); // response ack
|
||||
|
||||
if (received != BAUDRATE)
|
||||
{ // bad situation, now we're unclear about the baudrate of the target
|
||||
printf("Protocol error!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
SLEEP(100); // give it some time to settle
|
||||
|
||||
// change our baudrate, too
|
||||
UartConfig(serial_handle, lBaudrate, eNOPARITY, eONESTOPBIT, 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// call a subroutine using the target monitor
|
||||
int Execute(tUartHandle serial_handle, UINT32 addr, bool bReturns)
|
||||
{
|
||||
UINT8 send;
|
||||
UINT8 received;
|
||||
|
||||
// send the address command
|
||||
send = ADDRESS;
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
|
||||
// transmit the address, big endian
|
||||
send = (UINT8)((addr>>24) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)((addr>>16) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)((addr>>8) & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
send = (UINT8)(addr & 0xFF);
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
|
||||
UartRead(serial_handle, &received, 1); // response
|
||||
if (received != ADDRESS)
|
||||
{
|
||||
printf("Protocol error!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// send the execute command
|
||||
send = EXECUTE;
|
||||
UartWrite(serial_handle, &send, 1);
|
||||
if (bReturns)
|
||||
{ // we expect the call to return control to minimon
|
||||
UartRead(serial_handle, &received, 1); // response
|
||||
|
||||
if (received != EXECUTE)
|
||||
{
|
||||
printf("Protocol error!\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
21
flash/uart_boot/client.h
Normal file
21
flash/uart_boot/client.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef _CLIENT_H
|
||||
#define _CLIENT_H
|
||||
|
||||
|
||||
// setup function for monitor download
|
||||
int DownloadMonitor(tUartHandle serial_handle, bool bRecorder, char* szFilename);
|
||||
int DownloadArchosMonitor(tUartHandle serial_handle, char* szFilename);
|
||||
|
||||
// target functions using the Monitor Protocol
|
||||
UINT8 ReadByte(tUartHandle serial_handle, UINT32 addr);
|
||||
int WriteByte(tUartHandle serial_handle, UINT32 addr, UINT8 byte);
|
||||
int ReadByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer);
|
||||
int WriteByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer);
|
||||
int FlashByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer);
|
||||
UINT16 ReadHalfword(tUartHandle serial_handle, UINT32 addr);
|
||||
int WriteHalfword(tUartHandle serial_handle, UINT32 addr, UINT16 halfword);
|
||||
int SetTargetBaudrate(tUartHandle serial_handle, long lClock, long lBaudrate);
|
||||
int Execute(tUartHandle serial_handle, UINT32 addr, bool bReturns);
|
||||
|
||||
|
||||
#endif
|
||||
77
flash/uart_boot/flash.c
Normal file
77
flash/uart_boot/flash.c
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
// flash.cpp : higher-level functions for flashing the chip
|
||||
//
|
||||
|
||||
#include "scalar_types.h" // (U)INT8/16/32
|
||||
#include "Uart.h" // platform abstraction for UART
|
||||
#include "client.h" // client functions
|
||||
|
||||
|
||||
// read the manufacturer and device ID
|
||||
int ReadID(tUartHandle serial_handle, UINT32 base, UINT8* pManufacturerID, UINT8* pDeviceID)
|
||||
{
|
||||
base &= 0xFFF80000; // round down to 512k align, to make shure
|
||||
|
||||
WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
|
||||
WriteByte(serial_handle, base + 0x2AAA, 0x55);
|
||||
WriteByte(serial_handle, base + 0x5555, 0x90); // ID command
|
||||
SLEEP(20); // Atmel wants 20ms pause here
|
||||
|
||||
*pManufacturerID = ReadByte(serial_handle, base + 0);
|
||||
*pDeviceID = ReadByte(serial_handle, base + 1);
|
||||
|
||||
WriteByte(serial_handle, base + 0, 0xF0); // reset flash (back to normal read mode)
|
||||
SLEEP(20); // Atmel wants 20ms pause here
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// erase the sector which contains the given address
|
||||
int EraseSector(tUartHandle serial_handle, UINT32 address)
|
||||
{
|
||||
UINT32 base = address & 0xFFF80000; // round down to 512k align
|
||||
|
||||
WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
|
||||
WriteByte(serial_handle, base + 0x2AAA, 0x55);
|
||||
WriteByte(serial_handle, base + 0x5555, 0x80); // eraze command
|
||||
WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
|
||||
WriteByte(serial_handle, base + 0x2AAA, 0x55);
|
||||
WriteByte(serial_handle, address, 0x30); // eraze the sector
|
||||
SLEEP(25); // sector eraze time: 25ms
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// erase the whole flash
|
||||
int EraseChip(tUartHandle serial_handle, UINT32 base)
|
||||
{
|
||||
base &= 0xFFF80000; // round down to 512k align, to make shure
|
||||
|
||||
WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
|
||||
WriteByte(serial_handle, base + 0x2AAA, 0x55);
|
||||
WriteByte(serial_handle, base + 0x5555, 0x80); // eraze command
|
||||
WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
|
||||
WriteByte(serial_handle, base + 0x2AAA, 0x55);
|
||||
WriteByte(serial_handle, base + 0x5555, 0x10); // chip eraze command
|
||||
SLEEP(100); // chip eraze time: 100ms
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// program a bunch of bytes "by hand"
|
||||
int ProgramBytes(tUartHandle serial_handle, UINT32 address, UINT8* pData, UINT32 size)
|
||||
{
|
||||
UINT32 base = address & 0xFFF80000; // round down to 512k align
|
||||
|
||||
while (size--)
|
||||
{
|
||||
WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
|
||||
WriteByte(serial_handle, base + 0x2AAA, 0x55);
|
||||
WriteByte(serial_handle, base + 0x5555, 0xA0); // byte program command
|
||||
WriteByte(serial_handle, address++, *pData++);
|
||||
// UART protocol is slow enough such that I don't have to wait 20us here
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
9
flash/uart_boot/flash.h
Normal file
9
flash/uart_boot/flash.h
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef _FLASH_H
|
||||
#define _FLASH_H
|
||||
|
||||
int ReadID(tUartHandle serial_handle, UINT32 base, UINT8* pManufacturerID, UINT8* pDeviceID);
|
||||
int EraseSector(tUartHandle serial_handle, UINT32 address);
|
||||
int EraseChip(tUartHandle serial_handle, UINT32 base);
|
||||
int ProgramBytes(tUartHandle serial_handle, UINT32 address, UINT8* pData, UINT32 size);
|
||||
|
||||
#endif
|
||||
23
flash/uart_boot/minimon.h
Normal file
23
flash/uart_boot/minimon.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef _MINIMON_H
|
||||
#define _MINIMON_H
|
||||
|
||||
|
||||
// Commands
|
||||
// all multibyte values (address, halfwords) are passed as big endian
|
||||
// (most significant of the bytes first)
|
||||
|
||||
// set the address (all read/write commands will auto-increment it)
|
||||
#define BAUDRATE 0x00 // followed by BRR value; response: command byte
|
||||
#define ADDRESS 0x01 // followed by 4 bytes address; response: command byte
|
||||
#define BYTE_READ 0x02 // response: 1 byte content
|
||||
#define BYTE_WRITE 0x03 // followed by 1 byte content; response: command byte
|
||||
#define BYTE_READ16 0x04 // response: 16 bytes content
|
||||
#define BYTE_WRITE16 0x05 // followed by 16 bytes; response: command byte
|
||||
#define BYTE_FLASH 0x06 // followed by 1 byte content; response: command byte
|
||||
#define BYTE_FLASH16 0x07 // followed by 16 bytes; response: command byte
|
||||
#define HALFWORD_READ 0x08 // response: 2 byte content
|
||||
#define HALFWORD_WRITE 0x09 // followed by 2 byte content; response: command byte
|
||||
#define EXECUTE 0x0A // response: command byte if call returns
|
||||
|
||||
|
||||
#endif // _MINIMON_H
|
||||
44
flash/uart_boot/scalar_types.h
Normal file
44
flash/uart_boot/scalar_types.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
// this is meant to resolve platform dependency
|
||||
|
||||
#ifndef _SCALAR_TYPES_H
|
||||
#define _SCALAR_TYPES_H
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#define SLEEP Sleep
|
||||
#define GET_LAST_ERR GetLastError
|
||||
#endif
|
||||
// ToDo: add stuff for Linux
|
||||
|
||||
|
||||
|
||||
#ifndef UINT8
|
||||
#define UINT8 unsigned char
|
||||
#endif
|
||||
|
||||
#ifndef UINT16
|
||||
#define UINT16 unsigned short
|
||||
#endif
|
||||
|
||||
#ifndef UINT32
|
||||
#define UINT32 unsigned long
|
||||
#endif
|
||||
|
||||
#ifndef bool
|
||||
#define bool int
|
||||
#endif
|
||||
|
||||
#ifndef true
|
||||
#define true 1
|
||||
#endif
|
||||
|
||||
#ifndef false
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
56
flash/uart_boot/uart.h
Normal file
56
flash/uart_boot/uart.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
// A general definition for the required UART functionality.
|
||||
// This will be used to gain platform abstraction.
|
||||
|
||||
#ifndef _UART_H
|
||||
#define _UART_H
|
||||
|
||||
// data types
|
||||
|
||||
typedef void* tUartHandle;
|
||||
#define INVALID_UART_HANDLE (tUartHandle)-1
|
||||
|
||||
typedef enum
|
||||
{
|
||||
eNOPARITY,
|
||||
eODDPARITY,
|
||||
eEVENPARITY,
|
||||
eMARKPARITY,
|
||||
eSPACEPARITY,
|
||||
} tParity;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
eONESTOPBIT,
|
||||
eONE5STOPBITS,
|
||||
eTWOSTOPBITS,
|
||||
} tStopBits;
|
||||
|
||||
|
||||
// prototypes
|
||||
|
||||
tUartHandle UartOpen( // returns NULL on error
|
||||
char* szPortName); // COMx for windows
|
||||
|
||||
bool UartConfig( // returns true on success, false on error
|
||||
tUartHandle handle, // the handle returned from UartOpen()
|
||||
long lBaudRate, // must be one of the "standard" baudrates
|
||||
tParity nParity, // what kind of parity
|
||||
tStopBits nStopBits, // how many stop bits
|
||||
int nByteSize); // size of the "payload", can be 5 to 8
|
||||
|
||||
long UartWrite( // returns how much data was actually transmitted
|
||||
tUartHandle handle, // the handle returned from UartOpen()
|
||||
unsigned char* pData, // pointer to the data to be transmitted
|
||||
long lSize); // how many bytes
|
||||
|
||||
long UartRead( // returns how much data was actually received
|
||||
tUartHandle handle, // the handle returned from UartOpen()
|
||||
unsigned char* pBuffer, // pointer to the destination
|
||||
long lSize); // how many bytes to read (pBuffer must have enough room)
|
||||
|
||||
|
||||
void UartClose(tUartHandle handle);
|
||||
|
||||
|
||||
|
||||
#endif // _UART_H
|
||||
337
flash/uart_boot/uart_boot.c
Normal file
337
flash/uart_boot/uart_boot.c
Normal file
|
|
@ -0,0 +1,337 @@
|
|||
// uart_boot.cpp : Defines the entry point for the console application.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "scalar_types.h" // (U)INT8/16/32
|
||||
#include "Uart.h" // platform abstraction for UART
|
||||
#include "client.h" // client functions
|
||||
#include "flash.h" // flash high level functions
|
||||
|
||||
// command line configuration: what shall we do?
|
||||
struct
|
||||
{
|
||||
char* szPort; // COM port to use
|
||||
bool bRecorder; // it's a recorder
|
||||
bool bArchos; // use the Archos monitor to load, instead of UART boot
|
||||
bool bSpindown; // spindown the harddisk
|
||||
bool bReadID; // read manufacturer+device ID
|
||||
char* szFlashfile; // file to be programmed
|
||||
char* szDumpfile; // file to dump into
|
||||
char* szExecfile; // file with the executable
|
||||
bool bTest; // debug action
|
||||
bool bBlink; // blink red LED
|
||||
bool bNoDownload;
|
||||
} gCmd;
|
||||
|
||||
|
||||
int ProcessCmdLine(int argc, char* argv[])
|
||||
{
|
||||
argc--; // exclude our name
|
||||
argv++;
|
||||
|
||||
memset(&gCmd, 0, sizeof(gCmd));
|
||||
|
||||
if (argc == 0)
|
||||
{
|
||||
printf("Usage: uart_boot [-option {filename}]\n");
|
||||
printf(" uses activated UART boot mod, box has to be fresh started\n");
|
||||
printf("The order of the options does not matter, one letter is sufficient.\n");
|
||||
printf("Possible options are (in the order of later processing):\n");
|
||||
printf("-port <name of COM port to use>\n");
|
||||
printf("-recorder (this is a recorder/FM, default is player if not specified)\n");
|
||||
printf("-archos (use Archos bootloader, this one needs powerup while program waits)\n");
|
||||
printf("-nodownload (no MiniMon download, it's already active)\n");
|
||||
printf("-spindown (spindown the harddisk, else it stays on by default)\n");
|
||||
printf("-id (read manufacturer and device ID of flash, no checks)\n");
|
||||
printf("-flash <filename of binary to program into flash>\n");
|
||||
printf("-dump <filename to write flash content to>\n");
|
||||
printf("-exec <filename of executable for 0x09000000:0x09000200>\n");
|
||||
printf("-test (some test action currently under development, don't use!)\n");
|
||||
printf("-blink (blink red LED forever, meant as diagnostics)\n");
|
||||
printf("\n");
|
||||
printf("Examples:\n");
|
||||
printf("uart_boot -r -p COM1 -s -f flashfile.bin -d dumpfile.bin\n");
|
||||
printf(" recorder on COM1, spindown HD, program and dump (for e.g. offline verify)\n");
|
||||
printf("uart_boot -r -p COM2 -e rockbox.bin\n");
|
||||
printf(" recorder on COM2, load Rockbox from file and start it\n");
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
||||
while (argc)
|
||||
{
|
||||
if (!strncmp("-port", *argv, 2))
|
||||
{
|
||||
gCmd.szPort = *++argv;
|
||||
if (--argc <= 0 || **argv == '-')
|
||||
{
|
||||
printf("No argument given for option %s, aborting.\n", argv[-1]);
|
||||
exit (-2);
|
||||
}
|
||||
}
|
||||
else if (!strncmp("-recorder", *argv, 2))
|
||||
{
|
||||
gCmd.bRecorder = true;
|
||||
}
|
||||
else if (!strncmp("-archos", *argv, 2))
|
||||
{
|
||||
gCmd.bArchos = true;
|
||||
}
|
||||
else if (!strncmp("-nodownload", *argv, 2))
|
||||
{
|
||||
gCmd.bNoDownload = true;
|
||||
}
|
||||
else if (!strncmp("-spindown", *argv, 2))
|
||||
{
|
||||
gCmd.bSpindown = true;
|
||||
}
|
||||
else if (!strncmp("-id", *argv, 2))
|
||||
{
|
||||
gCmd.bReadID = true;
|
||||
}
|
||||
else if (!strncmp("-flash", *argv, 2))
|
||||
{
|
||||
gCmd.szFlashfile = *++argv;
|
||||
if (--argc <= 0 || **argv == '-')
|
||||
{
|
||||
printf("No argument given for option %s, aborting.\n", argv[-1]);
|
||||
exit (-2);
|
||||
}
|
||||
}
|
||||
else if (!strncmp("-dump", *argv, 2))
|
||||
{
|
||||
gCmd.szDumpfile = *++argv;
|
||||
if (--argc <= 0 || **argv == '-')
|
||||
{
|
||||
printf("No argument given for option %s, aborting.\n", argv[-1]);
|
||||
exit (-3);
|
||||
}
|
||||
}
|
||||
else if (!strncmp("-exec", *argv, 2))
|
||||
{
|
||||
gCmd.szExecfile = *++argv;
|
||||
if (--argc <= 0 || **argv == '-')
|
||||
{
|
||||
printf("No argument given for option %s, aborting.\n", argv[-1]);
|
||||
exit (-4);
|
||||
}
|
||||
}
|
||||
else if (!strncmp("-test", *argv, 2))
|
||||
{
|
||||
gCmd.bTest = true;
|
||||
}
|
||||
else if (!strncmp("-blink", *argv, 2))
|
||||
{
|
||||
gCmd.bBlink = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Unknown option %s, aborting. Use 'uart_boot' without options for help.\n", *argv);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
tUartHandle serial_handle;
|
||||
UINT16 reg;
|
||||
FILE* pFile;
|
||||
size_t size;
|
||||
UINT8 abFirmware[512*1024]; // blocksize
|
||||
memset(abFirmware, 0xFF, sizeof(abFirmware));
|
||||
|
||||
ProcessCmdLine(argc, argv); // what to do
|
||||
|
||||
if (!gCmd.szPort)
|
||||
{
|
||||
printf("No serial port given, use 'uart_boot' without parameters for options.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
serial_handle = UartOpen(gCmd.szPort); // opening serial port
|
||||
if (serial_handle == NULL)
|
||||
{
|
||||
printf("Cannot open port %s\n", gCmd.szPort);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (gCmd.bNoDownload)
|
||||
{ // just set our speed
|
||||
if (!UartConfig(serial_handle, gCmd.bRecorder ? 115200 : 14400, eNOPARITY, eONESTOPBIT, 8))
|
||||
{
|
||||
printf("Error setting up COM params\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // download the monitor program
|
||||
if (gCmd.bArchos)
|
||||
{
|
||||
printf("Waiting for box startup to download monitor...");
|
||||
DownloadArchosMonitor(serial_handle, "minimon_v2.bin"); // load the monitor image
|
||||
printf("\b\b\b done.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Downloading monitor...");
|
||||
DownloadMonitor(serial_handle, gCmd.bRecorder, "minimon.bin"); // load the monitor image
|
||||
// From now on, we can talk to the box.
|
||||
printf("\b\b\b done.\n");
|
||||
|
||||
if (gCmd.bRecorder)
|
||||
{ // we can be faster
|
||||
SetTargetBaudrate(serial_handle, 11059200, 115200); // set to 115200
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do the action
|
||||
|
||||
if (gCmd.bSpindown)
|
||||
{
|
||||
// spindown the disk (works only for master)
|
||||
UINT32 ata; // address of ATA_ALT_STATUS
|
||||
printf("Harddisk spindown...");
|
||||
ata = (gCmd.bRecorder && (ReadHalfword(serial_handle, 0x020000FC) & 0x0100)) ? 0x06200206 : 0x06200306;
|
||||
WriteHalfword(serial_handle, 0x05FFFFCA, 0xBF99); // PACR2 (was 0xFF99)
|
||||
WriteHalfword(serial_handle, 0x05FFFFC4, 0x0280); // PAIOR (was 0x0000)
|
||||
WriteHalfword(serial_handle, 0x05FFFFC0, 0xA27F); // PADR (was 0xA0FF)
|
||||
while (ReadByte(serial_handle, ata) & 0x80); // ATA_ALT_STATUS & STATUS_BSY
|
||||
WriteByte(serial_handle, 0x06100107, 0xE0); // ATA_COMMAND = CMD_STANDBY_IMMEDIATE;
|
||||
//while (ReadByte(serial_handle, ata) & 0x80); // ATA_ALT_STATUS & STATUS_BSY
|
||||
printf("\b\b\b done.\n");
|
||||
}
|
||||
|
||||
|
||||
if (gCmd.bReadID)
|
||||
{
|
||||
UINT8 bMan, bID;
|
||||
ReadID(serial_handle, 0x02000000, &bMan, &bID);
|
||||
printf("Manufacturer ID = 0x%02X, Device ID = 0x%02X\n", bMan, bID);
|
||||
}
|
||||
|
||||
|
||||
if (gCmd.szFlashfile)
|
||||
{
|
||||
// flash a firmware file
|
||||
printf("Flashing file %s...", gCmd.szFlashfile);
|
||||
pFile = fopen(gCmd.szFlashfile, "rb");
|
||||
if (pFile == NULL)
|
||||
{
|
||||
printf("\nFlash file %s not found, exiting.\n", gCmd.szFlashfile);
|
||||
return -2;
|
||||
}
|
||||
size = fread(abFirmware, 1, sizeof(abFirmware), pFile);
|
||||
fclose (pFile);
|
||||
|
||||
EraseChip(serial_handle, 0x02000000);
|
||||
FlashByteMultiple(serial_handle, 0x02000000, size, abFirmware);
|
||||
printf("\b\b\b done.\n");
|
||||
}
|
||||
|
||||
|
||||
if (gCmd.szDumpfile)
|
||||
{
|
||||
// dump the flash content
|
||||
printf("Writing flash dump into file %s...", gCmd.szDumpfile);
|
||||
ReadByteMultiple(serial_handle, 0x02000000, sizeof(abFirmware), abFirmware);
|
||||
pFile = fopen(gCmd.szDumpfile, "wb");
|
||||
if (pFile == NULL)
|
||||
{
|
||||
printf("\nDump file %s cannot be opened, exiting.\n", gCmd.szDumpfile);
|
||||
return -3;
|
||||
}
|
||||
fwrite(abFirmware, 1, sizeof(abFirmware), pFile);
|
||||
fclose (pFile);
|
||||
printf("\b\b\b done.\n");
|
||||
}
|
||||
|
||||
|
||||
if (gCmd.szExecfile)
|
||||
{
|
||||
UINT32 size;
|
||||
|
||||
printf("Downloading program...");
|
||||
|
||||
// init the DRAM controller like the flash boot does
|
||||
reg = ReadHalfword(serial_handle, 0x05FFFFCA); // PACR2
|
||||
reg &= 0xFFFB; // PA1 config: /RAS
|
||||
reg |= 0x0008;
|
||||
WriteHalfword(serial_handle, 0x05FFFFCA, reg); // PACR2
|
||||
reg = 0xAFFF; // CS1, CS3 config: /CASH. /CASL
|
||||
WriteHalfword(serial_handle, 0x05FFFFEE, reg); // CASCR
|
||||
reg = ReadHalfword(serial_handle, 0x05FFFFA0); // BCR
|
||||
reg |= 0x8000; // DRAM enable, default bus
|
||||
WriteHalfword(serial_handle, 0x05FFFFA0, reg); // BCR
|
||||
reg = ReadHalfword(serial_handle, 0x05FFFFA2); // WCR1
|
||||
reg &= 0xFDFD; // 1-cycle CAS
|
||||
WriteHalfword(serial_handle, 0x05FFFFA2, reg); // WCR1
|
||||
reg = 0x0E00; // CAS 35%, multiplexed, 10 bit row addr.
|
||||
WriteHalfword(serial_handle, 0x05FFFFA8, reg); // DCR
|
||||
reg = 0x5AB0; // refresh, 4 cycle waitstate
|
||||
WriteHalfword(serial_handle, 0x05FFFFAC, reg); // RCR
|
||||
reg = 0x9605; // refresh constant
|
||||
WriteHalfword(serial_handle, 0x05FFFFB2, reg); // RTCOR
|
||||
reg = 0xA518; // phi/32
|
||||
WriteHalfword(serial_handle, 0x05FFFFAE, reg); // RTCSR
|
||||
|
||||
|
||||
// download Rockbox/gdb
|
||||
pFile = fopen(gCmd.szExecfile, "rb");
|
||||
if (pFile == NULL)
|
||||
{
|
||||
printf("\nExecutable file %s cannot be opened, exiting.\n", gCmd.szExecfile);
|
||||
return -3;
|
||||
}
|
||||
|
||||
size = fread(abFirmware, 1, sizeof(abFirmware), pFile);
|
||||
WriteByteMultiple(serial_handle, 0x09000000, size, abFirmware);
|
||||
fclose (pFile);
|
||||
printf("\b\b\b done.\n");
|
||||
|
||||
// start rockbox/gdb
|
||||
printf("Starting program...");
|
||||
Execute(serial_handle, 0x09000200, false);
|
||||
printf("\b\b\b done.\n");
|
||||
}
|
||||
|
||||
|
||||
if (gCmd.bTest)
|
||||
{
|
||||
// test code: query keypad
|
||||
while (1)
|
||||
{
|
||||
WriteByte(serial_handle, 0x05FFFEE8, 0x24); // ADCSR
|
||||
while (!(ReadByte(serial_handle, 0x05FFFEE8) & 0x80));
|
||||
reg = ReadHalfword(serial_handle, 0x05FFFEE0); // ADDRA
|
||||
printf("ADC(4): %d\n", reg>>6);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (gCmd.bBlink)
|
||||
{
|
||||
// blinking LED
|
||||
UINT8 byte;
|
||||
printf("Flashing red LED forever... (stop with Ctrl-C)\n");
|
||||
byte = ReadByte(serial_handle, 0x05FFFFC3);
|
||||
while (1)
|
||||
{
|
||||
byte ^= 0x40;
|
||||
WriteByte(serial_handle, 0x05FFFFC3, byte);
|
||||
Sleep(200);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
130
flash/uart_boot/uart_boot.dsp
Normal file
130
flash/uart_boot/uart_boot.dsp
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
# Microsoft Developer Studio Project File - Name="uart_boot" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=uart_boot - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "uart_boot.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "uart_boot.mak" CFG="uart_boot - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "uart_boot - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "uart_boot - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "uart_boot - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# ADD BASE RSC /l 0x407 /d "NDEBUG"
|
||||
# ADD RSC /l 0x407 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "uart_boot - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# ADD BASE RSC /l 0x407 /d "_DEBUG"
|
||||
# ADD RSC /l 0x407 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "uart_boot - Win32 Release"
|
||||
# Name "uart_boot - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\client.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\flash.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\uart_boot.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\uart_win.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\client.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\flash.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\minimon.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\scalar_types.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\uart.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
138
flash/uart_boot/uart_win.c
Normal file
138
flash/uart_boot/uart_win.c
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
// UART wrapper implementation for the Win32 platform
|
||||
// make a new version of this file for different systems, e.g. Linux
|
||||
|
||||
#include <windows.h>
|
||||
#include "scalar_types.h" // (U)INT8/16/32
|
||||
#include "Uart.h"
|
||||
|
||||
// COMx for windows, returns NULL on error
|
||||
tUartHandle UartOpen(char* szPortName)
|
||||
{
|
||||
HANDLE serial_handle;
|
||||
DCB dcb;
|
||||
COMMTIMEOUTS cto = { 0, 0, 0, 0, 0 };
|
||||
|
||||
memset(&dcb,0,sizeof(dcb));
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
// set DCB to configure the serial port
|
||||
dcb.DCBlength = sizeof(dcb);
|
||||
|
||||
dcb.fOutxCtsFlow = 0;
|
||||
dcb.fOutxDsrFlow = 0;
|
||||
dcb.fDtrControl = DTR_CONTROL_ENABLE; // enable for power
|
||||
dcb.fDsrSensitivity = 0;
|
||||
dcb.fRtsControl = RTS_CONTROL_ENABLE; // enable for power
|
||||
dcb.fOutX = 0;
|
||||
dcb.fInX = 0;
|
||||
|
||||
/* ----------------- misc parameters ----- */
|
||||
dcb.fErrorChar = 0;
|
||||
dcb.fBinary = 1;
|
||||
dcb.fNull = 0;
|
||||
dcb.fAbortOnError = 0;
|
||||
dcb.wReserved = 0;
|
||||
dcb.XonLim = 2;
|
||||
dcb.XoffLim = 4;
|
||||
dcb.XonChar = 0x13;
|
||||
dcb.XoffChar = 0x19;
|
||||
dcb.EvtChar = 0;
|
||||
|
||||
/* ----------------- defaults ----- */
|
||||
dcb.BaudRate = 4800;
|
||||
dcb.Parity = NOPARITY;
|
||||
dcb.fParity = 0;
|
||||
dcb.StopBits = ONESTOPBIT;
|
||||
dcb.ByteSize = 8;
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
// opening serial port
|
||||
serial_handle = CreateFile(szPortName, GENERIC_READ | GENERIC_WRITE,
|
||||
0, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL);
|
||||
|
||||
if (serial_handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
//printf("Cannot open port \n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SetCommMask(serial_handle, 0);
|
||||
SetCommTimeouts(serial_handle, &cto);
|
||||
|
||||
if(!SetCommState(serial_handle, &dcb))
|
||||
{
|
||||
//printf("Error setting up COM params\n");
|
||||
CloseHandle(serial_handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return serial_handle;
|
||||
}
|
||||
|
||||
// returns true on success, false on error
|
||||
bool UartConfig(tUartHandle handle, long lBaudRate, tParity nParity, tStopBits nStopBits, int nByteSize)
|
||||
{
|
||||
DCB dcb;
|
||||
|
||||
if (!GetCommState (handle, &dcb))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
dcb.BaudRate = lBaudRate;
|
||||
dcb.Parity = nParity;
|
||||
dcb.StopBits = nStopBits;
|
||||
dcb.ByteSize = nByteSize;
|
||||
|
||||
if(!SetCommState(handle, &dcb))
|
||||
{
|
||||
//DWORD dwErr = GetLastError();
|
||||
//printf("Error %d setting up COM params for baudrate byte\n", dwErr);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// returns how much data was actually transmitted
|
||||
long UartWrite(tUartHandle handle, unsigned char* pData, long lSize)
|
||||
{
|
||||
BOOL success;
|
||||
DWORD result_nbr;
|
||||
|
||||
success = WriteFile(handle, pData, lSize, &result_nbr, NULL);
|
||||
|
||||
if(!success)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return result_nbr;
|
||||
}
|
||||
|
||||
// returns how much data was actually received
|
||||
long UartRead(tUartHandle handle, unsigned char* pBuffer, long lSize)
|
||||
{
|
||||
BOOL success;
|
||||
DWORD read_nbr;
|
||||
|
||||
success = ReadFile(handle, pBuffer, lSize, &read_nbr, NULL);
|
||||
if(!success)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return read_nbr;
|
||||
}
|
||||
|
||||
|
||||
void UartClose(tUartHandle handle)
|
||||
{
|
||||
if (handle != NULL)
|
||||
{
|
||||
CloseHandle(handle);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue