Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Алгоритм программирования FLASH памяти Atmega48
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
algidim
Здравствуйте ! В устройстве 2 микроконтроллера LPC1768 второй вспомогательный atmega48, хочется сделать так чтобы при начальной заливке или обновлении прошивки LPC1768 автоматически программировал atmega48… Т.е нужно написать программатор для atmega 48. Atmega48 подключена по SPI + вывод reset
Не могу разобраться с алгоритмом программирования FLASH памяти – читать память получается а вот записывать не очень )) Читаю по командам $28 (старший байт) $27 (младший байт).
Записывать я так понял там нужно по командам $40 и $48 в страницу памяти а потом по команде $4C переписывать во FLASH память.

Смотрел исподники avr910 там пишется байт по команде $40 и $48 а потом сразу же проверяется его запись, т.е читается по команде $28 и $27 . У меня при чтении читается байт, который там записан ( проверка реальным программатором ) а вот команды $40 и $48 получается проходят в холостую ))
Может кто подскажет алгоритм программирования Flash памяти ? или поделится исходником, где это понятно…
KRS
откопал свой программатор через старый FTDI bit bang (еще асинхронный)
Код
bool CFtdiItf::AtmelCmd(DWORD CmdCode,void* Res)
{
    DWORD Cmd;
    Cmd=((CmdCode & 0xFF000000)>>24) | ((CmdCode & 0x00FF0000)>>8) | ((CmdCode & 0x0000FF00)<<8);
    if (!Res) {
        Cmd|=((CmdCode & 0x000000FF)<<24);
        return Send(&Cmd,4);
    };
    if (!Send(&Cmd,3)) return false;
    return RecvByte(Res,CmdCode);
}

bool CFtdiItf::WritePage(const BYTE* Buf,unsigned Addr)
{
    DWORD Cmd;
    unsigned i;

    for(i=0;i<(PageSize>>1);i++) {
        Cmd=0x40000000 | (i<<8) | *Buf++;
        AtmelCmd(Cmd,0);
        Cmd=0x48000000 | (i<<8) | *Buf++;
        AtmelCmd(Cmd,0);
    }
    Addr&=~(PageSize-1);
    AtmelCmd(0x4C000000 | (Addr<<7),0);
    DoSync();
    Sleep(20);
    return true;
}

algidim
Цитата(KRS @ May 11 2012, 15:27) *
откопал свой программатор через старый FTDI bit bang (еще асинхронный)

Спасибо ! Сейчас попробую - кое чего понятно, т.е писать обязательно целой страницей ? А если мне нужно допустим записать 2 байта ))) все равно нужно писать целую страницу, просто остальные байты нужно в 0xFF установить ?
KRS
Цитата(algidim @ May 11 2012, 15:54) *
т.е писать обязательно целой страницей ? А если мне нужно допустим записать 2 байта ))) все равно нужно писать целую страницу, просто остальные байты нужно в 0xFF установить ?

да.
prottoss
Цитата(KRS @ May 11 2012, 18:08) *
да.
Нет. Не вводите человека в заблуждение. Если нужно записать байт меньше, чем размер страницы, нужно завершить запись командой записи страницы.

Вообще программирование очень подробно и внятно описано в разделе Serial Programming Algorithm любого МК AVR

Вот моя реализация алгоритма. Может сложно с наскоку, но, по крайней мере с комментами, так что должно быть понятно

CODE
/* Write memory parameters */
#pragma pack(ALIGN_INT8)
typedef struct __ISP2_WRITE_MEM_PARAM
{
UINT8 cmd_id; /* Command ID */
UINT16 num_bytes; /* Total number of bytes to program, LSB first */
UINT8 mode; /* Programming mode */
UINT8 delay; /* Delay, used for different types of programming termination,
according to mode byte */
UINT8 cmd_WrMem; /* Command 1 - Load Page, Write Programm Memory */
UINT8 cmd_WrPgm; /* Command 2 - Write Programm Memory Page */
UINT8 cmd_RdMem; /* Command 3 - Read Programm Memory */
UINT8 poll_1; /* Poll value 1 */
UINT8 poll_2; /* Poll value 2 - not using for flash programming */
UINT8 data[1]; /* Data array */

} ISP2_WRITE_MEM_PARAM, *P_ISP2_WRITE_MEM_PARAM;
#pragma pack()

/*******************************************************************************
*******************************************************************************/
static INT CMD_WriteMem(P_ISP2_WRITE_MEM_PARAM param, INT msg_len, UINT8 mem_type)
{
UINT8 byte, cmd[4], data[4];
UINT8 val_poll, rdy_poll;
INT i;

/* Check parameters */
if(msg_len < sizeof(ISP2_WRITE_MEM_PARAM) || /* Wrong message */
g_ISP2.state != ISP2_IN_PROG_STATE) /* Illegal programmer state */
return ISP2_STATUS_CMD_FAILED;

/* Get parameters */
param->num_bytes = SWAP16(param->num_bytes); /* Correct number of bytes read */

/* Make polling flags */
if(ISP2_WRMEM_MODE_PAGE & param->mode) /* Page mode */
{
val_poll = ISP2_WRMEM_MODE_PAGE_VALUE_POLL;
rdy_poll = ISP2_WRMEM_MODE_PAGE_READY_POLL;
}
else /* Word mode for flash, byte mode for eeprom */
{
val_poll = ISP2_WRMEM_MODE_WORD_VALUE_POLL;
rdy_poll = ISP2_WRMEM_MODE_WORD_READY_POLL;
}

/* Check delay value */
if(!param->delay)
param->delay = ISP2_CFG_DEF_WRITE_DELAY;

/* Check extended address for FLASH programming */
if(ISP2_MEM_TYPE_FLASH == mem_type && g_ISP2.prog_addr & 0x80000000)
{
cmd[0] = 0x4d; /* Load Extended Address command */
cmd[1] = 0x00;
cmd[2] = LOBYTE(HIWORD(g_ISP2.prog_addr));
cmd[3] = 0x00;
ISP_Tx(cmd, 32); /* Send extended address byte */
}

/* Write cycle */
for(i = 0; i < param->num_bytes; i++)
{
/* Load address and data byte */
cmd[1] = LOWORD(HIBYTE(g_ISP2.prog_addr));
cmd[2] = LOWORD(LOBYTE(g_ISP2.prog_addr));
cmd[3] = param->data[i];
byte = cmd[3];

/* Check memory type and make command byte */
if(ISP2_MEM_TYPE_FLASH == mem_type)
{
/* Make command byte (Load Page, Write Program Memory) &
increment address if hi byte writing */
if(i & 0x01)
{
cmd[0] = param->cmd_WrMem | 0x08; /* Make command for hight byte */
g_ISP2.prog_addr++; /* Increment address */
}
else
cmd[0] = param->cmd_WrMem & ~0x08; /* Make command for low byte */
}
else /* EEPROM */
{
cmd[0] = param->cmd_WrMem;
g_ISP2.prog_addr++; /* Increment address */
}

ISP_Tx(cmd, 32); /* Send command */

/* In page mode after send last byte need send command WRITE PAGE */
if(ISP2_WRMEM_MODE_PAGE & param->mode) /* Page mode */
{
if(i < param->num_bytes - 1 || !(ISP2_WRMEM_MODE_PAGE_WRITE_ENABLE & param->mode))
continue; /* It's not last byte or write page bit not set */

cmd[0] = param->cmd_WrPgm; /* Make Write Program Page command */
ISP_Tx(cmd, 32); /* Send PAGE WRITE command */
}

/* Check write success */
if(param->mode & val_poll) /* Value polling */
{
if((byte == param->poll_1) || /* Does not use polling if value is some for polling values */
(ISP2_MEM_TYPE_EEPROM == mem_type && byte == param->poll_2)) /* poll #2 use only EEPROM */
BOARD_DelayMS(param->delay);
else
{
/* Make READ command */
if(ISP2_MEM_TYPE_FLASH == mem_type)
{
if(i & 0x01) /* Make Read Program Memory command */
cmd[0] = param->cmd_RdMem | 0x08; /* Read hight byte */
else
cmd[0] = param->cmd_RdMem & ~0x08; /* Read low byte */
}
else
cmd[0] = param->cmd_RdMem;

/* Wait, when value was write complete */
BOARD_SetTimeout(param->delay);
do
{
ISP_Ex(cmd, data, 32); /* Send command */
if(BOARD_IsTimeout())
return ISP2_STATUS_CMD_TOUT;
}
while(data[3] != byte);
}
}
else
{
if(param->mode & rdy_poll) /* RDY/BSY polling */
{
if(FALSE == WaitReady(param->delay))
return ISP2_STATUS_CMD_TOUT;
}
else /* Timed delay */
BOARD_DelayMS(param->delay);
}
}
return ISP2_STATUS_CMD_OK;
}


Это общий алгоритм для ВСЕХ AVR. Все зависит от параметров.
KRS
Цитата(prottoss @ May 11 2012, 16:32) *
Нет. Не вводите человека в заблуждение. Если нужно записать байт меньше, чем размер страницы, нужно завершить запись командой записи страницы.

флешь пишется только по страницам и не записанные в буфер байты не обязательно будут 0xff
prottoss
Цитата(KRS @ May 11 2012, 18:41) *
флешь пишется только по страницам и не записанные в буфер байты не обязательно будут 0xff
И ЧЁ rolleyes.gif
algidim
Для программирования FLASH его нужно предварительно стереть ?
ArtemKAD
Цитата
Для программирования FLASH его нужно предварительно стереть ?

Да. Иначе локи(биты защиты) не дадут ничего сделать.
ReAl
Цитата(prottoss @ May 11 2012, 15:32) *
Нет. Не вводите человека в заблуждение. Если нужно записать байт меньше, чем размер страницы, нужно завершить запись командой записи страницы.
Более того, слова FF в середине данных для страницы тоже можно не писать в буфер.

Цитата(KRS @ May 11 2012, 15:41) *
флешь пишется только по страницам и не записанные в буфер байты не обязательно будут 0xff
Если флеш не стёрт, то во флеше вообще каша может получиться из AND старого и нового.
Что касается буфера, то «не записанные в буфер байты» будут не FF только в одном случае (если я правильно помню детали, это дело в avreal подправлено давно и не трогалось с тех пор):
Пишем в буфер страницы слово из не-FF по адресу, например, 2 (байты 2 и 3).
Теперь пишем один байт по адресу, скажем, 7.
Байты 0,1, 4,5, от 8 до конца будут FF.
В байте 7 будет то, что в него писали, а в байте 6 будет копия байта 2.
Посему при экономии времени передачи в AVR по SPI команд занесения байтов в буфер страницы можно выбрасывать только целые FF-слова.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.