]> cloudbase.mooo.com Git - z180-stamp.git/blob - avr/main.c
Merge branch 'test-fboot-support'
[z180-stamp.git] / avr / main.c
1 /*
2 * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7
8 #include "common.h"
9 #include <avr/interrupt.h>
10 #include <avr/wdt.h>
11 #include <stdlib.h>
12 #include <stdio.h>
13
14 #include "config.h"
15 #include "ff.h"
16 #include "z80-if.h"
17 #include "i2c.h"
18 #include "con-utils.h"
19 #include "serial.h"
20 #include "timer.h"
21 #include "cli.h"
22 #include "env.h"
23 #include "z180-serv.h"
24 #include "gpio.h"
25 #include "time.h"
26 #include "rtc.h"
27 #include "debug.h"
28
29 uint8_t mcusr __attribute__ ((section (".noinit")));
30
31 #if DEBUG
32 __attribute__ ((naked)) __attribute__ ((section (".init3")))
33 void preset_ram (void)
34 {
35 for (uint8_t *p = RAMSTART; p <= (uint8_t *) RAMEND; p++)
36 *p = 0xdd;
37
38 }
39 #endif
40
41 __attribute__ ((naked)) __attribute__ ((section (".init3")))
42 void get_mcusr (void)
43 {
44 /* save and clear reset reason(s) */
45 /* TODO: move to init section? */
46 mcusr = MCUSR;
47 MCUSR = 0;
48
49 wdt_disable();
50 }
51
52 /*--------------------------------------------------------------------------*/
53 #if DEBUG
54
55 static const FLASH char * const FLASH rreasons[] = {
56 FSTR("Power on"),
57 FSTR("External"),
58 FSTR("Brown out"),
59 FSTR("Watchdog"),
60 FSTR("JTAG"),
61 };
62
63 static
64 void print_reset_reason(void)
65 {
66 uint8_t r = mcusr & 0x1f;
67 const FLASH char * const FLASH *p = rreasons;
68
69 printf_P(PSTR("### Reset reason(s): %s"), r ? "" : "none");
70 for ( ; r; p++, r >>= 1) {
71 if (r & 1) {
72 my_puts_P(*p);
73 if (r & ~1)
74 printf_P(PSTR(", "));
75 }
76 }
77 printf_P(PSTR(".\n"));
78 }
79
80 #endif
81
82 ISR(INT5_vect)
83 {
84 Stat |= S_MSG_PENDING;
85 }
86
87 ISR(INT6_vect)
88 {
89 Stat |= S_CON_PENDING;
90 }
91
92 static
93 void setup_avr(void)
94 {
95 /* CPU */
96
97 /* Disable JTAG Interface regardless of the JTAGEN fuse setting. */
98 MCUCR = _BV(JTD);
99 MCUCR = _BV(JTD);
100
101 /* Disable peripherals. Enable individually in respective init function. */
102 PRR0 = _BV(PRTWI) |
103 _BV(PRTIM2) | _BV(PRTIM0) | _BV(PRTIM1) |
104 _BV(PRSPI) | _BV(PRUSART0) | _BV(PRADC);
105
106 PRR1 = _BV(PRTIM5) | _BV(PRTIM4) | _BV(PRTIM3) |
107 _BV(PRUSART3) | _BV(PRUSART2) | _BV(PRUSART1);
108
109
110 /* disable analog comparator */
111 ACSR = _BV(ACD);
112 /* Ports */
113
114 /* Clock */
115 CLKPR = _BV(CLKPCE);
116 CLKPR = 0;
117
118 /* Timer */
119 PRR1 &= ~_BV(PRTIM3);
120 OCR3A = F_CPU / 1000 - 1; /* Timer3: 1000Hz interval (OC3A) */
121 TCCR3B = (0b01<<WGM32)|(0b001<<CS30); /* CTC Mode, Prescaler 1 */
122 TIMSK3 = _BV(OCIE3A); /* Enable TC2.oca interrupt */
123
124 /* INT5, INT6: falling edge */
125 EICRB = (EICRB & ~((0b11 << ISC50) | (0b11 << ISC60))) |
126 (0b10 << ISC50) | (0b10 << ISC60);
127 /* Reset pending ints */
128 EIFR |= _BV(INTF5) | _BV(INTF6);
129 /* Enable INT5, and INT6 */
130 EIMSK |= _BV(INT5) | _BV(INT6);
131 }
132
133 static
134 int reset_reason_is_power_on(void)
135 {
136 return (mcusr & _BV(PORF)) != 0;
137 }
138
139 static
140 void setup_system_time(void)
141 {
142 struct tm rtc_time;
143
144 rtc_get(&rtc_time);
145 rtc_time.tm_isdst = 0;
146 set_system_time(mk_gmtime(&rtc_time) );
147 }
148
149
150
151 static void setup_fatfs(void)
152 {
153 static FATFS FatFs0;
154 static FATFS FatFs1;
155
156 f_mount(&FatFs0, "0:", 0);
157 f_mount(&FatFs1, "1:", 0);
158 }
159
160 /*--------------------------------------------------------------------------*/
161
162 /* Stored value of bootdelay, used by autoboot_command() */
163 static int stored_bootdelay;
164
165
166 /***************************************************************************
167 * Watch for 'delay' seconds for autoboot stop.
168 * returns: 0 - no key, allow autoboot
169 * 1 - got key, abort
170 */
171
172 static int abortboot(int bootdelay)
173 {
174 int abort = 0;
175 uint32_t ts;
176
177 if (bootdelay >= 0)
178 printf_P(PSTR("Hit any key to stop autoboot: %2d "), bootdelay);
179
180 #if defined CONFIG_ZERO_BOOTDELAY_CHECK
181 /*
182 * Check if key already pressed
183 * Don't check if bootdelay < 0
184 */
185 if (bootdelay >= 0) {
186 if (tstc()) { /* we got a key press */
187 (void) my_getchar(1); /* consume input */
188 my_puts_P(PSTR("\b\b\b 0"));
189 abort = 1; /* don't auto boot */
190 }
191 }
192 #endif
193
194 while ((bootdelay > 0) && (!abort)) {
195 --bootdelay;
196 /* delay 1000 ms */
197 ts = get_timer(0);
198 do {
199 if (tstc()) { /* we got a key press */
200 abort = 1; /* don't auto boot */
201 bootdelay = 0; /* no more delay */
202 break;
203 }
204 udelay(10000);
205 } while (!abort && get_timer(ts) < 1000);
206
207 printf_P(PSTR("\b\b\b%2d "), bootdelay);
208 }
209
210 putchar('\n');
211
212 return abort;
213 }
214
215 static
216 const char *bootdelay_process(void)
217 {
218 char *s;
219 int bootdelay;
220
221 bootdelay = (int) getenv_ulong(PSTR(ENV_BOOTDELAY), 10, CONFIG_BOOTDELAY);
222
223
224 debug("### main_loop entered: bootdelay=%d\n\n", bootdelay);
225 _delay_ms(20);
226
227 s = getenv(PSTR(ENV_BOOTCMD));
228 stored_bootdelay = bootdelay;
229 return s;
230 }
231
232 static
233 void autoboot_command(const char *s)
234 {
235 debug("### main_loop: bootcmd=\"%s\"\n", s ? s : PSTR("<UNDEFINED>"));
236 _delay_ms(20);
237
238 if (stored_bootdelay != -1 && s && !abortboot(stored_bootdelay)) {
239 run_command_list(s, -1);
240 }
241 }
242
243
244 static
245 void main_loop(void)
246 {
247 const char *s;
248
249 s = bootdelay_process();
250 autoboot_command(s);
251 cli_loop();
252 }
253
254 int main(void)
255 {
256 extern void setup_mmc(void);
257
258 for (int i = 0; i < GPIO_MAX; i++)
259 gpio_config(i, INPUT_PULLUP);
260 setup_avr();
261 setup_mmc();
262 z80_setup_bus();
263 env_init();
264
265 if (reset_reason_is_power_on())
266 _delay_ms(CONFIG_PWRON_DELAY);
267
268 serial_setup(getenv_ulong(PSTR(ENV_BAUDRATE), 10, CONFIG_BAUDRATE));
269 sei();
270
271 #if DEBUG
272 debug("\n=========================< (RE)START DEBUG >=========================\n");
273 print_reset_reason();
274 #endif
275
276 i2c_init(CONFIG_SYS_I2C_CLOCK);
277 setup_system_time();
278 setup_fatfs();
279
280 printf_P(PSTR("\nATMEGA1281+Z8S180 Stamp Monitor\n\n"));
281
282 setup_z180_serv();
283
284 main_loop();
285 }