Как загрузить данные из R2 в глобальную переменную с использованием asm?
- Войдите на сайт для отправки комментариев
Вс, 12/02/2017 - 22:46
Загрузчик сохраняет MCUSR в R2.
Пишу:
byte kmcusr;
__asm__ __volatile__ ("sts %0,r2":"=r"(kmcusr));
выдает ошибку "undefined reference to `r24'".
Пожалуйста, помогите правильно написать нутро asm.
Функция вернёт текущее значение R2
uint8_t r2(){asm volatile ("mov r24, r2" "\n\t" ); }Благодарю! Это тоже работает: register uint8_t tmp=0; asm volatile ("mov %[TMP],r2":[TMP]"=&r"(tmp):); kmcusr=tmp;Только все равно, MCUSR что по кнопке reset на ARDUINO, что при срабатывании WATCHDOG одинаков:
B00001000 , т.е. установлен WDRF: Watchdog System Reset Flag.
А мне бы хотелось знать, перезапуск ARDUINO произошел по WATCHDOG или по другой причине.
P.S.При отключении питания MCUSR B00000100, т.е. BORF: Brown-out Reset Flag.
Других значений не смог получить.
osetroff, да так и есть. Сам когда-то интересовался этим вопросом. Нужно копать в исходнике, почему сохранённый регистр не соответствует первозданному. Что-то там автор намудрил, и похоже сам не заметил. Ведь на работу лоадера это никак не влияет :)
Да, пришлось переделать optiboot.
//======================== //address in ram to save wbyte if we are inside bootloader //to know that watchdog event was happend inside bootloader, not in app #define waddr 0x4f0 #define wbyte 0x55 //exit from bootloader -> go to app static void startapp(){ watchdogConfig(WATCHDOG_2S); asm volatile ("clr r30 \n" "sts %[ADDR],r30 \n" "clr r31 \n" "ijmp \n" ::[ADDR]""(waddr)); } //=============================== int main(void) { register uint8_t ch = MCUSR; //save MCUSR for app: //==2 if was external reset //==4 if we get started or was low power //==8 if was watchdog interrupt inside app (not inside bootloader) GPIOR0=ch; watchdogConfig(WATCHDOG_500MS); MCUSR = 0; asm volatile ("clr __zero_reg__"); #if defined(__AVR_ATmega8__) || defined (__AVR_ATmega32__) SP=RAMEND; // This is done by hardware reset #endif //if not EXTRF goto app start if (!(ch & (_BV(EXTRF)))) { //test if we get watchdog reset when stay in bootloader register uint8_t tmp; asm volatile ("lds %[TMP],%[ADDR]":[TMP]"=&r"(tmp):[ADDR]""(waddr)); //we was inside bootloader -> clear WDRF if (tmp==wbyte) {GPIOR0=ch&(~_BV(WDRF))|_BV(EXTRF);} startapp(); } //set that we inside bootloader asm volatile ("ldi r24,%[WBT]\n" "sts %[ADDR],r24"::[ADDR]""(waddr),[WBT]""(wbyte));Сохраняю в RAM признак того, что я в bootloader.
Поэтому, когда внутри bootloader происходит reset по watchdog, я очищаю этот признак для программы.
У меня теперь в программе GPIOR0:
2 при внешнем reset;
4 при включении и потере питания;
8 при срабатывании watchdog внутри программы.
Может кто поможет передать код в репозиторий optiboot?
osetroff, по хорошему нужно написать автору оптибута. Его же эта тема тоже беспокоила, раз он в дистрибутив включил файлик test_reset.ino Собссно этот тест его и не работает как положено. Но это нужно сносно на инглише объясняться.
Запостил на github issue #197, может добавят в оффициальную сборку.