Зачем нужен цикл while в main для вызова ISR в arduino UNO?

Я пишу код C, который загружается в arduino uno. Это было простое упражнение по изучению того, как вызывать ISR на C. Вот код:

#include<stdio.h>
#include<stdlib.h>
#include<avr/interrupt.h>
#include<avr/io.h>


int main(){

 DDRB        = 0;
 PORTB       = 0;
 DDRB        = (1<<5);
 PORTB       = (0<<5);

 //resetting the Timer/Counter1
 TCNT1H         = 0;
 TCNT1L         = 0;  

 //disabling all global interrupts
 SREG         = 0;

 //defining prescalar

 //TCCR1B: ICNC1 ICES1 – WGM13 WGM12 CS12 CS11 CS10
 TCCR1B = 0;
 //TCCR1B_reg = CS11_val; WORKING SETTINGS
 TCCR1B = 0b00000101;//(1<<CS10_val)|(1<<CS12_val);

 //setting up PWM mode

 //TCCR1A: COM1A1 COM1A0 COM1B1 COM1B0 COM1C1 COM1C0 WGM11 WGM10
 TCCR1A      = 0; //this is for waveform generation and CTC setting up mode;
 //TCCR1A      = 0b10000000;//(1<<COM1A1_val);
 TCCR1A      = COM1A1;

 OCR1AH      = 0b10011100;//0b00000000;
 OCR1AL      = 0b01000000;//0b01000000;

 TIMSK1      = 0b00100010;//(1<<ICIE1_val)|(1<<OCIE1A_val);//0b00100010;//writing so that output compare A is set up

 //enable global interrupts
 SREG         = (1<<7);
 while(1){}

 return 0;

}

ISR(TIMER1_COMPA_vect){
  PORTB = PORTB^(1<<5);
}

Интересно то, что когда я избавляюсь от «пока (1) {}», код, похоже, не работает для переключения PinB5 (встроенный светодиод на arduino uno). Как только я добавил в цикл while, я увидел переключение PinB5. Странная часть заключается в том, что когда я хочу использовать таймер для создания ШИМ, который выводит напрямую на вывод, мне не нужно использовать цикл while.

На всякий случай, если вам интересно, вот как я загружаю на arudino-uno:

avr-gcc -Os -DF_CPU=16000000UL -mmcu=atmega328p -c -o ISR_example.o ISR_example.c
avr-gcc -mmcu=atmega328p ISR_example.o -o ISR_example
avr-objcopy -O ihex -R .eeprom ISR_example ISR_example.hex

read -p "Get ready to flash!"
#flashing the Arduino:
avrdude -C/home/ashwini/Downloads/arduino-1.8.3/hardware/tools/avr/etc/avrdude.conf -v -patmega328p -carduino -P/dev/ttyACM0 -b115200 -D -Uflash:w:ISR_example.hex:i

person ahat    schedule 07.08.2017    source источник
comment
зависит от того, как выглядит загрузчик, можно было бы надеяться/ожидать, что он просто попадет в бесконечный цикл и сделает то же самое, но, возможно, здесь это не так. Поможет быстрый разбор вызова main().   -  person old_timer    schedule 07.08.2017
comment
@old_timer Стандартный код запуска AVR просто CLI заканчивается мертвой петлей.   -  person 0___________    schedule 08.08.2017


Ответы (2)


Очень простой ответ. Когда main возвращается в большинстве наборов инструментов AVR, он вызывает инструкцию cli, отключая прерывания, а затем завершается бесконечным циклом. Это наиболее распространенная процедура эпилога в цепочках инструментов AVR для «голого железа».

Вот что происходит, когда вы выходите из main

00000078 <_exit>:
  78:   f8 94           cli

0000007a <__stop_program>:
  7a:   ff cf           rjmp    .-2         ; 0x7a <__stop_program>

Вы можете изменить его, изменив файл стартовой сборки (он также содержит эпилог).

person 0___________    schedule 07.08.2017

Без цикла занятости программа немедленно вернет 0 и завершится. Пока он находится в цикле, ничего не делая, он может быть прерван процедурой обслуживания прерывания.

person JGroven    schedule 07.08.2017
comment
Почему цикл while не нужен, когда я создал ШИМ? Это функционально отличается от подпрограммы обслуживания прерываний? Я предполагаю, что прерывание означает, что оно должно прервать процесс, а без цикла while прерывать нечего? - person ahat; 07.08.2017
comment
PWM обрабатывается аппаратными таймерами. Это вообще не управляется кодом. - person Delta_G; 07.08.2017
comment
Инструментальные цепочки @JGroven AVR не заботятся о возвращаемом значении. В УК что-то вроде end не существует. Проведите некоторые исследования, прежде чем отвечать на вопросы - person 0___________; 08.08.2017
comment
@ahat, если только это не программный ШИМ и не нужны прерывания, вам не нужен цикл в основном, поскольку подпрограммы эпилога ничего не меняют, кроме прерываний. Но на самом деле это выглядит ужасно, и у вас нет никакого контроля - если запуск изменится, и вы перекомпилируете свой код - он может не работать, если они что-то изменят. Этот мертвый цикл — всего лишь одна инструкция машинного кода. - person 0___________; 08.08.2017