Add project [bootloader_zevero_sd_m644p_make]
This commit is contained in:
259
bootloader_zevero_sd_m644p_make/main.c
Normal file
259
bootloader_zevero_sd_m644p_make/main.c
Normal file
@@ -0,0 +1,259 @@
|
||||
/*-------------------------------------------------------------------------/
|
||||
/ Stand-alone MMC boot loader R0.01
|
||||
/--------------------------------------------------------------------------/
|
||||
/
|
||||
/ Copyright (C) 2010, ChaN, all right reserved.
|
||||
/
|
||||
/ * This software is a free software and there is NO WARRANTY.
|
||||
/ * No restriction on use. You can use, modify and redistribute it for
|
||||
/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
|
||||
/ * Redistributions of source code must retain the above copyright notice.
|
||||
/
|
||||
/--------------------------------------------------------------------------/
|
||||
/ Dec 6, 2010 R0.01 First release
|
||||
/--------------------------------------------------------------------------/
|
||||
/ This is a stand-alone MMC/SD boot loader for megaAVRs. It requires a 4KB
|
||||
/ boot section for code, four GPIO pins for MMC/SD as shown in sch.jpg and
|
||||
/ nothing else. To port the boot loader into your project, follow the
|
||||
/ instruction described below.
|
||||
/
|
||||
/ 1. Setup the hardware. Attach a memory card socket to the any GPIO port
|
||||
/ where you like. Select boot size at least 4KB for the boot loader with
|
||||
/ BOOTSZ fuses and enable boot loader with BOOTRST fuse.
|
||||
/
|
||||
/ 2. Setup the software. Change the four port definitions in the asmfunc.S.
|
||||
/ Change MCU_TARGET, BOOT_ADR and MCU_FREQ in the Makefile. The BOOT_ADR
|
||||
/ is a BYTE address of boot section in the flash. Build the boot loader
|
||||
/ and write it to the device with a programmer.
|
||||
/
|
||||
/ 3. Build the application program and output it in binary form instead of
|
||||
/ hex format. Rename the file "app.bin" and put it into the memory card.
|
||||
/
|
||||
/ 4. Insert the card and turn the target power on. When the boot loader found
|
||||
/ the application file, the file is written into the flash memory prior to
|
||||
/ start the application program. On-board LED lights (if exist) during
|
||||
/ the flash programming operation.
|
||||
/
|
||||
/-------------------------------------------------------------------------*/
|
||||
|
||||
const char filename[13] ="644BOOT.BIN\0"; // EDIT FILENAME HERE
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/eeprom.h>
|
||||
#include <util/delay.h>
|
||||
#include <string.h>
|
||||
#include "pff/src/pff.h"
|
||||
#include <avr/wdt.h> //Watchdog
|
||||
// The following code is recommended in http://avr-libc.nongnu.org/user-manual/group__avr__watchdog.html but is disabled for now because avr_boot doesn't currently do anything with mcusr_mirror so for now we will only reset MCUSR and disable WDT.
|
||||
//uint8_t mcusr_mirror __attribute__ ((section (".noinit")));void get_mcusr(void) __attribute__((naked)) __attribute__((section(".init3")));void get_mcusr(void){mcusr_mirror = MCUSR;MCUSR = 0;wdt_disable();}
|
||||
void disable_watchdog(void) __attribute__((naked)) __attribute__((section(".init3")));
|
||||
void disable_watchdog(void)
|
||||
{
|
||||
#if defined(MCUCSR)
|
||||
MCUCSR = ~(_BV(WDRF)); //Some MCUs require the watchdog reset flag to be cleared before WDT can be disabled. & operation is skipped to spare few bytes as bits in MCUSR can only be cleared.
|
||||
#else
|
||||
MCUSR = ~(_BV(WDRF)); //Some MCUs require the watchdog reset flag to be cleared before WDT can be disabled. & operation is skipped to spare few bytes as bits in MCUSR can only be cleared.
|
||||
#endif
|
||||
wdt_disable(); //immediately disable watchdog in case it was running in the application to avoid perpetual reset loop
|
||||
}
|
||||
|
||||
#if BOOT_ADR > 0xFFFF
|
||||
#define PGM_READ_BYTE(x) pgm_read_byte_far(x)
|
||||
#else
|
||||
#define PGM_READ_BYTE(x) pgm_read_byte(x)
|
||||
#endif
|
||||
|
||||
#if USE_UART
|
||||
#include "uart/uart.h"
|
||||
#endif
|
||||
|
||||
#if USE_LED
|
||||
void init_leds();
|
||||
void led_power_on();
|
||||
void led_power_off();
|
||||
void led_power_toggle();
|
||||
void led_write_on();
|
||||
void led_write_off();
|
||||
void led_write_toggle();
|
||||
#endif
|
||||
void flash_erase (DWORD); /* Erase a flash page (asmfunc.S) */
|
||||
void flash_write (DWORD, const BYTE*); /* Program a flash page (asmfunc.S) */
|
||||
|
||||
|
||||
FATFS Fatfs; // Petit-FatFs work area
|
||||
BYTE Buff[SPM_PAGESIZE]; // Page data buffer
|
||||
|
||||
|
||||
|
||||
static uint8_t pagecmp(const DWORD fa, uint8_t buff[SPM_PAGESIZE])
|
||||
{
|
||||
UINT i;
|
||||
uint8_t b_flash,b_buff;
|
||||
for (i = 0; i < SPM_PAGESIZE; i++) {
|
||||
b_flash = PGM_READ_BYTE(fa+i);
|
||||
b_buff = buff[i];
|
||||
if ( b_flash != b_buff) {
|
||||
#if USE_UART //output first difference
|
||||
UART_puthex32(fa);UART_puts(PSTR(":"));
|
||||
UART_puthex(b_flash);UART_puts(PSTR(" "));
|
||||
UART_puthex(b_buff); UART_newline();
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#if USE_UART //output first difference
|
||||
UART_puthex32(fa);UART_puts(PSTR(":"));
|
||||
UART_puts(PSTR("="));UART_newline();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void doFlash() {
|
||||
DWORD fa; /* Flash address */
|
||||
UINT br; /* Bytes read */
|
||||
#if USE_LED
|
||||
uint8_t i;
|
||||
for(i=0;i<50;i++) { led_write_toggle();_delay_ms(100);} //Start Programming: Flash WRITE Wildly for 5 secs
|
||||
#endif
|
||||
|
||||
|
||||
for (fa = 0; fa < BOOT_ADR; fa += SPM_PAGESIZE) { /* Update all application pages */
|
||||
|
||||
memset(Buff, 0xFF, SPM_PAGESIZE); /* Clear buffer */
|
||||
pf_read(Buff, SPM_PAGESIZE, &br); /* Load a page data */
|
||||
|
||||
if (pagecmp(fa, Buff)) { /* Only flash if page is changed */
|
||||
#if USE_LED
|
||||
led_write_off();
|
||||
//led_power_on();
|
||||
#endif
|
||||
flash_erase(fa); /* Erase a page */
|
||||
flash_write(fa, Buff); /* Write it if the data is available */
|
||||
|
||||
} else {
|
||||
|
||||
#if USE_LED
|
||||
//led_power_off();
|
||||
led_write_on();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkFile() {
|
||||
uint8_t fresult;
|
||||
|
||||
fresult = pf_mount(&Fatfs); /* Initialize file system */
|
||||
|
||||
if (fresult != FR_OK) { /* File System could not be mounted */
|
||||
#if USE_UART
|
||||
UART_puts(PSTR("File not mounted"));
|
||||
UART_newline();
|
||||
#endif
|
||||
|
||||
#if USE_LED
|
||||
//uint8_t i;
|
||||
//led_write_on();
|
||||
//for(i=0;i<2*fresult;i++) { led_power_toggle();_delay_ms(500);}//Give error number while Write led is on
|
||||
//led_write_off();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
/*
|
||||
|
||||
WORD flashver = eeprom_read_word((const uint16_t *)E2END - 1);
|
||||
if (flashver > 999) {
|
||||
flashver = 0;
|
||||
}
|
||||
BYTE y, tmp;
|
||||
WORD x;
|
||||
BYTE found = 0;
|
||||
|
||||
for (x = flashver+10; x > flashver; x--) {
|
||||
y = x / 100;
|
||||
filename[5] = y + 0x30;
|
||||
tmp = x % 100;
|
||||
|
||||
y = tmp / 10;
|
||||
filename[6] = y + 0x30;
|
||||
tmp = x % 10;
|
||||
|
||||
filename[7] = tmp + 0x30;
|
||||
|
||||
if (pf_open(filename) == FR_OK) { // File opens normally
|
||||
found = 1;
|
||||
doProgram();
|
||||
}
|
||||
led_power_toggle();
|
||||
}
|
||||
|
||||
if (found == 0) {*/
|
||||
|
||||
fresult = pf_open(filename);
|
||||
|
||||
if (fresult != FR_OK) { /* File could not be opened */
|
||||
|
||||
#if USE_UART
|
||||
UART_puts(PSTR("File not open"));
|
||||
UART_newline();
|
||||
#endif
|
||||
#if USE_LED
|
||||
//uint8_t i;
|
||||
//led_power_on();
|
||||
//for(i=0;i<2*fresult;i++) { led_write_toggle();_delay_ms(500);}//Give error number while Power led is on
|
||||
//led_power_off();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
doFlash();
|
||||
|
||||
#if USE_LED
|
||||
led_write_off();
|
||||
//led_power_off();
|
||||
_delay_ms(2000);
|
||||
uint8_t i;
|
||||
//for(i=0;i<40;i++) { led_power_toggle();_delay_ms(50);}//SUCCESS FLASH WILDLY for 2 secs
|
||||
for(i=0;i<40;i++) { led_write_toggle();_delay_ms(50);}//SUCCESS FLASH WILDLY for 2 secs
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int main (void)
|
||||
{
|
||||
#if USE_LED
|
||||
init_leds();
|
||||
uint8_t i=0;
|
||||
#endif
|
||||
|
||||
#if USE_UART
|
||||
UART_init();
|
||||
UART_puts(PSTR("AVR_BOOT"));
|
||||
UART_newline();
|
||||
#endif
|
||||
while (1) {
|
||||
#if USE_LED
|
||||
//led_power_on();_delay_ms(200);led_power_off(); //Test Power Led
|
||||
led_write_on();_delay_ms(200);led_write_off(); //Test Write Led
|
||||
#endif
|
||||
|
||||
checkFile();
|
||||
|
||||
if (pgm_read_word(0) != 0xFFFF) ((void(*)(void))0)(); //EXIT BOOTLOADER
|
||||
|
||||
#if USE_UART
|
||||
UART_puts(PSTR("retry"));
|
||||
UART_newline();
|
||||
#endif
|
||||
#if USE_LED
|
||||
//for(i=0;i<10;i++) { led_power_toggle();_delay_ms(200);} //SOMETHING WENT WRONG: Flash Power LED
|
||||
for(i=0;i<10;i++) { led_write_toggle();_delay_ms(200);} //SOMETHING WENT WRONG: Flash Write LED
|
||||
#endif
|
||||
_delay_ms(5000); // Retry
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user