diff options
Diffstat (limited to 'src/product/ao_flash_task.c')
| -rw-r--r-- | src/product/ao_flash_task.c | 137 | 
1 files changed, 137 insertions, 0 deletions
diff --git a/src/product/ao_flash_task.c b/src/product/ao_flash_task.c new file mode 100644 index 00000000..fdc4d0aa --- /dev/null +++ b/src/product/ao_flash_task.c @@ -0,0 +1,137 @@ +/* + * Copyright © 2013 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include <ao_exti.h> +#include <ao_boot.h> +#include <ao_flash.h> +#include <ao_flash_task.h> + +void +ao_panic(uint8_t reason) +{ +} + +void +ao_put_string(__code char *s) +{ +	char	c; +	while ((c = *s++)) { +		if (c == '\n') +			ao_usb_putchar('\r'); +		ao_usb_putchar(c); +	} +} + +static void +ao_application(void) +{ +	ao_boot_reboot(AO_BOOT_APPLICATION_BASE); +} + +static uint32_t +ao_get_hex32(void) +{ +	int8_t	n; +	uint32_t v = 0; + +	for (;;) { +		n = ao_usb_getchar(); +		if (n != ' ') +			break; +	} +	for(;;) { +		if ('0' <= n && n <= '9') +			n = n - '0'; +		else if ('a' <= n && n <= 'f') +			n = n - ('a' - 10); +		else if ('A' <= n && n <= 'F') +			n = n - ('A' - 10); +		else +			break; +		v = (v << 4) | n; +		n = ao_usb_getchar(); +	} +	return v; +} + +static void +ao_block_erase(void) +{ +	uint32_t	addr = ao_get_hex32(); +	uint32_t	*p = (uint32_t *) addr; + +	ao_flash_erase_page(p); +} + +static void +ao_block_write(void) +{ +	uint32_t	addr = ao_get_hex32(); +	uint32_t	*p = (uint32_t *) addr; +	union { +		uint8_t		data8[256]; +		uint32_t	data32[64]; +	} u; +	uint16_t	i; + +	if (addr < (uint32_t) AO_BOOT_APPLICATION_BASE) { +		ao_put_string("Invalid address\n"); +		return; +	} +	for (i = 0; i < 256; i++) +		u.data8[i] = ao_usb_getchar(); +	ao_flash_page(p, u.data32); +} + +static void +ao_block_read(void) +{ +	uint32_t	addr = ao_get_hex32(); +	uint8_t		*p = (uint8_t *) addr; +	uint16_t	i; +	uint8_t		c; + +	for (i = 0; i < 256; i++) { +		c = *p++; +		ao_usb_putchar(c); +	} +} + +static void +ao_show_version(void) +{ +	ao_put_string("altos-loader"); +	ao_put_string("\nmanufacturer     "); ao_put_string(ao_manufacturer); +	ao_put_string("\nproduct          "); ao_put_string(ao_product); +	ao_put_string("\nsoftware-version "); ao_put_string(ao_version); +	ao_put_string("\n"); +} + +void +ao_flash_task(void) { +	for (;;) { +		ao_usb_flush(); +		switch (ao_usb_getchar()) { +		case 'v': ao_show_version(); break; +		case 'a': ao_application(); break; +		case 'X': ao_block_erase(); break; +		case 'W': ao_block_write(); break; +		case 'R': ao_block_read(); break; +		} +	} +}  | 
