-
Notifications
You must be signed in to change notification settings - Fork 0
/
bootloaderc.c
274 lines (250 loc) · 5.61 KB
/
bootloaderc.c
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
#include<S3C2440.h>
#define uchar unsigned char
#define uint unsigned int
#define LED1_ON ~(1<<5)
#define LED2_ON ~(1<<6)
#define LED3_ON ~(1<<7)
#define LED4_ON ~(1<<8)
#define LED1_OFF (1<<5)
#define LED2_OFF (1<<6)
#define LED3_OFF (1<<7)
#define LED4_OFF (1<<8)
#define TACLS 2
#define TWRPH0 2
#define TWRPH1 0
extern uint Image$$SDZI$$ZI$$Base;
extern uint Image$$SDZI$$ZI$$Limit;
extern uint Image$$SDZI$$ZI$$Length;
extern uint Image$$SDNOR$$Limit;
extern uint Image$$SDRW$$Base;
void clear_zi(void);
void uart0_init(void);
void putc(uchar c);
void puts(char *str);
void puthex(uint val);
void nand_init(void);
void nand_select(void);
void nand_deselect(void);
void nand_addr(uint addr);
void nand_cmd(uchar cmd);
void nand_wait_ready(void);
uchar nand_data(void);
void nand_reset(void);
void setup_start_tag(void);
void setup_memory_tags(void);
void nand_read(uint addr, uchar *buf, uint len);
void setup_commandline_tag(char *cmdline);
void setup_end_tag(void);
void dely(int tt);
uchar strlen(char *str);
void strcpy(char *dest, char *src);
static struct tag *params;
struct tag_header {
uint size;
uint tag;
};
struct tag_core {
uint flags; /* bit 0 = read-only */
uint pagesize;
uint rootdev;
};
struct tag_mem32 {
uint size;
uint start; /* physical start address */
};
struct tag_cmdline {
char cmdline[1]; /* this is the minimum size */
};
struct tag {
struct tag_header hdr;
union {
struct tag_core core;
struct tag_mem32 mem;
//struct tag_videotext videotext;
//struct tag_ramdisk ramdisk;
//struct tag_initrd initrd;
//struct tag_serialnr serialnr;
//struct tag_revision revision;
//struct tag_videolfb videolfb;
struct tag_cmdline cmdline;
/*
* Acorn specific
*/
//struct tag_acorn acorn;
/*
* DC21285 specific
*/
//struct tag_memclk memclk;
} u;
} ;
int main()
{
void (*theKernel)(int zero, int arch, uint params);
uart0_init();
puts("Copy kernel from nand start\n\r");
nand_init();
nand_read(0x60000, (uchar *)0x30008000, 0x500000);
puts("Set boot params\n\r");
setup_start_tag();
setup_memory_tags();
setup_commandline_tag("noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0,115200");
setup_end_tag();
puts("Boot kernel\n\r");
theKernel = (void (*)(int, int, uint))0x30008040;
theKernel(0, 1999, 0x30000100);
puts("Error!\n\r");
return -1;
}
void dely(int tt)
{
int i;
for(i =0;i<tt;i++);
}
void uart0_init()
{
GPHCON&=~((3<<4)|(3<<6)); //GPH4--TXD0;GPH5--RXD0先清0
GPHCON|=((2<<4)|(2<<6)); //设置GPH4、GPH5为TXD0、RXD0功能
GPHUP=0x00; //上拉电阻使能
UFCON0=0x00; //不使用fifo
UMCON0=0x00; //不使用流控
ULCON0|=0x03; //设置数据发送格式:8个数据位,1个停止位,无校验位
UCON0=0x05; //发送模式和接收模式都使用查询模式
UBRDIV0=(int)((50000000/(115200*16))-1); //设置波特率
URXH0=0; //将URXH0清零
UTXH0=0;
}
void clear_zi()
{
uint *p = &Image$$SDZI$$ZI$$Base;
for (; p < &Image$$SDZI$$ZI$$Limit; p++)
*p = 0;
}
void nand_init(void)
{
//NFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);
nand_reset();
}
void nand_reset(void)
{
NFCONT |= (1<<0);
NFCONT &= ~(1<<1);
NFCMD=0xff; // 复位命令
while(!(NFSTAT & 1));
NFCONT &= ~(1<<0);
NFCONT &= ~(1<<1);
}
void nand_addr(uint addr)
{
unsigned int col = addr % 2048;
unsigned int page = addr / 2048;
volatile int i;
NFADDR = col & 0xff;
for (i = 0; i < 10; i++);
NFADDR = (col >> 8) & 0xff;
for (i = 0; i < 10; i++);
NFADDR = page & 0xff;
for (i = 0; i < 10; i++);
NFADDR = (page >> 8) & 0xff;
for (i = 0; i < 10; i++);
NFADDR = (page >> 16) & 0xff;
for (i = 0; i < 10; i++);
}
void nand_read(uint addr, uchar *buf, uint len)
{
int col = addr%2048;
int i = 0;
int j = 0;
NFCONT |= (1<<0);
NFCONT &= ~(1<<1);
while (i < len)
{
NFCMD=0x00;
nand_addr(addr);
NFCMD=0x30;
for (j=0; j<10; j++);
while (!(NFSTAT & 1));
for (;(col < 2048) && (i < len); col++)
{
buf[i] = NFDATA;
i++;
addr++;
}
col = 0;
}
NFCONT &= ~(1<<0);
NFCONT &= ~(1<<1);
}
void putc(uchar c)
{
UTXH0=c;
while(!(UTRSTAT0&(1<<2))); //等待发送完成
}
void puts(char *str)
{
int i = 0;
while (str[i])
{
putc(str[i]);
i++;
}
}
void puthex(uint val)
{
/* 0x1234abcd */
int i;
int j;
puts("0x");
for (i = 0; i < 8; i++)
{
j = (val >> ((7-i)*4)) & 0xf;
if ((j >= 0) && (j <= 9))
putc('0' + j);
else
putc('A' + j - 0xa);
}
}
void setup_start_tag(void)
{
params = (struct tag *)0x30000100;
params->hdr.tag = 0x54410001;
params->hdr.size =(sizeof(struct tag_header) + sizeof(struct tag_core))/4;
params->u.core.flags = 0;
params->u.core.pagesize = 0;
params->u.core.rootdev = 0;
params = (struct tag *)((uint *)params + params->hdr.size);
}
void setup_memory_tags(void)
{
params->hdr.tag = 0x54410002;
params->hdr.size = (sizeof(struct tag_header) + sizeof(struct tag_mem32))/4;
params->u.mem.start = 0x30000000;
params->u.mem.size = 64*1024*1024;
params = (struct tag *)((uint *)params + params->hdr.size);
}
void setup_commandline_tag(char *cmdline)
{
uchar len = strlen(cmdline) + 1;
params->hdr.tag = 0x54410009;
params->hdr.size = (sizeof (struct tag_header) + len + 3)/4;
strcpy (params->u.cmdline.cmdline, cmdline); //?
params = (struct tag *)((uint *)params + params->hdr.size);
}
void setup_end_tag(void)
{
params->hdr.tag = 0;
params->hdr.size = 0;
}
uchar strlen(char *str)
{
uchar i = 0;
while (str[i])
{
i++;
}
return i;
}
void strcpy(char *dest, char *src)
{
while ((*dest++ = *src++) != '\0');
}