altos: Remove 8051 address space specifiers
[fw/altos] / src / product / ao_flash_task.c
1 /*
2  * Copyright © 2013 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #include "ao.h"
20 #include <ao_exti.h>
21 #include <ao_boot.h>
22 #include <ao_flash.h>
23 #include <ao_flash_task.h>
24
25 void
26 ao_panic(uint8_t reason)
27 {
28         (void) reason;
29 }
30
31 void
32 ao_put_string(const char *s)
33 {
34         char    c;
35         while ((c = *s++)) {
36                 if (c == '\n')
37                         ao_usb_putchar('\r');
38                 ao_usb_putchar(c);
39         }
40 }
41
42 static void
43 ao_application(void)
44 {
45         ao_boot_reboot(AO_BOOT_APPLICATION_BASE);
46 }
47
48 static uint32_t
49 ao_get_hex32(void)
50 {
51         int8_t  n;
52         uint32_t v = 0;
53
54         for (;;) {
55                 n = ao_usb_getchar();
56                 if (n != ' ')
57                         break;
58         }
59         for(;;) {
60                 if ('0' <= n && n <= '9')
61                         n = n - '0';
62                 else if ('a' <= n && n <= 'f')
63                         n = n - ('a' - 10);
64                 else if ('A' <= n && n <= 'F')
65                         n = n - ('A' - 10);
66                 else
67                         break;
68                 v = (v << 4) | n;
69                 n = ao_usb_getchar();
70         }
71         return v;
72 }
73
74 static void
75 ao_block_erase(void)
76 {
77         uint32_t        addr = ao_get_hex32();
78         void            *p = (void *) addr;
79
80         ao_flash_erase_page(p);
81 }
82
83 static int
84 ao_block_valid_address(uint32_t addr)
85 {
86         if ((uint32_t) AO_BOOT_APPLICATION_BASE <= addr && addr <= (uint32_t) AO_BOOT_APPLICATION_BOUND - 256)
87                 return 1;
88         return 0;
89 }
90
91 static void
92 ao_block_write(void)
93 {
94         uint32_t        addr = ao_get_hex32();
95         void            *p = (void *) addr;
96         uint8_t         data[256];
97         uint16_t        i;
98
99         for (i = 0; i < 256; i++)
100                 data[i] = ao_usb_getchar();
101         if (!ao_block_valid_address(addr))
102                 return;
103         ao_flash_page(p, (void *) data);
104 }
105
106 static void
107 ao_block_read(void)
108 {
109         uint32_t        addr = ao_get_hex32();
110         uint8_t         *p = (uint8_t *) addr;
111         uint16_t        i;
112         uint8_t         c;
113
114         if (!ao_block_valid_address(addr)) {
115                 for (i = 0; i < 256; i++)
116                         ao_usb_putchar(0xff);
117                 return;
118         }
119         for (i = 0; i < 256; i++) {
120                 c = *p++;
121                 ao_usb_putchar(c);
122         }
123 }
124
125 static inline void
126 hexchar(uint8_t c)
127 {
128         if (c > 10)
129                 c += 'a' - ('9' + 1);
130         ao_usb_putchar(c + '0');
131 }
132
133 static void
134 ao_put_hex(uint32_t u)
135 {
136         int8_t i;
137         for (i = 28; i >= 0; i -= 4)
138                 hexchar((u >> i) & 0xf);
139 }
140
141 static void
142 ao_show_version(void)
143 {
144         ao_put_string("altos-loader");
145         ao_put_string("\nmanufacturer     "); ao_put_string(ao_manufacturer);
146         ao_put_string("\nproduct          "); ao_put_string(ao_product);
147         ao_put_string("\nflash-range      ");
148         ao_put_hex((uint32_t) AO_BOOT_APPLICATION_BASE);
149         ao_usb_putchar(' ');
150         ao_put_hex((uint32_t) AO_BOOT_APPLICATION_BOUND);
151         ao_put_string("\nsoftware-version "); ao_put_string(ao_version);
152         ao_put_string("\n");
153 }
154
155 void
156 ao_flash_task(void) {
157         for (;;) {
158                 ao_usb_flush();
159                 switch (ao_usb_getchar()) {
160                 case 'v': ao_show_version(); break;
161                 case 'a': ao_application(); break;
162                 case 'X': ao_block_erase(); break;
163                 case 'W': ao_block_write(); break;
164                 case 'R': ao_block_read(); break;
165                 }
166         }
167 }