Добрый день! Есть задача прошить Attiny через spi c помощью другого контроллера. Сам обмен с контроллером происходит нормально, возвращается байт 0x53, но есть вопрос по поводу алгоритмов записи и чтения, у меня он происходит как-то не корректно, возможно я что-то упустил.
С начала я посылаю команду Programming Enable, получаю необходимый байт 0x53(третий), потом посылаю комманду Chip Erase (которая происходит успешно), получаю сдвинутые байты.
Теперь самое интересное, запись. Я выполняю команды Load Instruction(сначала загужаю младший байт):
-Load Program Memory Page, Low byte
-Load Program Memory Page, Hight byte
Для примера, есть массив c 6 байт array[6] = { 1, 2, 3, 4, 5, 6 }; для загрузки я делаю следующее:
0x40 0x00 0x00(адрес) 0x01(младший байт)
0x48 0x00 0x00(адрес) 0x02(старший байт)
0x40 0x00 0x01(адрес) 0x03(младший байт)
0x48 0x00 0x01(адрес) 0x04(старший байт)
0x40 0x00 0x02(адрес) 0x05(младший байт)
0x48 0x00 0x02(адрес) 0x06(старший байт)
Потом выполняю инструкцию Write Program Memory Page:
0x4C adr_MSB adr_LSB 0x00, где adr_MSB - это номер страницы(даташит, рис. 21.8), а Add_LSB смещение относ. базового адреса страницы. Начальный адресс флешь = 0x00.
0x4C 0x00(первая страница) 0x00(смещение относ. адреса текущей стр.) 0x00(всегда 0) - запись первого слова;
0x4C 0x00(первая страница) 0x01(смещение относ. адреса текущей стр.) 0x00(всегда 0) - запись второго слова(2-ух байт);
0x4C 0x00(первая страница) 0x02(смещение относ. адреса текущей стр.) 0x00(всегда 0) - запись третего слова;
Чтение:
Выполняю инструкцию Read(нужно прочитать 6 байт, те которые и записал...если записал):
Read Program Memory, Low byte 0x20 addr_MSB(номер стр.) adr_LSB(смещ. относ. адреса текущей стр.), любой байт(вернет low_data_byte);
Read Program Memory, High byte...
0x20 0x00(номер стр.) 0x00(смещ.) X(любой байт - возвр. low_data_byte) - должен получить значение "1"
0x28 0x00(номер стр.) 0x00(смещ.) X(любой байт - возвр. high_data_byte) - должен получить значение "2"
0x20 0x00(номер стр.) 0x01(смещ.) X(любой байт - возвр. low_data_byte) - должен получить значение "3"
0x28 0x00(номер стр.) 0x01(смещ.) X(любой байт - возвр. high_data_byte) - должен получить значение "4"
0x20 0x00(номер стр.) 0x02(смещ.) X(любой байт - возвр. low_data_byte) - должен получить значение "5"
0x28 0x00(номер стр.) 0x02(смещ.) X(любой байт - возвр. high_data_byte) - должен получить значение "6"
На самом деле, когда я по такому алгоритму записываю байт 50(сначала загружаю load, потом write, потом читаю) получается при чтении не то-что я писал, какая-то каша...когда пишу 6 байт, как у примере, то не записывается первый байт, а остальные 5 запис., опять же при увелич. колич. записанных байт за раз выходи каша.
Возможно я не правильно понял алгоритм записи и чтения, буду благодарен за просветление.
Приведу рабочий пример для tiny2313:
Код
// Load Program Memory Page 0100 H000 000x xxxx xxxx bbbb iiii iiii
static void PRG_LoadProgramMemoryPage(u16 ByteAddr, u8 B)
{
SPI_Exchange(0x40 | ((ByteAddr & 1) ? 0x08 : 0x00));
SPI_Exchange(0x00);
SPI_Exchange((ByteAddr >> 1) & 0x0F);
SPI_Exchange(B);
}
Когда адрес становится кратным размеру страницы, т.е. 32 байта, выполняем запись.
Код
// Write Program Memory Page 0100 1100 0000 00aa bbbb xxxx xxxx xxxx
static void PRG_WriteProgramMemoryPage(u16 ByteAddr)
{
SPI_Exchange(0x4C);
SPI_Exchange((ByteAddr >> 1) >> 8);
SPI_Exchange((ByteAddr >> 1) & 0xF0);
SPI_Exchange(0x00);
while(PRG_PollRDYBSY());
}
У меня Attiny48, но суть таже, спасибо, завтра буду пробовать. Выходит аргумент, который будет передан функции как адрес всегда будет кратен 16-ти словам: 0, 16, 32...
PRG_WriteProgramMemoryPage(u16 ByteAddr).
Цитата(Twen @ Apr 16 2012, 18:31)

Выходит аргумент, который будет передан функции как адрес всегда будет кратен 16-ти словам: 0, 16, 32...
PRG_WriteProgramMemoryPage(u16 ByteAddr).
Ну, тут используется побайтовая запись, а не словами, но в принципе да.
Кроме того младшие 5 бит (PAGE_SIZE = 32) в PRG_WriteProgramMemoryPage не используются и можно просто сделать так:
Код
PRG_ChipErase();
for(adr = 0; adr < (sizeof(slave_bin) | (PAGE_SIZE - 1)); adr++)
{
PRG_LoadProgramMemoryPage(adr, slave_bin[adr]);
if((adr & (PAGE_SIZE - 1)) == (PAGE_SIZE - 1))
{
PRG_WriteProgramMemoryPage(adr);
}
}
PAGE_SIZE тут для tiny2313 равен 32
slave_bin - массив u8 - собственно прошивка...
adr тип u16
НО, у tiny48 размер страницы записи PAGE_SIZE = 64 байта и соответственно необходимо скорректировать преобразование адресов в функциях PRG_LoadProgramMemoryPage и PRG_WriteProgramMemoryPage.
Цитата(Twen @ Apr 16 2012, 13:07)

Потом выполняю инструкцию Write Program Memory Page:
0x4C adr_MSB adr_LSB 0x00, где adr_MSB - это номер страницы(даташит, рис. 21.8), а Add_LSB смещение относ. базового адреса страницы. Начальный адресс флешь = 0x00.
0x4C 0x00(первая страница) 0x00(смещение относ. адреса текущей стр.) 0x00(всегда 0) - запись первого слова;
0x4C 0x00(первая страница) 0x01(смещение относ. адреса текущей стр.) 0x00(всегда 0) - запись второго слова(2-ух байт);
0x4C 0x00(первая страница) 0x02(смещение относ. адреса текущей стр.) 0x00(всегда 0) - запись третего слова;
Команда записи страницы подаётся одна на всю страницу. После чего ожидание готовности записи страницы.
Как уже сказано, с любым адресом внутри страницы, он игнорируется.
При желании слова FFFF внутри страницы можна командой Load не заносить (экономия времени передачи), но байты FF внутри слова заносить обязательно, так как иначе неправильно сформируется само слово.
Спасибо, сейчас буду пробовать.
Прошить получилось! Прошил бинарный файл, считал, значения сошлись, но после ресета програмного не стартует зашитая программа...возможно проблемы у бинарнике, которого я компилил у iar для AVR.
Код программы, которая зашивалась:
#define DDRA(x) (*(unsigned char *) 0x2D) = x
#define PORTA(x) (*(unsigned char *) 0x2E) = x
int main(void)
{
DDRA(8);
PORTA(8);
while(1);
}
Пин порта A3 должен был подняться в "1", а там 0...
Возможно нужно посмотреть на карту памяти...
Ниже, показаны настройки iar-а для компиляции bin файла.
Цитата(Twen @ Apr 17 2012, 14:10)

Прошить получилось! Прошил бинарный файл, считал, значения сошлись, но после ресета програмного не стартует зашитая программа...возможно проблемы у бинарнике, которого я компилил у iar для AVR.
Сам бинарник в студию!
Ребята, заработало, я скомпилировал bin файл у WinAVR и заработало ), пин поднялся.
Смотрите, есть такой вопрос, я не совсем понимаю... я скомпилировал код, в котором я просто включаю пин порта, прошил бинарный файл и все заработало, но когда я например скомпилирую такой код:
while (1) {
for (unsigned int i =0; i < 1000; i++) {
}
}
Ребята, заработало, я скомпилировал bin файл у WinAVR и заработало ), пин поднялся.
Смотрите, есть такой вопрос, я не совсем понимаю... я скомпилировал код, в котором я просто включаю пин порта, прошил бинарный файл и все заработало, но когда я например скомпилирую такой код:
Код
void main (void)
{
uint8_t state = 0;
while (1) {
for (uint32_t long i =0; i < 1000000; i++) {
if ( state == 0) {
DDRA = 0;
PORTA = 0;
} else {
DDRA = 1;
PORTA = 1;
}
}
state =~ state;
}
}
Переменные i и state должны быть размещены у RAM. Сами инструкции, код, будет прошиваться у Flash, а переменные... Компилятор сгенерирует когд, с инструкциями которые могут работать с RAM?
Когда я объявляю хотям бы одну переменную и компилирую файл, а потом его заливаю у Attiny48 он не работает...
У авр разное адресное пространство для flash и ram...А бинарник я заливаю у флешь...Вообщем не понятно почему не работает код залитый через spi в котором есть переменные ОЗУ.
Код генерил у WinAVR.
Работа с переменными в ОЗУ организуется в программе, залитой во флеш, так что тут никаких проблем.
Что такое «не работает»? Сколько времени ждали состояния «заработало»?
Зашивалось именно это, с циклом до миллиона?
А какая тактовая у микроконтроллера? По умолчанию 1 МГц?
А какой уровень оптимизации выставлен? При -O2 тут цикл до миллиона будет секунд 15-20 молотить до первой инверсии state, а без оптимизации я боюсь даже начинать считать сколько выйдет.
Частота по умолчанию 1Mhz, разную задержку ставил. Когда объявляю переменную и компилю не работает, а без переменных все отлично пашет, когда в программе только : DDRA = 0x08; PORTA = 0x08;
Генерировал bin файл у WinAVR и y IAR for AVR, писал на ассемблере и на С маленькие программки и ничего, порт устанавливает, а сам алгоритм не работает...то ли он виснет, толи я не знаю уже...
Может нужно установить какие-то фьюзы после прошивки ATtiny48 или watch-dog может сбрасывает, так он выкл. по умолчанию...кто-то прошивал по spi ATtiny48 ?
Зашил программу написанную на ассемблере, в которой я оперировал только с регистрами общего назначения и портами ввода-вывода, заработала только тогда кода я проинициализировал указатель стека в начале программы на 1FF(конец RAM). В иаре стек чего-то по умолчанию иницилизируется 13F.
Программа на с скомпилированная в иаре не работает при объявлении хотябы одной переменной...не пойму.
Цитата
А какой уровень оптимизации выставлен? При -O2 тут цикл до миллиона будет секунд 15-20 молотить до первой инверсии state, а без оптимизации я боюсь даже начинать считать сколько выйдет.
А почему вы говорите, что без оптимизации будет много? 1000000 тактов с частотой 1Mhz = 1 s.
Вот код и вложенные файлы(см. ниже) сделанные у WinAVR, без оптимизации(0 - стоит, оптимизация выкл.):
Код
#define DDRA(x) (*(unsigned char *) 0x2D) = x
#define PORTA(x) (*(unsigned char *) 0x2E) = x
#define SPL(x) (*(unsigned char *) 0x3D) = x;
#define SPH(x) (*(unsigned char *) 0x3E) = x;
int main(void)
{
SPL(0xFF);
SPH(0x01);
unsigned int i;
while(1) {
for(i = 0; i < 200; i++);
PORTA(0);
for(i = 0; i < 200; i++);
PORTA(8);
}
}
Это код у отладчике работает, а когда зашиваю - то нет.
Итог сегодняшней работы таков:
- в иаре для аvr создал проект с асемблерным файлом, в котором я инициализировал spi и дергал пином с интервалом 1с., скомпилил у иаре файл raw-bin, зашил его через spi, зашилось...пин дергается все работает и spi тоже.
- создал в иаре сишный проект с асмб. файлом и сишным, у асемблерном просто иниц. стек и прыгнул на main, у main дергал пином(задержку делал без переменные, с помощью __delay_cycles()) и иниц. spi., скомпилил, зашил работает тоже...
- создал в иаре сишный проект без асемблерного файла с переменной в качестве реализации задержки дерганния пином. В начальных адресах иар записывает ассемблерный код по умолчанию: иниц. переменных, стека...Зашил не работает!!!
Итог: Бинарные файлы для прошивки не работают те, которые я создавал на С с переменными и компилил в иаре и winAvr , виной всему я думаю, то как компилятор оперирует с переменными!
В avr гарвардская архитектара, разные адрессные шины и шины данных для разных типов памяти...может здесь кроется проблема?
Если вы компилили бинарнык дляпрошивки с сишного кода, с переменными, отпишитесь пожалуйста.
То есть не понятно, как писать бинарные файлы для прошивки на Си, если они не работают.
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.