forked from mharizanov/avr_boot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
152 lines (127 loc) · 4.65 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*-------------------------------------------------------------------------/
/ 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 sdescribed 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.
/
/-------------------------------------------------------------------------*/
/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duomilanuove */
/* other boards like e.g. Crumb8, Crumb168 are using PB2 */
/* Arduino Ethernet is PB1 */
#define LED_DDR DDRB
#define LED_PORT PORTB
#define LED_PIN PINB
#define LED PINB1
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <string.h>
#include "pff.h"
#include <avr/eeprom.h>
#include <util/delay.h>
void flash_erase (DWORD); /* Erase a flash page (asmfunc.S) */
void flash_write (DWORD, const BYTE*); /* Program a flash page (asmfunc.S) */
void flash_led(uint8_t);
FATFS Fatfs; /* Petit-FatFs work area */
BYTE Buff[SPM_PAGESIZE]; /* Page data buffer */
static uint8_t
pagecmp(uint16_t addr, uint8_t *data)
{
uint16_t i;
for (i = 0; i < SPM_PAGESIZE; i++) {
if (pgm_read_byte(addr++) != *data++)
return 1;
}
return 0;
}
int main (void)
{
DWORD fa; /* Flash address */
WORD br; /* Bytes read */
uint8_t i = 0;
uint8_t ch = 0;
/* set LED pin as output */
LED_DDR |= _BV(LED);
pf_mount(&Fatfs); /* Initialize file system */
/* read board name from eeprom to Buff */
while(i<13) { //8+'.'+3
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
while(EECR & (1<<EEPE));
EEAR = (uint16_t)(void *)E2END -i;
EECR |= (1<<EERE);
ch =EEDR;
#else
ch = eeprom_read_byte((void *)E2END - i);
#endif
if( ch == 0xFF) break;
Buff[i] = ch;
i++;
}
Buff[i] = '\0';
ch=0; /* Re-use the variable to save space, now we use it to check if EEPROM or hard-coded file name exists */
if (i) { /* File name found in EEPROM */
if (pf_open(Buff) == FR_OK) { /* File opens normally */
ch=1;
}
}
else { /* No EEPROM file name found, or the EEPROM file name could not be located on the SD card, so revert tp the hard-coded name */
if (pf_open("app.bin") == FR_OK) ch=1;
}
if (ch) { /* Open application file */
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 (br) { /* Bytes Read > 0? */
for (i = br; i < SPM_PAGESIZE; i++) /* Pad the remaining last page with 0xFF so that comparison goes OK */
Buff[i] = 0xFF;
if (pagecmp(fa, Buff)) { /* Only flash if page is changed */
LED_PORT |= _BV(LED);
flash_erase(fa); /* Erase a page */
flash_write(fa, Buff); /* Write it if the data is available */
LED_PORT &= ~_BV(LED);
}
}
}
}
if (pgm_read_word(0) != 0xFFFF) /* Start application if exist */
((void(*)(void))0)();
for (;;) ; /* No application, Halt. */
}
void flash_led(uint8_t count)
{
while (count--) {
LED_PORT |= _BV(LED);
_delay_ms(100);
LED_PORT &= ~_BV(LED);
_delay_ms(80);
}
}