1
|
#include <sys/types.h>
|
2
|
#include <lib_AT91SAM7.h>
|
3
|
#include <AT91SAM7.h>
|
4
|
#include <dfu/dbgu.h>
|
5
|
#include <board.h>
|
6
|
|
7
|
#define EFCS_CMD_WRITE_PAGE 0x1
|
8
|
#define EFCS_CMD_SET_LOCK_BIT 0x2
|
9
|
#define EFCS_CMD_WRITE_PAGE_LOCK 0x3
|
10
|
#define EFCS_CMD_CLEAR_LOCK 0x4
|
11
|
#define EFCS_CMD_ERASE_ALL 0x8
|
12
|
#define EFCS_CMD_SET_NVM_BIT 0xb
|
13
|
#define EFCS_CMD_CLEAR_NVM_BIT 0xd
|
14
|
#define EFCS_CMD_SET_SECURITY_BIT 0xf
|
15
|
|
16
|
static uint16_t page_from_ramaddr(const void *addr)
|
17
|
{
|
18
|
uint32_t ramaddr = (uint32_t) addr;
|
19
|
ramaddr -= (uint32_t) AT91C_IFLASH;
|
20
|
return ((ramaddr >> AT91C_IFLASH_PAGE_SHIFT));
|
21
|
}
|
22
|
#define PAGES_PER_LOCKREGION (AT91C_IFLASH_LOCK_REGION_SIZE>>AT91C_IFLASH_PAGE_SHIFT)
|
23
|
#define IS_FIRST_PAGE_OF_LOCKREGION(x) ((x % PAGES_PER_LOCKREGION) == 0)
|
24
|
#define LOCKREGION_FROM_PAGE(x) (x / PAGES_PER_LOCKREGION)
|
25
|
|
26
|
static int is_page_locked(uint16_t page)
|
27
|
{
|
28
|
uint16_t lockregion = LOCKREGION_FROM_PAGE(page);
|
29
|
|
30
|
return (AT91C_BASE_MC->MC_FSR & (lockregion << 16));
|
31
|
}
|
32
|
|
33
|
static void unlock_page(uint16_t page)
|
34
|
{
|
35
|
page &= 0x3ff;
|
36
|
AT91F_MC_EFC_PerformCmd(AT91C_BASE_MC, AT91C_MC_FCMD_UNLOCK |
|
37
|
AT91C_MC_CORRECT_KEY | (page << 8));
|
38
|
}
|
39
|
|
40
|
void flash_page(uint8_t *addr)
|
41
|
{
|
42
|
uint16_t page = page_from_ramaddr(addr) & 0x3ff;
|
43
|
uint32_t fsr = AT91F_MC_EFC_GetStatus(AT91C_BASE_MC);
|
44
|
DEBUGP("flash_page(0x%x=%u) ", addr, page);
|
45
|
|
46
|
if (is_page_locked(page)) {
|
47
|
DEBUGP("unlocking ");
|
48
|
unlock_page(page);
|
49
|
}
|
50
|
|
51
|
if (!(fsr & AT91C_MC_FRDY)) {
|
52
|
DEBUGP("NOT_FLASHING ");
|
53
|
return;
|
54
|
}
|
55
|
|
56
|
DEBUGP("performing start_prog ");
|
57
|
|
58
|
AT91F_MC_EFC_PerformCmd(AT91C_BASE_MC, AT91C_MC_FCMD_START_PROG |
|
59
|
AT91C_MC_CORRECT_KEY | (page << 8));
|
60
|
}
|
61
|
|
62
|
void flash_init(void)
|
63
|
{
|
64
|
unsigned int fmcn = AT91F_MC_EFC_ComputeFMCN(MCK);
|
65
|
|
66
|
AT91F_MC_EFC_CfgModeReg(AT91C_BASE_MC, (fmcn&0xff) << 16 |
|
67
|
AT91C_MC_FWS_3FWS);
|
68
|
}
|