Существует задача перешивать базу данных, находящуюся во FLASH контроллера, из собственной EEPROM
Загрузчик базы я написал, работает, а вот с оновным кодом проблеммы...
Как сделать перезагрузку контроллера желательно не через WD?
По идее я сначала заливаю основную программу, затем шью в конец FLASH бутлоадер.
Как можно узнать что проц стартует правильно т.е. с бутлоадера (его работу проверял через Jtag), и при перезагрузке, вызванной основной прграммой.
Может есть какой-то другой способ перешивать флешь, и загрузчик отдельный делать не обязательно, а надо просто функцию в бут области разместить? (я не знаю как).
Fuses
OSCCAL = C7, C7, BF, BF
BLEV = 0
BODEN = 0
SUT = 2
CKSEL = F
BLB1 = 3
BLB0 = 3
OCDEN = 1
JTAGEN = 0
CKOPT = 0
EESV = 1
BSIZ = 2
BRST = 0
M103C = 1
WDTON = 1
Собственно код загрузчика (слизан у Атмел)
Код
/**************** Библиотеки общего назначения ******************/
#include <board.h>
/**************** Подключаемые внешние модули всякие******************/
#include "main.h"
#define BLOCKSIZE 256 // байт
#define SCMDCOUNT 70
#define SCMDLEN (1/*блока*/ * BLOCKSIZE /**/) // 256
#define SCMDADDR 10240
#define LCMDCOUNT 15
#define LCMDLEN (2/*блока*/ * BLOCKSIZE /**/) //512
#define LCMDADDR (SCMDADDR+(SCMDCOUNT*SCMDLEN))
typedef struct database{
unsigned short s_addr;
unsigned short e_addr;
unsigned short data[384];
}pdatabase;
#define _ENABLE_RWW_SECTION() __DataToR0ByteToSPMCR_SPM( 0x00, 0x11 )
#define _WAIT_FOR_SPM() while( SPMCR & (1<<SPMEN) );
#define _LOAD_PROGRAM_MEMORY(addr) __load_program_memory( (const unsigned char __flash *) (addr) )
#define _FILL_TEMP_WORD(addr,data) __AddrToZWordToR1R0ByteToSPMCR_SPM( (void __flash *) (addr), data, 0x01 )
#define _PAGE_ERASE(addr) __AddrToZByteToSPMCR_SPM( (void __flash *) (addr), 0x03 )
#define _PAGE_WRITE(addr) __AddrToZByteToSPMCR_SPM( (void __flash *) (addr), 0x05 )
__no_init __eeprom database db@15;
void BlockLoad(unsigned int size, unsigned long *address, unsigned short *cnt)
{
unsigned int data;
long tempaddress;
tempaddress = (*address); // Store address in page.
do
{
data = db.data[(*cnt++)];
#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
_FILL_TEMP_WORD(*address,data);
#pragma diag_default=Pe1053 // Back to default.
(*address)+=2; // Select next word in memory.
size -= 2; // Reduce number of bytes to write by two.
} while(size); // Loop until all bytes written.
#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
_PAGE_WRITE(tempaddress);
#pragma diag_default=Pe1053 // Back to default.
_WAIT_FOR_SPM();
_ENABLE_RWW_SECTION();
// (*address) >>= 1; // Convert address back to Flash words again.
}
__C_task main(void)
{
unsigned long addr;
unsigned long s_addr;
unsigned long e_addr;
unsigned short i;
unsigned char block_count;
unsigned short ee_cnt;
void (*funcptr)( void ) = 0x0000; // Set up function pointer to RESET vector.
__disable_interrupt();
_ENABLE_RWW_SECTION();
//for(i=0;i<384;i++)db.data[i]=i;
//db.s_addr = 10240;
//db.e_addr = 11008;
s_addr = db.s_addr;
e_addr = db.e_addr;
if(s_addr>=64000)s_addr = 0x00;
while(1){
if(s_addr)
{// есть задание записать пару блоков
addr = s_addr;
block_count = ((e_addr-s_addr)/BLOCKSIZE); // расчитываю количество
ee_cnt = 0x00;
for(i=0;i<block_count;i++)BlockLoad(BLOCKSIZE, &addr, &ee_cnt);
}
s_addr = 0x00;
e_addr = 0x00;
db.s_addr = 0x00;
db.e_addr = 0x00;
funcptr(); // Перехожу к основной программе
}
}
#include <board.h>
/**************** Подключаемые внешние модули всякие******************/
#include "main.h"
#define BLOCKSIZE 256 // байт
#define SCMDCOUNT 70
#define SCMDLEN (1/*блока*/ * BLOCKSIZE /**/) // 256
#define SCMDADDR 10240
#define LCMDCOUNT 15
#define LCMDLEN (2/*блока*/ * BLOCKSIZE /**/) //512
#define LCMDADDR (SCMDADDR+(SCMDCOUNT*SCMDLEN))
typedef struct database{
unsigned short s_addr;
unsigned short e_addr;
unsigned short data[384];
}pdatabase;
#define _ENABLE_RWW_SECTION() __DataToR0ByteToSPMCR_SPM( 0x00, 0x11 )
#define _WAIT_FOR_SPM() while( SPMCR & (1<<SPMEN) );
#define _LOAD_PROGRAM_MEMORY(addr) __load_program_memory( (const unsigned char __flash *) (addr) )
#define _FILL_TEMP_WORD(addr,data) __AddrToZWordToR1R0ByteToSPMCR_SPM( (void __flash *) (addr), data, 0x01 )
#define _PAGE_ERASE(addr) __AddrToZByteToSPMCR_SPM( (void __flash *) (addr), 0x03 )
#define _PAGE_WRITE(addr) __AddrToZByteToSPMCR_SPM( (void __flash *) (addr), 0x05 )
__no_init __eeprom database db@15;
void BlockLoad(unsigned int size, unsigned long *address, unsigned short *cnt)
{
unsigned int data;
long tempaddress;
tempaddress = (*address); // Store address in page.
do
{
data = db.data[(*cnt++)];
#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
_FILL_TEMP_WORD(*address,data);
#pragma diag_default=Pe1053 // Back to default.
(*address)+=2; // Select next word in memory.
size -= 2; // Reduce number of bytes to write by two.
} while(size); // Loop until all bytes written.
#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
_PAGE_WRITE(tempaddress);
#pragma diag_default=Pe1053 // Back to default.
_WAIT_FOR_SPM();
_ENABLE_RWW_SECTION();
// (*address) >>= 1; // Convert address back to Flash words again.
}
__C_task main(void)
{
unsigned long addr;
unsigned long s_addr;
unsigned long e_addr;
unsigned short i;
unsigned char block_count;
unsigned short ee_cnt;
void (*funcptr)( void ) = 0x0000; // Set up function pointer to RESET vector.
__disable_interrupt();
_ENABLE_RWW_SECTION();
//for(i=0;i<384;i++)db.data[i]=i;
//db.s_addr = 10240;
//db.e_addr = 11008;
s_addr = db.s_addr;
e_addr = db.e_addr;
if(s_addr>=64000)s_addr = 0x00;
while(1){
if(s_addr)
{// есть задание записать пару блоков
addr = s_addr;
block_count = ((e_addr-s_addr)/BLOCKSIZE); // расчитываю количество
ee_cnt = 0x00;
for(i=0;i<block_count;i++)BlockLoad(BLOCKSIZE, &addr, &ee_cnt);
}
s_addr = 0x00;
e_addr = 0x00;
db.s_addr = 0x00;
db.e_addr = 0x00;
funcptr(); // Перехожу к основной программе
}
}