|
|
  |
IAP и LPC1768, Непонятные проблемы со стиранием |
|
|
|
Mar 16 2010, 16:18
|
Местный
  
Группа: Свой
Сообщений: 266
Регистрация: 8-12-05
Пользователь №: 11 964

|
Добрый день! Пытаюсь использовать для размещения констант флэш LPC1768 (ее там много, а ставить что-то снаружи не хочется), на базе примера EEPROM для LPC2368 слегка изменил код и подстроил его под свои нужды. На LPC2368 код работал без проблем. Сейчас возникают непонятные зависоны при стирании флэша (только при стирании, запись работает как часы). Вот мой код: Код #define IAP_LOCATION 0x1fff1ff1
#define EE1_SEC_L 14 //Flash sector where EEPROM begins (see UM for details) #define EE1_SEC_H 14 //Flash sector where EEPROM ends (see UM for details) #define EE1_ADDR_L 0x0000E000 //Must match the EE_SEC_L Flash sector start address #define EE1_ADDR_H 0x0000EFFF //Must match the EE_SEC_H Flash sector end address #define EE_CCLK 96000 //system clock cclk expressed in kHz (96MHz)
typedef void (*IAP)(unsigned int [],unsigned int[]); IAP iap_entry;
TDWord EEPROM_Erase(void) { unsigned int command_iap[5]; unsigned int result_iap[3];
__disable_irq();
command_iap[0]=50; //prepare sectors from EE_SEC_L to EE_SEC_H for erase command_iap[1]=EE1_SEC_L; command_iap[2]=EE1_SEC_H; iap_entry=(IAP) IAP_LOCATION; iap_entry(command_iap,result_iap);
command_iap[0]=52; //erase sectors from EE_SEC_L to EE_SEC_H command_iap[1]=EE1_SEC_L; command_iap[2]=EE1_SEC_H; command_iap[3]=EE_CCLK; iap_entry=(IAP) IAP_LOCATION; iap_entry(command_iap,result_iap);
command_iap[0]=53; //blankcheck sectors from EE_SEC_L to EE_SEC_H command_iap[1]=EE1_SEC_L; command_iap[2]=EE1_SEC_H; iap_entry=(IAP) IAP_LOCATION; iap_entry(command_iap,result_iap);
__enable_irq();
return result_iap[0]; } При прохождении отладчиком не виснет, если же просто загрузить приложение, то виснет секунд на 30, потом работает нормально. Запись во флэш производится, что удивительно. Никто с подобным не сталкивался?? Заранее спасибо!!!
|
|
|
|
|
Mar 18 2010, 14:45
|
Местный
  
Группа: Свой
Сообщений: 266
Регистрация: 8-12-05
Пользователь №: 11 964

|
Вроде бы обнаружил причину неправильной работы. Ранее я писал, что не работают прерывания. Они работают. За исключением одного - прерывания от RIT (Repetitive Interrupt Timer). Впечатление о неработающей остальной периферии сложилось из-за того, что я использую RIT в качестве системного таймера, где вызывается ряд других обработчиков. Да, я в курсе, что в Кортексах есть System Tick Timer, но мне нужна была частота повыше, чем 100 Гц (500 Гц конкретно). В общих чертах анамнез следующий: при вызывании функции IAP Erase Sector происходит блокировка прерываний RIT примерно на 30-40 секунд, что в условиях моего приложения имело катастрофические последствия (зависание системы на это время). В чем причина - не знаю, ничего в документах про подобное поведение не обнаружил. Других причин быть не может, урезал уже до самого минимального функционала программу - ничего не изменилось. Вся проблема именно в блокировке RIT. Очень смахивает на какой-то баг в ядре LPC17xx. С удовольствием послушал бы возможные версии причин
|
|
|
|
|
Mar 18 2010, 22:17
|
Местный
  
Группа: Свой
Сообщений: 266
Регистрация: 8-12-05
Пользователь №: 11 964

|
Цитата(sonycman @ Mar 18 2010, 18:32)  А разве SysTick нельзя настроить на любую другую, отличную от 100 Гц частоту? Можно, пропустил этот момент. Но RIT понятнее настраивается. Цитата(zltigo @ Mar 18 2010, 17:32)  В ядре? 30-40 секунд  . Например, у Вас что-то с обработчиком этого прерывания - при пропуске прерываний из-за длительного запрета что-то сходит с ума. Запретите, для начала, дополнительно RIT в железе. А что может сойти с ума? В урезанном варианте там остались только счетчики. Работоспособности это не помогло. К тому же отладчиком (только не надо снова про их вред  ) становился туда - ноль реакции, в остальных прерываниях все отлично. Да и в том давешнем баге IAP, который признали и в NXP, тоже речь шла о 30-60 секундах (в зависимости от тактовой частоты). Если переложить функцию RIT на обычный таймер - все работает как часы. Я уже отписал в техподдержку, посмотрим, что скажут.
|
|
|
|
|
Mar 19 2010, 07:34
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Polaris @ Mar 19 2010, 01:17)  А что может сойти с ума? Вам виднее, что Вы там написали  . Цитата К тому же отладчиком (только не надо снова про их вред  ) становился туда - ноль реакции не помог, значит  Цитата Если переложить функцию RIT на.... Уже писал - Вы бы для начала прерывание от него перед вызовом стирания заблокировали-бы.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Mar 19 2010, 08:01
|
Местный
  
Группа: Свой
Сообщений: 266
Регистрация: 8-12-05
Пользователь №: 11 964

|
Цитата(zltigo @ Mar 19 2010, 09:34)  Уже писал - Вы бы для начала прерывание от него перед вызовом стирания заблокировали-бы. Перед вызовом стирания я блокирую ВСЕ прерывания, ситуация абсолютно такая же, как при неблокировании. Очевидно, блокировка прерываний уже имеется внутри IAP (?). Но мне кажется, что я понял механизм, по крайней мере по 40 секундам все сходится. Я для RIT выставляю бит RITENCLR, по документации это не имеет никаких ограничений по включенности-невключенности прерывания. Судя по всему, при вызове IAP очистки счетчика не происходит, в итоге счетчик считает до переполнения 2^32/96МГц - это получается 44.7 секунды, далее работоспособность восстанавливается без всякого сброса. Остается только вопрос - связано ли это с внутренними процессами в IAP, или же RIT имеет особенность не очищать счетчик, если прерывания запрещены, но при этом продолжает счет - в таком случае это серьезный баг именно ядра, и использовать RIT в таком виде совершенно невозможно. Рано или поздно подобный баг вполне может всплыть даже при кратковременном запрещении прерываний.
|
|
|
|
|
Mar 19 2010, 08:08
|
Местный
  
Группа: Свой
Сообщений: 266
Регистрация: 8-12-05
Пользователь №: 11 964

|
Цитата(zltigo @ Mar 19 2010, 10:07)  Последний раз не "все" прерывания, а именно РАСПРОГРАММИРОВАТЬ конкретно RIT. Перед вызовом Flash erase отключить RIT, после вызова - включить?
|
|
|
|
|
Mar 19 2010, 08:15
|
Местный
  
Группа: Свой
Сообщений: 266
Регистрация: 8-12-05
Пользователь №: 11 964

|
Цитата(zltigo @ Mar 19 2010, 10:11)  Да. В таком виде работает: Код command_iap[0]=52; command_iap[1]=EE1_SEC_L; command_iap[2]=EE1_SEC_H; LPC_RIT->RICTRL &= ~(1<<RITEN); iap_entry(command_iap,result_iap); LPC_RIT->RICTRL |= (1<<RITEN);
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|