реклама на сайте
подробности

 
 
> Отключение выгрузки регистров в стек (CVAVR)
ProMetei
сообщение Dec 8 2016, 08:46
Сообщение #1





Группа: Новичок
Сообщений: 2
Регистрация: 11-05-16
Пользователь №: 91 679



Камень: atmega88pa
Компилятор: CVAVR

Главная часть проекта - 8-канальный аппаратно-программный генератор ШИМа на 6 прерываниях таймеров 0 и 2 (Fclk=2MHz, Fpwm=7,8kHz).
Расчёт значений для ШИМ производится в прерывании от ADC. Сразу после входа в обработчик разрешаются вложенные прерывания (чтоб не глох ШИМ), затем идёт задумчивый код с 32-битной арифметикой и лишь перед выходом из обработчика- запускается новый отсчёт АЦП.

Проблема в том, что компилятор абсолютно верно и предсказуемо сохраняет регистры при входе в обработчик, и лишь затем добирается до SEI, вот упрощенная выдержка из листинга:

CODE

_ADC_isr:

ST -Y,R0
ST -Y,R1
ST -Y,R22
ST -Y,R23
ST -Y,R24
ST -Y,R25
ST -Y,R26
ST -Y,R27
ST -Y,R30
ST -Y,R31
IN R30,SREG
ST -Y,R30

sei

; тут живёт медленный код

D R30,Y+
OUT SREG,R30
LD R31,Y+
LD R30,Y+
LD R27,Y+
LD R26,Y+
LD R25,Y+
LD R24,Y+
LD R23,Y+
LD R22,Y+
LD R1,Y+
LD R0,Y+
RETI

Эта пауза в 23/20 (вход/выход) дополнительных тактов даёт джиттер ШИМ до 3 единиц.
Джиттер не особо напрягает, но хотелось бы от него избавиться.

Переносить медленный код в основной цикл - не вариант, там крутится основная логика программы, абстрагированная от железа.
Разбавлять её опросом флага ADSC - кощунство.

Попробовал покататься на вот таком костыле- помогает, но не уверен что он правильный.

CODE

#pragma savereg-
interrupt [ADC_INT] void ADC_isr(void) // замер входов АЦП, плавный разгон
{
static unsigned int soft_rpm=0; // внутренняя переменная плавной скорости
static unsigned int addition; // компенсация ограничения

unsigned char temp; // вспомогательная переменная для ускорения расчётов
unsigned long L; // для точных расчётов

#asm
ST -Y,R0 ; выгрузили R0
IN R0,SREG ; в R0 положили SREG (с I-bit=0)

SEI ; разрешили прерывания

ST -Y,R0 ; выгрузили R0 ( реально - там SREG)
ST -Y,R1 ; выгрузили R1
ST -Y,R15 ; выгрузили R15
ST -Y,R22 ; выгрузили R22
ST -Y,R23 ; выгрузили R23
ST -Y,R24 ; выгрузили R24
ST -Y,R25 ; выгрузили R25
ST -Y,R26 ; выгрузили R26
ST -Y,R27 ; выгрузили R27
ST -Y,R30 ; выгрузили R30
ST -Y,R31 ; выгрузили R31
#endasm

{} // тут живёт медленный код

ADCSRA=(1<<ADEN) | (1<<ADSC) |(1<<ADIE) | (1<<ADIF) | 0x06; // перезапуск прерывания

#asm
LD R31,Y+ ; восстановили R31
LD R30,Y+ ; восстановили R30
LD R27,Y+ ; восстановили R27
LD R26,Y+ ; восстановили R26
LD R25,Y+ ; восстановили R25
LD R24,Y+ ; восстановили R24
LD R23,Y+ ; восстановили R23
LD R22,Y+ ; восстановили R22
LD R15,Y+ ; восстановили R15
LD R1,Y+ ; восстановили R1
LD R0,Y+ ; восстановили R0 ( реально - там SREG)

OUT SREG,R0 ; из R0 восстановить SREG (с I-bit=0, запретив прерывания)
LD R0,Y+ ; восстановили R0
#endasm

}
#pragma savereg+

Уважаемые знатоки, подскажите, пожалуйста- есть ли иной вариант, как заставить компилятор запускать вложенные прерывания пораньше?
И если нет - насколько правильно написан мой костыль?

Спасибо!

Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Zlumd
сообщение Dec 14 2016, 04:47
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 327
Регистрация: 12-04-05
Из: Новосибирск
Пользователь №: 4 057



Цитата(ProMetei @ Dec 8 2016, 15:46) *
Сразу после входа в обработчик разрешаются вложенные прерывания (чтоб не глох ШИМ)
Внутри прерывания ШИМ не глохнет.
ШИМ генерируется таймером аппаратно, независимо от того, чем занимается процессор. Или вы вручную ногами дергаете?
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd June 2025 - 20:35
Рейтинг@Mail.ru


Страница сгенерированна за 0.01385 секунд с 7
ELECTRONIX ©2004-2016