summaryrefslogtreecommitdiff
path: root/flash/uart_boot/uart_boot.c
blob: acfbb8e9c5670acf2c311f0ea6dcd53ddd38ff39 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id$
 *
 * Copyright (C) 2007 Copyright Kévin Ferrare
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/


#include "clock_bitmaps.h"

/* bitmaps */
#include "pluginbitmaps/clock_binary.h"
#include "pluginbitmaps/clock_digits.h"
#include "pluginbitmaps/clock_smalldigits.h"
#include "pluginbitmaps/clock_segments.h"
#include "pluginbitmaps/clock_smallsegments.h"

#include "pluginbitmaps/clock_logo.h"
#include "pluginbitmaps/clock_messages.h"

#if NB_SCREENS==2
#include "pluginbitmaps/clock_binary_remote.h"
#include "pluginbitmaps/clock_digits_remote.h"
#include "pluginbitmaps/clock_smalldigits_remote.h"
#include "pluginbitmaps/clock_segments_remote.h"
#include "pluginbitmaps/clock_smallsegments_remote.h"

#include "pluginbitmaps/clock_logo_remote.h"
#include "pluginbitmaps/clock_messages_remote.h"

#endif


const struct picture logos[]={
        {clock_logo, BMPWIDTH_clock_logo, BMPHEIGHT_clock_logo, 
                BMPHEIGHT_clock_logo},
#if NB_SCREENS==2
        {clock_logo_remote,BMPWIDTH_clock_logo_remote,
                BMPHEIGHT_clock_logo_remote, BMPHEIGHT_clock_logo_remote}
#endif
};

const struct picture messages[]={
    {clock_messages,BMPWIDTH_clock_messages, BMPHEIGHT_clock_messages, 
        BMPHEIGHT_clock_messages/6},
#if NB_SCREENS==2
    {clock_messages_remote,BMPWIDTH_clock_messages_remote, 
        BMPHEIGHT_clock_messages_remote, BMPHEIGHT_clock_messages_remote/6}
#endif
};

const struct picture binary[]={
    {clock_binary, BMPWIDTH_clock_binary, BMPHEIGHT_clock_binary, 
        BMPHEIGHT_clock_binary/2 },
#if NB_SCREENS==2
    {clock_binary_remote, BMPWIDTH_clock_binary_remote,
        BMPHEIGHT_clock_binary_remote, BMPHEIGHT_clock_binary_remote/2}
#endif
};

const struct picture digits[]={
    {clock_digits, BMPWIDTH_clock_digits, BMPHEIGHT_clock_digits, 
        BMPHEIGHT_clock_digits/13 },
#if NB_SCREENS==2
    {clock_digits_remote,
    BMPWIDTH_clock_digits_remote, BMPHEIGHT_clock_digits_remote,
        BMPHEIGHT_clock_digits_remote/13}
#endif
};

const struct picture smalldigits[]={
    {clock_smalldigits, BMPWIDTH_clock_smalldigits, BMPHEIGHT_clock_smalldigits, 
        BMPHEIGHT_clock_smalldigits/13 },
#if NB_SCREENS==2
    {clock_smalldigits_remote, BMPWIDTH_clock_smalldigits_remote, 
        BMPHEIGHT_clock_smalldigits_remote, 
        BMPHEIGHT_clock_smalldigits_remote/13}
#endif
};

const struct picture segments[]={
    {clock_segments, BMPWIDTH_clock_segments, BMPHEIGHT_clock_segments, 
        BMPHEIGHT_clock_segments/13 },
#if NB_SCREENS==2
    {clock_segments_remote, BMPWIDTH_clock_segments_remote, 
        BMPHEIGHT_clock_segments_remote, BMPHEIGHT_cloc// 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 bHold; // hold power (for FMs & V2s)
	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("-hold  (hold the power, useful for FMs and V2s, so you can release ON)\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("-hold", *argv, 2))
		{
			gCmd.bHold = 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.bHold)
	{
		// hold power for FM
		reg = ReadHalfword(serial_handle, 0x05FFFFC2); // PBDR
		reg |= 0x0020; // set PB5 to keep power
		WriteHalfword(serial_handle, 0x05FFFFC2, reg);

		reg = ReadHalfword(serial_handle, 0x05FFFFC6); // PBIOR
		reg |= 0x0020; // make PB5 an output
		WriteHalfword(serial_handle, 0x05FFFFC6, reg);
		printf("Power hold, you can release ON button now.\n");
	}


	if (gCmd.bSpindown)
	{
		// power down the disk
		reg = ReadHalfword(serial_handle, 0x05FFFFCA); // PACR2
		reg &= ~0x0400; // clear bit 10: GPIO
		WriteHalfword(serial_handle, 0x05FFFFCA, reg);

		reg = ReadHalfword(serial_handle, 0x05FFFFC4); // PAIOR
		reg |= 0x0020; // set bit 5: output
		WriteHalfword(serial_handle, 0x05FFFFC4, reg);

		reg = ReadHalfword(serial_handle, 0x05FFFFC0); // PADR
		reg &= ~0x0020; // clear PA5 to power down
		WriteHalfword(serial_handle, 0x05FFFFC0, reg);
		printf("Harddisk powered down.\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: toggle PA5 to test FM IDE power
		reg = ReadHalfword(serial_handle, 0x05FFFFCA); // PACR2
		reg &= ~0x0400; // clear bit 10: GPIO
		WriteHalfword(serial_handle, 0x05FFFFCA, reg);

		reg = ReadHalfword(serial_handle, 0x05FFFFC4); // PAIOR
		reg |= 0x0020; // set bit 5: output
		WriteHalfword(serial_handle, 0x05FFFFC4, reg);

		printf("Toggling PA5 forever... (stop with Ctrl-C)\n");
		reg = ReadHalfword(serial_handle, 0x05FFFFC0); // PADR
		while (1)
		{
			reg ^= 0x0020;
			WriteHalfword(serial_handle, 0x05FFFFC0, reg); // PADR
			Sleep(1000);
		}
	}


	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;
}