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

 
 
> Правильное запрещение прерываний в LPC176x, перенос кода с LPC2xxx и критические секции
Altemir
сообщение Aug 31 2011, 19:13
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 249
Регистрация: 2-05-06
Из: Россия, Поволжье
Пользователь №: 16 686



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

Переношу код с LPC2214 и LPC2132 на LPC176x, потихоньку разбираюсь с мощным блоком NVIC и всякой вкусной системной обвязкой в кортексе. В старых проектах есть ряд участков кода в основной программе (критические секции), где запрещались прерывания, для того, чтобы не произошло изменение блока нужных регистров или есть жёсткая привязка по таймингам. Выглядело это примерно так для LPC2xxx:
CODE
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). Или я что-то недопонял?
Go to the top of the page
 
+Quote Post



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

 


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


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