#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
+#include "kazzo_request.h"
#include "bus_access.h"
+#include "mcu_program.h"
+
+#if SPM_PAGESIZE > READ_PACKET_SIZE
+ #error READ_PACKET_SIZE is few capacity
+#endif
/*
firmware bootloader sequence
- User insert a cartrige which has charcter RAM. eg. UNROM or SGROM
- Host receive and compare charcter memory image.
- Firmware reprogram by REQUEST_FIRMWARE_PROGRAM.
-compiler notice/ WinAVR 20080610
-compiler produces bad object with optimize option -O2
-use -Os
+MEGA164P-20[AP]U
+ISP programming -> REQUEST_FIRMWARE_PROGRAM -> flash memory is programmed 2 pages only...
+ISP programming -> power off->on -> REQUEST_FIRMWARE_PROGRAM -> flash memory is programmed all pages.
*/
__attribute__((noreturn))
-BOOTLOADER_SECTION
-void mcu_data_program(uint8_t *buf, const uint16_t bufsize, uint16_t address, uint16_t length)
+__attribute__ ((section(".bootloader.programmer")))
+static void mcu_data_program(uint8_t *buf, uint16_t address, uint16_t length)
{
uint16_t offset = 0;
int page;
offset += SPM_PAGESIZE;
address += SPM_PAGESIZE;
}
- boot_rww_enable();
- sei();
- wdt_enable(WDTO_500MS);
+ if(0){ //force re-turn power on. keep watchdog disable
+ boot_rww_enable();
+ sei();
+ wdt_enable(WDTO_500MS);
+ }
endless: //wait watchdog interruptting reset
goto endless;
}
+
+__attribute__ ((section(".bootloader.version")))
+const struct bootloader_assign BOOTLOADER_ASSIGN = {
+ .version = "bootlader 0.1.0",
+ .programmer = mcu_data_program
+};
+
#include <time.h>
#include <usb.h>
#include <kazzo_request.h>
+#include "ihex.h"
+#include "file.h"
#include "usbdevice.h"
static void echo(usb_dev_handle *handle)
printf("\nTest completed.\n");
}
-static bool buf_load(uint8_t *buf, const char *file, int size)
+static bool hex_load(const char *file, long firmsize, uint8_t *image)
{
- FILE *fp;
-
- fp = fopen(file, "rb");
- if(fp == NULL){
+ FILE *f;
+ char s[0x80];
+ f = fopen(file, "r");
+ if(f == NULL){
return false;
}
- fseek(fp, 0, SEEK_SET);
- fread(buf, sizeof(uint8_t), size, fp);
- fclose(fp);
- return true;
+ fseek(f, 0, SEEK_SET);
+
+ struct record *t = ihex_new();
+ bool ret = true;
+ while(fgets(s, 0x80, f) != NULL){
+ if(ihex_load(s, t) == false){
+ ret = false;
+ break;
+ }
+ ihex_write(t, firmsize, image);
+ }
+ ihex_destory(t);
+ return ret;
+}
+static void snrom_ramopen(usb_dev_handle *handle)
+{
+ uint8_t t[5];
+ t[0] = 0x80;
+ write_memory(handle, REQUEST_CPU_WRITE_6502, INDEX_IMPLIED, 0x8000, 1, t);
+ t[0] = 0, t[1] = 0, t[2] = 0, t[3] = 1, t[4] = 0;
+ write_memory(handle, REQUEST_CPU_WRITE_6502, INDEX_IMPLIED, 0x8000, 5, t);
+ t[0] = 0, t[1] = 0, t[2] = 0, t[3] = 0, t[4] = 0;
+ write_memory(handle, REQUEST_CPU_WRITE_6502, INDEX_IMPLIED, 0xe000, 5, t);
+ write_memory(handle, REQUEST_CPU_WRITE_6502, INDEX_IMPLIED, 0xa000, 5, t);
}
+static int cartridge_ram_transform(usb_dev_handle *handle, const uint8_t *firmware, enum request w, enum request r, long address, long length)
+{
+ uint8_t *compare;
+ compare = malloc(length);
+ write_memory(handle, w, INDEX_IMPLIED, address, length, firmware);
+ read_memory(handle, r, INDEX_IMPLIED, address, length, compare);
+ int ret = memcmp(firmware, compare, length);
+ free(compare);
+ return ret;
+}
static void firmware_update(usb_dev_handle *handle, const char *file)
{
- uint8_t *firmware, *compare;
- const int firmsize = 0x1c00;
- assert(firmsize <= 0x2000);
+ uint8_t *firmware;
+ const int firmsize = 0x3800;
+ assert(firmsize <= 0x3800);
firmware = malloc(firmsize);
memset(firmware, 0xff, firmsize);
+
+ if(hex_load(file, firmsize, firmware) == false){
+ puts("image open error!");
+ goto end;
+ }
+ snrom_ramopen(handle);
+
+ int ppu, cpu = 0;
+ ppu = cartridge_ram_transform(handle, firmware, REQUEST_PPU_WRITE, REQUEST_PPU_READ, 0x0000, 0x2000);
+ if(firmsize >= 0x2000){
+ cpu = cartridge_ram_transform(handle, firmware + 0x2000, REQUEST_CPU_WRITE_6502, REQUEST_CPU_READ, 0x6000, firmsize - 0x2000);
+ }
+ if((ppu == 0) && (cpu == 0)){
+// write_memory(handle, REQUEST_FIRMWARE_PROGRAM, firmsize, 0x2000, 0, firmware);
+ write_memory(handle, REQUEST_FIRMWARE_PROGRAM, firmsize, 0x0000, 0, firmware);
+ puts("USB connection will be disconnteced. This is normally.");
+ puts("Re-turn on kazzo power.");
+ }else{
+ puts("firmware transform error!");
+ }
+end:
+ free(firmware);
+}
+enum{
+ FIRM_VERSION_OFFSET = 0x3780,
+ BOOTLOADER_VERSION_OFFSET = 0x3d00
+};
+static void firmware_verify(usb_dev_handle *handle, const char *file)
+{
+ uint8_t *firmware, *compare;
+ const int firmsize = 0x3800;
+ assert(firmsize <= 0x3800);
+ firmware = malloc(firmsize);
compare = malloc(firmsize);
- if(buf_load(firmware, file, firmsize) == false){
+ memset(compare, 0xff, firmsize);
+// if(buf_load(compare, file, firmsize) == false){
+ if(hex_load(file, firmsize, compare) == false){
puts("image open error!");
goto end;
}
- write_memory(handle, REQUEST_PPU_WRITE, 0, firmsize, firmware);
- read_memory(handle, REQUEST_PPU_READ, INDEX_IMPLIED, 0, firmsize, compare);
+ read_memory(handle, REQUEST_FIRMWARE_DOWNLOAD, INDEX_IMPLIED, 0, firmsize, firmware);
if(memcmp(firmware, compare, firmsize) == 0){
- write_memory(handle, REQUEST_FIRMWARE_PROGRAM, 0, 1, firmware);
- //usb_close(handle);
+ puts("firmware compare ok!");
}else{
- puts("firmware transform error!");
+ puts("firmware compare ng!");
+ printf("hex: %s\n", compare + FIRM_VERSION_OFFSET);
+ printf("avr: %s\n", firmware + FIRM_VERSION_OFFSET);
}
end:
free(firmware);
free(compare);
}
+static void firmware_download(usb_dev_handle *handle, const char *file)
+{
+ const int firmsize = 0x4000;
+ uint8_t *firmware = malloc(firmsize);
+ read_memory(handle, REQUEST_FIRMWARE_DOWNLOAD, INDEX_IMPLIED, 0, firmsize, firmware);
+ buf_save(firmware, file, firmsize);
+ puts(firmware + FIRM_VERSION_OFFSET);
+ free(firmware);
+}
static void firmware_version(usb_dev_handle *handle)
{
read_memory(handle, REQUEST_FIRMWARE_VERSION, INDEX_IMPLIED, 0, VERSION_STRING_SIZE, (uint8_t *) version);
puts(version);
}
+
int main(int c, char **v)
{
usb_init();
firmware_version(handle);
break;
case 3:
- firmware_update(handle, v[2]);
+ switch(v[1][0]){
+ case 'w':
+ firmware_update(handle, v[2]);
+ break;
+ case 'r':
+ firmware_download(handle, v[2]);
+ break;
+ case 'v':
+ firmware_verify(handle, v[2]);
+ break;
+ }
break;
}
usb_close(handle);