ATTiny2313: использование инструкции SPM

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
eqltv
Открыл глаза
Сообщения: 63
Зарегистрирован: Вс янв 31, 2010 17:16:17

ATTiny2313: использование инструкции SPM

Сообщение eqltv »

Хочу использовать память программ для долговременного хранения данных. Почитал AVR109 про самопрошивку и написал такой код (привожу только ту часть, которая пытается работать с памятью программ):

Код: Выделить всё

   ; Считать байт и проверить его на равенство 0xff
   ldi   r30, lo8(1024)
   ldi   r31, hi8(1024)
   lpm
   inc   r0
   brne   end

   ; заполнить таблицу словом 0xaa55
   ldi   r18, 0x55
   ldi   r19, 0xaa
   mov   r0, r18
   mov   r1, r19
   ldi   r19, PGSIZE
l1:   ldi   r18, 1
   out   SPMCSR, r18
   spm
   adiw   r30, 2
   dec   r19
   brne   l1
   ; записать
   ldi   r30, lo8(1024)
   ldi   r31, hi8(1024)
   ldi   r18, 5
   out   SPMCSR, r18
   spm
end:      
   rjmp   end

Ожидается, что в 16 словах с адреса 1024 будет записано 0xAA55. Но они остаются незапрограммированными.
Кроме того, возник вопрос про "bootloader". В описании tiny2313 совсем ничего о нем не сказано, а фьюзы, которыми он управляется, помечены неиспользуемыми. Но про самопрограммирование там есть - запись в любую область памяти останавливает процессор на время записи, как будто вся память образует этот bootloader.
Помогите разобраться и понять, почему не работает код.
Аватара пользователя
GP1
Поставщик валерьянки для Кота
Сообщения: 2401
Зарегистрирован: Пт май 23, 2008 19:32:22
Откуда: Россия, Волгоград
Контактная информация:

Сообщение GP1 »

Если я ничего не путаю, вот так из текста программы использовать SPM не получится.
Чем дальше, тем больше становлюсь занудой...
Изображение
eqltv
Открыл глаза
Сообщения: 63
Зарегистрирован: Вс янв 31, 2010 17:16:17

Сообщение eqltv »

GP1 писал(а):Если я ничего не путаю, вот так из текста программы использовать SPM не получится.

А как получится? Откуда ее вызывать, если в даташите ничего про бутлоадер не сказано?
uchar
Родился
Сообщения: 8
Зарегистрирован: Чт янв 28, 2010 16:27:21

Сообщение uchar »

Могу ошибаца, но мое предположение такое - записывая в регистр Z адрес ячейки, начиная с которой хотите писать свои данные, надо сдвинуть адрес на 1 влево :

Код: Выделить всё

ldi      ZL,Low (SerialN<<1)
ldi      ZH,High(SerialN<<1)


А дальше после записи каждого байта делать инкремент Z.

Тут все дело в том, что в регистре Z 15 старших бит указывают на адрес ячейки, а младший бит указывает на то, старший или младший байт ячейки вы будете читать/писать.

Полагаю, что сейчас вы пишете во флэш, но только совсем ну туда, куда хотите. У меня все было именно так, только при чтении :)
eqltv
Открыл глаза
Сообщения: 63
Зарегистрирован: Вс янв 31, 2010 17:16:17

Сообщение eqltv »

Написал на C программу (avr-libc) - тоже не работает. Вот код:

Код: Выделить всё

BOOTLOADER_SECTION
void fillPage(unsigned int addr, unsigned int word)
{
   int i;
   for(i = 0; i < SPM_PAGESIZE; i+=2)
   {
      boot_page_fill(addr + i, word);
   }
}

BOOTLOADER_SECTION
void writePage(unsigned int addr)
{
   boot_page_write(addr);
   boot_spm_busy_wait();
   //boot_rww_enable();
}

BOOTLOADER_SECTION
void erasePage(unsigned int addr)
{
   boot_page_erase(addr);
   boot_spm_busy_wait();
}

int main()
{
   unsigned char b = 0;
   unsigned int addr = 0;
   unsigned int pgaddr = 0;
   lptInit();
   while(1)
   {
      b = lptRecv(0xcc);
      addr = 0;
      switch(b)
      {
         case 1: // lpm
            addr |= lptRecv(0xa0);
            addr |= lptRecv(0xa1)<<8;
            lptSend(pgm_read_byte_near(addr));
            break;
         case 2: // set page address
            addr |= lptRecv(0xa0);
            addr |= lptRecv(0xa1)<<8;
            pgaddr = addr;
            break;
         case 3: // fill page with word
            addr |= lptRecv(0xd0);
            addr |= lptRecv(0xd1)<<8;
            fillPage(pgaddr, addr);
            break;
         case 4: // write page
            writePage(pgaddr);
            break;
         case 5: // erase page
            erasePage(pgaddr);
            break;
         case 6: // lpm 2 bytes from pgaddr
            lptSend(pgm_read_byte_near(pgaddr));
            lptSend(pgm_read_byte_near(pgaddr+1));
            break;
         default:
            break;
      }
   }
   return 0;
}


lpt* - это команды общения с компьютером. Всё работает правильно, кроме записи во флэш. Пытался даже просто стереть страницу с адресом 0, не стерлась.
Почему не работает? Как заставить?
eqltv
Открыл глаза
Сообщения: 63
Зарегистрирован: Вс янв 31, 2010 17:16:17

Сообщение eqltv »

Всё, проблема решена. Нужно было запрограммировать бит SELFPRGEN(0) из efuse. Выводы - нужно читать весь даташит, а не только отдельную главу.
uchar
Родился
Сообщения: 8
Зарегистрирован: Чт янв 28, 2010 16:27:21

Сообщение uchar »

Перечитал документацию ешо раз - все написанное мной выше относица только к чтению данных из флэша, т.е. к команде LPM.
При записи все будет иначе.
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»