summaryrefslogtreecommitdiff
path: root/flash/minimon/minimon.c
blob: e7981f2d090271637cd0f064c548b4780d9e163e (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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
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;
}