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

 
 
> LPC1768 uart bootloader, не получается
Cosmojam
сообщение Dec 8 2011, 21:00
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182



Всем привет!
Помогите победить проблему.
Пробую сделать загрузчик по юарту. Позже планируется usb, но пока с этим ничего не получается.
За основу взят usb bootloader от NXP AN10866 http://www.nxp.com/documents/other/LPC1700..._bootloader.zip
В аттаче архив с 2 проектами для LPCXpresso. UART_bootloader - собственно бутлодырь, точнее только его скелет с самым самым минимумом. test - светодиодная моргалка, которую надо загружать для теста.
Проблема такова:
Загрузчик работает верно, бинарный файл с прошивкой тестового проекта сохраняет как нужно (файл не выравнен по 512байт, то чего не хватает для записи последнего блока дописываю ручками, временно так). Проверки при записи проходят т.е. неверно залитый файл исключается.
При старте он проверяет контрольную сумму прошивки в секторе 4 (туда по умолчанию загружаем). Сумма есть в бинарнике.
Сумма сошлась, надо переходить к исполнению программы с 4 сектора.
Указываем новое местоположение таблицы векторов прерываний, смещаем программный счётчик и верхушку стека (всё как в NXP-шном примере, только там для Keil, а у меня gcc с другим синтаксисом ассемблера):
Код
void boot(uint32_t a)
{
    asm(
    "LDR SP, [R0]\n"
    "LDR PC, [R0, #4]\n"
    );
}

void execute_user_code(void)
{
    uint32_t addr=(uint32_t)sector_start_adress[USERCODE_SECTOR_START];
    SCB->VTOR = (addr & 0x1FFFFF80);
    boot(addr);
}

Успешно попадаем в ResetISR загруженной программы (смотрю пошагово в отладчике и сверяю адреса инструкций с адресами в .map файле)
Дальше самое интересное:
Тестовая программа:
Код
volatile uint32_t del;
void _delay(uint32_t delay)
{
    uint32_t i;
    for(i = 0; i < delay; i++ )
        del = i; // do this so that the compiler does not optimize away the loop.
}


int main(void)
{
//    SystemInit();

//    init_uart(57600);

    LPC_SC->PCONP |= ( 1 << 15 ); // power up GPIO
    LPC_GPIO0->FIODIR |= 1 << 1;
    LPC_GPIO0->FIOPIN = 1<<1;

//    uart_sendstring("YES\n");

    uint32_t i;
    const uint32_t delay=1<<22;
    while(1)
    {
    //    _delay(1<<22);
        for(i = 0; i < delay; i++ )
            del = i;
        LPC_GPIO0->FIOPIN ^= 1 << 1;
    }
    return 0;
}

В таком виде работает, светодиод на P1.1 моргает. Но стоит раскомментировать задержку в вечном цикле и закомментировать "инлайновую" задержку (так она в теле цикла, а станет функцией) - всё, получаем HardFault Precise Error (скачок на адрес 0x40F6 где лежит обработчик HardFault-ов). Тоже самое и с юартом и системинитом. Можно предположить косяк со стеком при вызове функции, но фактически стек работает верно. Например, если убрать системинит, но оставить юарт, то хардфолтов не будет, он исправно пробежит uart_sendstring("YES\n"); но ничего не отправит. Та же программа зашитая в 0 сектор как обычно (с соответсвующей правкой скрипта линкера) работает абсолютно верно.
Оно мне уже мозг вынесло. Подскажите плз, что я делаю не так?

Прикрепленные файлы
Прикрепленный файл  uart_boot.zip ( 183.5 килобайт ) Кол-во скачиваний: 26
 


--------------------
typedef enum { no, yes, maybe } bool; | блог тут
Go to the top of the page
 
+Quote Post
2 страниц V  < 1 2  
Start new topic
Ответов (15 - 21)
Cosmojam
сообщение Dec 11 2011, 12:17
Сообщение #16


Местный
***

Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182



Цитата(toweroff @ Dec 11 2011, 02:27) *
а Вы читаете, что я пишу? в NON-Zero-Init сегменте

Сорри, не понял, сразу. В скрипте линкера оно так выглядит:
Код
    .uninit_RESERVED : ALIGN(4)
    {
        KEEP(*(.bss.$RESERVED*))
    } > RamLoc32

верно?

Кстати с вотчдогом получилось. Спасибо за подсказку
Код
if(LPC_SC->RSID & (1 << 2))
{
    LPC_SC->RSID ^= 1 << 2;
    /* WDT reset */
}


--------------------
typedef enum { no, yes, maybe } bool; | блог тут
Go to the top of the page
 
+Quote Post
toweroff
сообщение Dec 11 2011, 13:07
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Цитата(Cosmojam @ Dec 11 2011, 16:17) *
В скрипте линкера оно так выглядит:
Код
    .uninit_RESERVED : ALIGN(4)
    {
        KEEP(*(.bss.$RESERVED*))
    } > RamLoc32

верно?

тут не подскажу, т.к. пишу в кейле... там все области описывает скаттер-файл
Go to the top of the page
 
+Quote Post
Dron_Gus
сообщение Dec 12 2011, 20:22
Сообщение #18


Профессионал
*****

Группа: Свой
Сообщений: 1 202
Регистрация: 9-01-05
Из: Санкт-Петербург
Пользователь №: 1 861



Цитата(Cosmojam @ Dec 10 2011, 20:54) *
Да, только бутлодырь должен уметь отличать вызвали его программно, или по POR.

При программном вызове вы попадете не на ресет-вектор. Ни это ли признак?


--------------------
Если сверху смотреть, то сбоку кажется, что снизу ничего не видно.
Go to the top of the page
 
+Quote Post
Cosmojam
сообщение Dec 13 2011, 09:17
Сообщение #19


Местный
***

Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182



Цитата(Dron_Gus @ Dec 12 2011, 23:22) *
При программном вызове вы попадете не на ресет-вектор. Ни это ли признак?

Почему не на ресет вектор? Как раз на него. По идее наверное можно вызвать сразу main() в бутлодыре через указатель на функцию, но я не очень уверен в таком решении. На досуге можно будет поэксперементировать.


--------------------
typedef enum { no, yes, maybe } bool; | блог тут
Go to the top of the page
 
+Quote Post
Dron_Gus
сообщение Dec 13 2011, 10:38
Сообщение #20


Профессионал
*****

Группа: Свой
Сообщений: 1 202
Регистрация: 9-01-05
Из: Санкт-Петербург
Пользователь №: 1 861



Я Вам предлагаю вызвать SWI. Для него свой вектор.


--------------------
Если сверху смотреть, то сбоку кажется, что снизу ничего не видно.
Go to the top of the page
 
+Quote Post
Cosmojam
сообщение Dec 13 2011, 19:00
Сообщение #21


Местный
***

Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182



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


--------------------
typedef enum { no, yes, maybe } bool; | блог тут
Go to the top of the page
 
+Quote Post
Dron_Gus
сообщение Dec 14 2011, 10:28
Сообщение #22


Профессионал
*****

Группа: Свой
Сообщений: 1 202
Регистрация: 9-01-05
Из: Санкт-Петербург
Пользователь №: 1 861



При вызове SWI процессор переходит в привелигированный режим. К тому же таблица векторов известно где лежит. Зачем плодить сущности?


--------------------
Если сверху смотреть, то сбоку кажется, что снизу ничего не видно.
Go to the top of the page
 
+Quote Post

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

 


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


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