Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: IAP и LPC1768
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Polaris
Добрый день!

Пытаюсь использовать для размещения констант флэш 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, потом работает нормально. Запись во флэш производится, что удивительно. Никто с подобным не сталкивался??
Заранее спасибо!!!
Polaris
Нашел описание подобного поведения вот здесь:
http://www.embeddedrelated.com/groups/lpc2000/show/2763.php
Но применительно к старым версиям загрузчика на LPC2114. Пишут, что баг, связанный с работой PLL. Буду экспериментировать дальше. О результатах сообщу позднее smile.gif
Polaris
Обнаружил, что зависание - это на самом деле не зависание, а отсутствие реакции на прерывания, исполнение программы идет, но прерывания никакие не обрабатываются. Что очень странно. После примерно 30 секунд контроллер сбрасывается, и продолжается нормальная работа. Ничего не понятно sad.gif
Polaris
Вроде бы обнаружил причину неправильной работы. Ранее я писал, что не работают прерывания. Они работают. За исключением одного - прерывания от RIT (Repetitive Interrupt Timer). Впечатление о неработающей остальной периферии сложилось из-за того, что я использую RIT в качестве системного таймера, где вызывается ряд других обработчиков. Да, я в курсе, что в Кортексах есть System Tick Timer, но мне нужна была частота повыше, чем 100 Гц (500 Гц конкретно). В общих чертах анамнез следующий: при вызывании функции IAP Erase Sector происходит блокировка прерываний RIT примерно на 30-40 секунд, что в условиях моего приложения имело катастрофические последствия (зависание системы на это время). В чем причина - не знаю, ничего в документах про подобное поведение не обнаружил. Других причин быть не может, урезал уже до самого минимального функционала программу - ничего не изменилось. Вся проблема именно в блокировке RIT. Очень смахивает на какой-то баг в ядре LPC17xx. С удовольствием послушал бы возможные версии причин smile.gif
zltigo
Цитата(Polaris @ Mar 18 2010, 17:45) *
Очень смахивает на какой-то баг в ядре LPC17xx.

В ядре? 30-40 секунд smile.gif. Например, у Вас что-то с обработчиком этого прерывания - при пропуске прерываний из-за длительного запрета что-то сходит с ума. Запретите, для начала, дополнительно RIT в железе.
sonycman
Цитата(Polaris @ Mar 18 2010, 19:45) *
Да, я в курсе, что в Кортексах есть System Tick Timer, но мне нужна была частота повыше, чем 100 Гц (500 Гц конкретно).

А разве SysTick нельзя настроить на любую другую, отличную от 100 Гц частоту?
Polaris
Цитата(sonycman @ Mar 18 2010, 18:32) *
А разве SysTick нельзя настроить на любую другую, отличную от 100 Гц частоту?

Можно, пропустил этот момент. Но RIT понятнее настраивается.

Цитата(zltigo @ Mar 18 2010, 17:32) *
В ядре? 30-40 секунд smile.gif. Например, у Вас что-то с обработчиком этого прерывания - при пропуске прерываний из-за длительного запрета что-то сходит с ума. Запретите, для начала, дополнительно RIT в железе.

А что может сойти с ума? В урезанном варианте там остались только счетчики. Работоспособности это не помогло. К тому же отладчиком (только не надо снова про их вред smile.gif) становился туда - ноль реакции, в остальных прерываниях все отлично. Да и в том давешнем баге IAP, который признали и в NXP, тоже речь шла о 30-60 секундах (в зависимости от тактовой частоты). Если переложить функцию RIT на обычный таймер - все работает как часы. Я уже отписал в техподдержку, посмотрим, что скажут.
zltigo
Цитата(Polaris @ Mar 19 2010, 01:17) *
А что может сойти с ума?

Вам виднее, что Вы там написали sad.gif.
Цитата
К тому же отладчиком (только не надо снова про их вред smile.gif) становился туда - ноль реакции

не помог, значит smile.gif
Цитата
Если переложить функцию RIT на....

Уже писал - Вы бы для начала прерывание от него перед вызовом стирания заблокировали-бы.
Polaris
Цитата(zltigo @ Mar 19 2010, 09:34) *
Уже писал - Вы бы для начала прерывание от него перед вызовом стирания заблокировали-бы.

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

Последний раз не "все" прерывания в ядре а-ля disable(), а именно РАСПРОГРАММИРОВАТЬ конкретно железо RIT / контроллера прерываний. После чего думайте, как Вы запрограммировали RIT и как обрабатываете его прерывания.
Polaris
Цитата(zltigo @ Mar 19 2010, 10:07) *
Последний раз не "все" прерывания, а именно РАСПРОГРАММИРОВАТЬ конкретно RIT.

Перед вызовом Flash erase отключить RIT, после вызова - включить?
zltigo
Цитата(Polaris @ Mar 19 2010, 11:08) *
Перед вызовом Flash erase отключить RIT, после вызова - включить?

Да.
Polaris
Цитата(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);
Polaris
Так что, нет идей по поводу причин подобной работы? Ведь налицо системная ошибка.
P.S. Мне это уже интересно из чисто спортивных побуждений, от идеи использования флэши для хранения настроек отказался, вешать систему на сотни мс не очень хочется...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.