-
Notifications
You must be signed in to change notification settings - Fork 18
/
fls.c
76 lines (62 loc) · 1.88 KB
/
fls.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
#include "fls.h"
#include <avr/boot.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h> /* for sei(), cli() */
// attiny85 SPM_PAGESIZE is 64 bytes
#define FLS_IS_PAGE_ALIGNED(x) ((x%SPM_PAGESIZE) == 0u)
#define FLS_IS_WORD_ALIGNED(x) ((x%2) == 0u)
// Local functions prototype
void fls_writePage(uint16_t byteaddr);
void fls_erasePage(uint16_t byteaddr);
void fls_loadPage(const uint8_t* buff, uint16_t byteaddr);
void fls_writePage(uint16_t byteaddr) {
cli();
boot_page_write_safe(byteaddr); // will halt CPU, no waiting required
sei();
}
void fls_erasePage(uint16_t byteaddr){
cli();
boot_page_erase_safe(byteaddr);
sei();
}
void fls_loadPage(const uint8_t* buff, uint16_t byteaddr){
uint8_t i;
uint16_t w;
for(i=0; i<SPM_PAGESIZE; i+=2)
{
// Set up little-endian word.
w = *buff++;
w += (*buff++) << 8;
boot_page_fill (byteaddr + i, w);
}
}
void FLS_write(uint8_t* buff, uint16_t startaddr, uint16_t size){
uint8_t tempBuff[SPM_PAGESIZE];
uint8_t eraseBuffStart;
uint8_t eraseBuffEnd;
uint8_t totalBytesPending;
uint16_t alignedStartAddr;
uint16_t i;
uint8_t j;
i = 0;
while(i<size)
{
alignedStartAddr = (startaddr+i) & 0xFFC0; /* 5 last bytes are not usefull */
eraseBuffStart = (startaddr+i) & ~(0xFFC0);
totalBytesPending = (size-i);
eraseBuffEnd = eraseBuffStart+totalBytesPending;
if( eraseBuffEnd > SPM_PAGESIZE )
{
eraseBuffEnd = SPM_PAGESIZE;
}
memcpy_P((void*)tempBuff,(void*)alignedStartAddr, SPM_PAGESIZE);
fls_erasePage(alignedStartAddr);
for(j=eraseBuffStart; j<eraseBuffEnd; j++)
{
tempBuff[j] = *buff++;
}
fls_loadPage(tempBuff,alignedStartAddr);
fls_writePage(alignedStartAddr);
i+= eraseBuffEnd-eraseBuffStart;
}
}