Перейти к содержанию
    

Правильное запрещение прерываний в LPC176x

Доброго времени суток.

 

Переношу код с LPC2214 и LPC2132 на LPC176x, потихоньку разбираюсь с мощным блоком NVIC и всякой вкусной системной обвязкой в кортексе. В старых проектах есть ряд участков кода в основной программе (критические секции), где запрещались прерывания, для того, чтобы не произошло изменение блока нужных регистров или есть жёсткая привязка по таймингам. Выглядело это примерно так для LPC2xxx:

void func()
{
   DWORD cpsr=INT_DISABLE(); //сохраняем текущее состояние, отключаем IRQ, FIQ 
   //критическая секция
   //...код...
   INT_RESTORE(cpsr); //восстанавливаем состояние
}

#define IRQ_FLAG        0x80
#define FIQ_FLAG        0x40

/*************************************************************************
* Function Name: INT_RESTORE
* Parameters: unsigned long IFlag
* Return: void
* Description: Restore F,I flag state
*
*************************************************************************/
void INT_RESTORE(unsigned long IFlag)
{
 unsigned long tmp;
 tmp=__get_CPSR();
 __set_CPSR(tmp & (IFlag | ~(IRQ_FLAG | FIQ_FLAG)));
}

/*************************************************************************
* Function Name: INT_DISABLE
* Parameters:
* Return: unsigned long
* Description: Disable interrupts and return previous state state of flgas I
*
*************************************************************************/
unsigned long INT_DISABLE(void)
{
 unsigned long tmp;
 tmp=__get_CPSR();
 __set_CPSR(tmp | IRQ_FLAG | FIQ_FLAG);
 return tmp;
}

 

Сейчас использую CMSIS. В результате курения мануалов и экспериментов выяснил, что простое отключение прерываний через __disable_irq() (или CPSID I) приводит к Hard fault при возникновении прерывания, и, разумеется, радостно выставлен бит FORCED. Как я понял, это сообщает об отсутствии обработки прерывания. Естественно, мне же надо было отключить все разом. Насколько удалось из мануалов понять, требуется применение __disable_fault_irq() (или CPSID F), тогда перехода на fault-handlers не будет.

Правильным ли будет следующий подход по аналогии со старым кодом для критических секций?

void new_func()
{
  DWORD prm, fm;
  prm = __get_PRIMASK();    //сохраняем состояние PRIMASK
  fm = __get_FAULTMASK();    //сохраняем состояние FAULTMASK
  __disable_fault_irq();
  //критическая секция
  //...код...
  __set_PRIMASK(prm);        //восстанавливаем состояния. Правильная ли очерёдность? Если наоборот, то не произойдёт ли переход на fault_handler?
  __set_FAULTMASK(fm);
}

 

Учитывая, что в PRIMASK и FAULTMASK используется только по одному биту, то можно обойтись одним временным регистром.

И ещё. Пока мне непонятно: при переходе на hard_fault_handler считываю состояние HFSR, вижу установленный бит FORCED, а в BFSR - BFARVALID и PRECISERR, что указывает на возможность чтения Bus Fault Address Register (BFAR). Так вот, значение, которое лежит в этом регистре, равно 0x100175ED. Откуда такой адрес? По идее, там должен находиться адрес, откуда произошёл bus fault, но на карте памяти таких адресов нет в моём процессоре (LPC1767). Или я что-то недопонял?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В IAR пользуюсь конструкцией

 

    unsigned long int_bak;
    int_bak = __get_interrupt_state();
    __disable_interrupt();
    .....
    __set_interrupt_state(int_bak);

 

все работает без проблем.

 

PS И забудте вы про CMSIS - легче станет. Проще написать свой драйвер NVIC, чем адаптировать творчество ARM. Сейчас у меня одни и те же модули легко работают как под ARM7 (LPC 21хх и LPC23xx), так и под C-M3 (LPC17xx)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

все работает без проблем.

Очень странно, т.к. данный интринсик:

For Cortex-M devices, it raises the execution priority level to 0 by setting the priority mask bit, PRIMASK

Т.е. на FAULTMASK не оказывает влияния, что в моём случае приведёт в fault_handler. Либо у вас изначально уже замаскирован регистр FAULTMASK.

 

PS И забудте вы про CMSIS - легче станет. Проще написать свой драйвер NVIC, чем адаптировать творчество ARM. Сейчас у меня одни и те же модули легко работают как под ARM7 (LPC 21хх и LPC23xx), так и под C-M3 (LPC17xx)

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

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А Вы не пробовали разобраться с причиной возникновения fault? :smile3009:

В моем случае оно как-то не возникает :laughing:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А Вы не пробовали разобраться с причиной возникновения fault?

Пробовал. Написал же выше причину. Что ещё может быть не так?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Очень странно, т.к. данный интринсик:

 

Если речь идет про ИАР, то Вы путаете __disable_irq(), которое действительно вызовет проблему на кортексе, и __disable_interrupt(), о котором упоминал Alechek. Последнее на кортексе работает нормально.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если речь идет про ИАР, то Вы путаете __disable_irq(), которое действительно вызовет проблему на кортексе, и __disable_interrupt(), о котором упоминал Alechek. Последнее на кортексе работает нормально.

Подозревал, но тогда как понимать в файле cmsis_iar.h этот дефайн:

#define __disable_irq   __disable_interrupt

Хм, не могу найти описание для __disable_interrupt. Может, Вы подскажете? В хэлпе IARа указано только то, что я привёл выше. Там ошибка?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Подозревал, но тогда как понимать в файле cmsis_iar.h этот дефайн:

#define __disable_irq   __disable_interrupt

Хм, не могу найти описание для __disable_interrupt. Может, Вы подскажете? В хэлпе IARа указано только то, что я привёл выше. Там ошибка?

 

Никакой ошибки нет. __disable_irq() не предназначена для Cortex-M3, о чем и я Вам выше написал. А как устроена CMSIS не знаю, не пользовался. Все таки правильно тут советовали, что начинать знакомство с новой архитектурой используя чью-то библиотеку неправильно, т.к. наступаете не только на собственные грабли, но еще и на чужие.

Я хелп редко читаю. А вот в файле <intrinsics.h> в комментах совершенно четко описано какие функции для чего можно/нужно использовать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Все таки правильно тут советовали, что начинать знакомство с новой архитектурой используя чью-то библиотеку неправильно, т.к. наступаете не только на собственные грабли, но еще и на чужие.

Зато сколько интересного можно откопать! :rolleyes: Во первых, есть неплохие примеры. Во вторых, длительный опыт ковыряния чужих некомментированных исходников позволяет адекватно воспринимать код и даже находить в нём ошибки (а в CMSIS-е их хватает). Я сначала пробегаюсь по используемым функциям, смотрю, что в них и как сделано, и что вообще стоит из этого использовать, и ТОЛЬКО ПОСЛЕ ЭТОГО подрубаю к своему проекту. Зато нескучно. И пусть в меня кинут тапком :smile3046:

 

З.Ы. а описания на асме __disable_interrupt я так и не раскопал :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

З.Ы. а описания на асме __disable_interrupt я так и не раскопал :(

у IAR это intrinsic, которая просто вставляет CPSID I

Exceptions у этой инструкции нет!

А может вы в непривилегированном режиме? тогда эта инструкция игнорируется.

В любом случае лучше посмотреть содержимое регистров под отладчиком после запрещения прерываний, ну fault отловить.

Для отладки достаточно такого обработчика:

void fault(void)
{
  __no_operation();
}

и брекпоинт поставить, потом в асме сделать пару шагов и вы вернетесь в то место где случился fault

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...