Приветствую!
Пытаюсь перепрограммировать ПИК по ICSP протоколу, чтение и Bulk Erase работают на ура.
При поблочной записи (блок - 4 слова) возникает следующий баг - программа пишет периодично, записывает во флеш 4 слова
(1 операция записи), потом 16 слов пропускает и так в периоде.
Для теста пробовал писать туда просто инкрементирующийся буфер 1, 2, 3.... 256 - при чтении получаем следующее:
00 01 02 03 FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF
14 15 16 17 FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF
..........
Перед записью проводится операция BulkErase всего устройства (код 80h по адресу 3С0004h).
Как не извращался - использовал режим мульти и сингл панельной записи, режим модификации (сначала удаляется по 64 байта, потом пишется в эту область) - результат тот же. В чем может быть дело?
Функции записи и удаления - ниже.
Алгоритм - сначала вызывается функция BulkEraseBlocks(void).
Через паузу в цикле начинает вызываться функция SinglePanelWriteWord(void)
CODE
// Процедура посылает 20ти битную команду - 4 бита опкод и 16 бит расширенной команды
void SendCommandAndData(int cmd, uint16 data)
{
static int counter;
RGC = 0; NOP;
// Цикл передачи команды
for(counter = 0; counter < 4; counter++)
{
// Устаналиваем бит команды в порт
RGDO = (cmd & 0x01); NOP;
// CLOCK = 1
RGC = 1; NOP;
// CLOCK = 0
RGC = 0; NOP;
// Сдвигаем команду вправо на 1 (получаем следующий бит)
cmd >>= 1;
}
NOP;
// Цикл передачи данных
for(counter = 0; counter < 16; counter++)
{
// Устаналиваем бит данных в порт
RGDO = (data & 0x01); NOP;
// CLOCK = 1
RGC = 1; NOP;
// CLOCK = 0
RGC = 0; NOP;
// Сдвигаем данные вправо на 1 (получаем следующий бит)
data >>= 1;
}
NOP;
}
// НОП после команды на запись 8 байт
void WriteNOPPause(void)
{
static int counter;
// Устаналиваем бит данных в ноль
RGDO = 0; NOP;
// Цикл передачи команды NOP
for(counter = 0; counter < 4; counter++)
{
// CLOCK = 1
RGC = 1; NOP;
if (counter < 3)
{
// CLOCK = 0
RGC = 0; NOP;
}
}
}
// Запись слова по адресу в режиме однопанельной записи
void SinglePanelWriteWord(void)
{
static int counter;
static int AddressPart;
// Задержка Р10 после снятия SCLK перед новым циклом записи
RGC = 0; NOP;
for (counter = 0; counter < 1000; counter++)
{
NOP;
}
// Step 1: Direct access to config memory.
SendCommandAndData(NOPoperator, 0x8EA6); // BSF EECON1, EEPGD
SendCommandAndData(NOPoperator, 0x8CA6); // BSF EECON1, CFGS
SendCommandAndData(NOPoperator, 0x86A6); // BSF EECON1, WREN
// Step 2: Configure device for single-panel writes.
SendCommandAndData(NOPoperator, 0x0E3C); // MOVLW 3Ch
SendCommandAndData(NOPoperator, 0x6EF8); // MOVWF TBLPTRU
SendCommandAndData(NOPoperator, 0x0E00); // MOVLW 00h
SendCommandAndData(NOPoperator, 0x6EF7); // MOVWF TBLPTRH
SendCommandAndData(NOPoperator, 0x0E06); // MOVLW 06h
SendCommandAndData(NOPoperator, 0x6EF6); // MOVWF TBLPTRL
SendCommandAndData(TabWr, 0x00); // Write 0h to 3C0006h to enable single-panel write.
// Step 3: Direct access to code memory.
SendCommandAndData(NOPoperator, 0x8EA6); // BSF EECON1, EEPGD
SendCommandAndData(NOPoperator, 0x9CA6); // BCF EECON1, CFGS
// Step 4: Load write buffer for panel.
SendCommandAndData(NOPoperator, 0x0E00); // MOVLW <Addr[21:16]> = 00
SendCommandAndData(NOPoperator, 0x6EF8); // MOVWF TBLPTRU
// Выделяем биты 15:8 адреса
AddressPart = WriteAddress;
AddressPart >>= 8;
AddressPart = AddressPart & 0xFF;
SendCommandAndData(NOPoperator, 0x0E00 + AddressPart); // MOVLW <Addr[15:8]>
SendCommandAndData(NOPoperator, 0x6EF7); // MOVWF TBLPTRH
// Выделяем биты 7:0 адреса
AddressPart = WriteAddress;
AddressPart = AddressPart & 0xFF;
SendCommandAndData(NOPoperator, 0x0E00 + AddressPart); // MOVLW <Addr[7:0]>
SendCommandAndData(NOPoperator, 0x6EF6); // MOVWF TBLPTRL
// Передаем 1-е слово
SendCommandAndData(TabWrPostInc, InputPICData[0]);
// Передаем 2-е слово
SendCommandAndData(TabWrPostInc, InputPICData[1]);
// Передаем 3-е слово
SendCommandAndData(TabWrPostInc, InputPICData[2]);
// Передаем 4-е слово в регистр и начинаем программирование
SendCommandAndData(TabWrPreInc, InputPICData[3]);
// НОП после записи с удержанием SCLK = 1 время Р9 = 1мс
WriteNOPPause();
WriteAddress = WriteAddress + 8;
}
// НОП после команды на удаление
void EraseNOPPause(void)
{
static int counter;
// Устаналиваем бит данных в ноль
RGDO = 0; NOP;
// Цикл передачи команды NOP
for(counter = 0; counter < 4; counter++)
{
// CLOCK = 1
RGC = 1; NOP;
RGC = 0; NOP;
}
}
// Bulk Erase device
void BulkEraseBlocks(void)
{
SendCommandAndData(NOPoperator, 0x0E3C); // MOVLW 3Ch
SendCommandAndData(NOPoperator, 0x6EF8); // MOVWF TablePTRU
SendCommandAndData(NOPoperator, 0x0E00); // MOVLW 00h
SendCommandAndData(NOPoperator, 0x6EF7); // MOVWF TablePTRH
SendCommandAndData(NOPoperator, 0x0E04); // MOVLW 04h
SendCommandAndData(NOPoperator, 0x6EF6); // MOVWF TablePTRL
SendCommandAndData(TabWr, 0x0080);
// Посылаем 4х разрядный последовательны 0, удерживаем SCLK = 0 время Р11
EraseNOPPause();
}
Модератор. Для включения в сообщение объемных исходных текстов пользуйтесь тегами codebox вместо code.