2 //#include <avr/interrupt.h>
3 #include "kazzo_task.h"
4 #include "bus_access.h"
6 //---- global variable ----
8 void (*const writer)(uint16_t address, uint16_t length, const uint8_t *data);
9 void (*const programmer)(const struct flash_order *t);
10 void (*const reader)(uint16_t address, uint16_t length, uint8_t *data);
11 enum compare_status (*const compare)(uint16_t address, uint16_t length, const uint8_t *data);
13 IDLE = KAZZO_TASK_FLASH_IDLE,
15 PROGRAM, TOGGLE_FIRST, TOGGLE_CHECK
17 uint16_t command_000x, command_2aaa, command_5555;
19 uint16_t address, length, program_unit;
21 uint8_t toggle, retry_count;
22 struct flash_order program_command[FLASH_PROGRAM_ORDER];
24 static struct flash_seqence seqence_cpu = {
25 .status = IDLE, .reader = cpu_read,
26 .writer = cpu_write_flash, .programmer = cpu_write_flash_order,
27 .compare = cpu_compare
29 static struct flash_seqence seqence_ppu = {
30 .status = IDLE, .reader = ppu_read,
31 .writer = ppu_write, .programmer = ppu_write_order,
32 .compare = ppu_compare
35 //---- task registration ----
36 uint8_t flash_cpu_status(void)
38 return seqence_cpu.status;
40 uint8_t flash_ppu_status(void)
42 return seqence_ppu.status;
44 void flash_both_idle(void)
46 seqence_cpu.status = IDLE;
47 seqence_ppu.status = IDLE;
49 static inline uint16_t unpack_short_le(const uint8_t *t)
55 static void config_set(const uint8_t *data, uint16_t length, struct flash_seqence *t)
57 t->command_000x = unpack_short_le(data);
58 data += sizeof(uint16_t);
59 t->command_2aaa = unpack_short_le(data);
60 data += sizeof(uint16_t);
61 t->command_5555 = unpack_short_le(data);
62 data += sizeof(uint16_t);
63 t->program_unit = unpack_short_le(data);
64 data += sizeof(uint16_t);
65 if(length < 9){ //support client 0.6.0
68 t->retry_enable = *data;
71 t->program_command[0].address = t->command_5555;
72 t->program_command[0].data = 0xaa;
73 t->program_command[1].address = t->command_2aaa;
74 t->program_command[1].data = 0x55;
75 t->program_command[2].address = t->command_5555;
76 t->program_command[2].data = 0xa0;
78 void flash_cpu_config(const uint8_t *data, uint16_t length)
80 config_set(data, length, &seqence_cpu);
82 void flash_ppu_config(const uint8_t *data, uint16_t length)
84 config_set(data, length, &seqence_ppu);
87 static void program_assign(enum status status, uint16_t address, uint16_t length, const uint8_t *data, struct flash_seqence *t)
89 if(0 && (t->program_unit != 1) && (t->status == PROGRAM)){ //W29C040 ¤ÎºÆ½ñ¤¹þ¤ß²ó¿ô¤ò¸º¤é¤·¤Æ¤ß¤ë
90 t->status = TOGGLE_FIRST;
100 void flash_cpu_program(uint16_t address, uint16_t length, const uint8_t *data)
102 program_assign(PROGRAM, address, length, data, &seqence_cpu);
104 void flash_ppu_program(uint16_t address, uint16_t length, const uint8_t *data)
106 program_assign(PROGRAM, address, length, data, &seqence_ppu);
109 void flash_cpu_erase(uint16_t address)
111 //length ¤Ë unit ¤òÅϤ·¤Æ toggle check ¸å IDLE ¤Ë¤Ê¤ë¤è¤¦¤Ë¤¹¤ë
112 program_assign(ERASE, address, seqence_cpu.program_unit, NULL, &seqence_cpu);
114 void flash_ppu_erase(uint16_t address)
116 program_assign(ERASE, address, seqence_ppu.program_unit, NULL, &seqence_ppu);
119 //---- command write ----
120 struct flash_command{
121 enum {C2AAA, C5555, END} address;
124 static void command_execute(const struct flash_command *c, const struct flash_seqence *const t)
126 while(c->address != END){
130 addr = t->command_2aaa;
133 addr = t->command_5555;
138 t->writer(addr, 1, &c->data);
142 static void program(const struct flash_seqence *t)
144 /* static const struct flash_command c[] = {
145 {C5555, 0xaa}, {C2AAA, 0x55}, {C5555, 0xa0}, {END, 0}
147 command_execute(c, t);*/
148 t->programmer(t->program_command);
149 t->writer(t->address, t->program_unit, t->data);
152 static void erase(const struct flash_seqence *t)
154 static const struct flash_command c[] = {
155 {C5555, 0xaa}, {C2AAA, 0x55}, {C5555, 0x80},
156 {C5555, 0xaa}, {C2AAA, 0x55}, {C5555, 0x10},
159 command_execute(c, t);
162 static void device_get(const struct flash_seqence *t, uint8_t d[2])
164 static const struct flash_command entry[] = {
165 {C5555, 0xaa}, {C2AAA, 0x55}, {C5555, 0x90}, {END, 0}
167 static const struct flash_command exit[] = {
168 {C5555, 0xaa}, {C2AAA, 0x55}, {C5555, 0xf0}, {END, 0}
170 command_execute(entry, t);
171 t->reader(t->command_000x, 1, d);
172 command_execute(entry, t);
173 t->reader(t->command_000x + 1, 1, d + 1);
174 command_execute(exit, t);
176 void flash_cpu_device_get(uint8_t d[2])
178 device_get(&seqence_cpu, d);
180 void flash_ppu_device_get(uint8_t d[2])
182 device_get(&seqence_ppu, d);
184 //---- status read ----
185 static void toggle_first(struct flash_seqence *t)
187 t->reader(t->address, 1, &t->toggle);
190 static void toggle_check(struct flash_seqence *t)
193 t->reader(t->address, 1, &d);
194 if(t->toggle == (d & 0x40)){
195 if((t->retry_enable != 0) && (t->request == PROGRAM) && (t->retry_count < 20)){
196 if(t->compare(t->address, t->program_unit, t->data) == NG){
203 t->address += t->program_unit;
204 t->data += t->program_unit;
205 t->length -= t->program_unit;
206 if((t->length == 0) || (t->request == ERASE)){
212 t->toggle = d & 0x40;
213 if(0 && (d & 0x20)){ //polling DQ5, AM29F040B only
215 t->reader(t->address, 1, &d0);
216 t->reader(t->address, 1, &d1);
217 if((d0 & 0x40) == (d1 & 0x40)){
218 t->address += t->program_unit;
219 t->data += t->program_unit;
220 t->length -= t->program_unit;
221 if((t->length == 0) || (t->request == ERASE)){
230 static void erase_wait(struct flash_seqence *t)
233 t->reader(t->address, 1, &d);
238 //---- task execute ----
239 static void process(struct flash_seqence *s)
246 s->status = ERASE_WAIT;
252 if((s->program_unit != 1) || (*(s->data) != 0xff)){
255 s->status = TOGGLE_FIRST;
259 s->status = TOGGLE_CHECK;
262 toggle_check(s); //status is updated by function
267 void flash_process(void)
269 //for CPU and PPU dual programming
270 process(&seqence_cpu);
271 process(&seqence_ppu);