2016-08-06 3 views
0

Я разрабатываю проект ARM без покрытия, используя LPC2138 soc. Я написал обработчик прерываний IRQ для I2C. Но он не возвращается должным образом. Обработчик вызывается повторно для одного прерывания.Обработчик IRM IRQ не работает должным образом в GCC

Я подробно проанализировал этот вопрос.

В справочном руководстве ARM7TDMI четко указано следующее.

enter image description here Но когда я разобрал код, я обнаружил, что код, созданный GCC, не восстанавливает Resgister CPSR. И наконец, неизвестное значение.

enter image description here

Я объявил обработчик прерываний, как следующий

void I2C0_IRQ_handler(void) __attribute__ ((interrupt("IRQ"))); 

Is s это ошибка в GCC или я сделал что-то не так?

флаги компилятора, ассемблера и компоновщика я использовал для создания проекта являются:

CFLAGS := -mcpu=arm7tdmi-s -g3 -Wall -I. -gdwarf-2 
AS_FLAGS := -mcpu=arm7tdmi-s -g3 -gdwarf-2 
LD_FLAGS := -Wl,-Map,$(TARGET:%.hex=%).map -nostartfiles 
+3

Каким образом он не работает должным образом; какое поведение вы видите по сравнению с тем, что вы ожидаете?Предполагая, что 'VICVectAddr = 0;' очищает прерывание, тогда этот код выполняет все 3 кавычки соответственно (подсказка: прочитайте, что на самом деле делает 'subs pc, ...') – Notlikethat

+0

@Notlikethat Когда I2C запускается условие прерывания должен быть сгенерирован. Работает. Но после процедуры прерывания элемент управления не возвращается к прерванному коду. В коде сборки отсутствует шаг 2. – sreeyesh

+0

Как я уже сказал, шаг 2 _is_ выполняется в этом коде под 'subs pc ...'. Уйдя и нашел руководство LPC213x, я вижу, что эта запись делает прерывание в VIC, но прерывание, по-видимому, вызвано уровнем, и вы ничего не делаете, чтобы отключить его на конце контроллера I2C (см. Раздел 13.9). Следовательно, когда вы возвращаетесь, вы сразу же снова принимаете то же прерывание, до бесконечности. – Notlikethat

ответ

4

Ваш анализ имеет две фатальные недостатки: во-первых, вы смотрите на него с точки зрения ядра процессора, во-вторых, это неправильно.

Второй недостаток, я не уверен, почему руководство ARM7TDMI имеет такую ​​странно чрезмерно конкретную формулировку (вы не можете реалистично делать все эти вещи в любом случае), но все 3 аспекта выполняются по линии subs pc, lr, #4 в вашем код. subs pc, lr is specifically an exception return instruction - он автоматически восстанавливает CPSR из SPSR и возвращается к фиксированному адресу LR. Поскольку флаги отключения прерываний CPU находятся в CPSR, тогда предполагается, что бит I в этом значении SPSR является ясным (что вы ожидаете, учитывая, что вы взяли IRQ, чтобы получить здесь ...), IRQ также будут автоматически отключены в процессе.

Таким образом, от точки ядра процессора зрения, ваш код уже (в силу своей окончательной инструкции) делает все, что нужно обработчик исключений для, т.е. он возобновляет выполнение в той же точке и в том же состоянии, когда произошел IRQ - в компиляторе нет ничего плохого. Однако то, что оно не делает, связано с тем, что периферийный путь за пределами ядра все еще утверждает его прерывание, поэтому следующая вещь, которую вы после возвращения из IRQ, должна с радостью снова принять тот же IRQ. Повторите бесконечность.

Вы, по крайней мере, вышли за пределы ядра до контроллера прерываний; записывая в VICVectAddracknowledges the interrupt at the VIC, но это просто освобождает VIC самостоятельно, чтобы приоритизировать любые ожидающие прерывания и доставить следующий, который, поскольку внешний источник все еще утверждается (и при условии, что IRQ с более высоким приоритетом не появился в другом месте), по-прежнему остается тот самый.

Фактически ручка прерывание и прогресс, вам необходимо обслуживать периферийное устройство I2C, поднимающее его. В разделе 13.9 из the LPC213x manual описано, что необходимо сделать для каждого условия прерывания, но с точки зрения устранения заявленного прерывания вам необходимо написать поле SIC для I2C0CONCLR.

+0

Это действительно помогло мне решить мою проблему и узнать новые вещи. Из вашего ответа я могу понять усилия, которые вы положили, и время, которое вы пощадили для ответа на мой вопрос. Большое спасибо за это :) И, конечно, мой голос. – sreeyesh

Смежные вопросы