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

Был у меня загрузчик для LPC2378 и прочих.

Теперь стала задача переписать его под LPC1766.

 

Все переписалось без особых проблем, однако камнем предкновения оказалось сделать вызов прикладной программы.

 

Прикладная программа заливается вместе с векторами начиная с адреса 0x1 0000 (16-я страница). Т.е. в ней находятся сначала вектора, а потом все остальное.

 

Код вызова программы:

 

#define FIRST_PAGE_ADDR 0x10000
#define NVIC_VectTab_FLASH           (0x00000000)

// код вызова приложения

volatile unsigned long    *p = (volatile unsigned long*)NVIC_VECT_TABLE;
*p = NVIC_VectTab_FLASH | (USER_FLASH_START & 0x1FFFFF80);

void (*App)() =  (void(*)())(FIRST_PAGE_ADDR + 1);
App();            // уходим в прикладную программу

 

Код вызова брал по аналогии из LPC1700 USB Bootloader.

 

Сделал прикладную программу, которая настраивает порт светодиода на плате и зажигает его.

Прикладная программа вызывается неправильно. В ассемблерном коде используется BLX на адрес, 10001, хотя должен был быть 10002. И яр отображает код совсем подругому.

В приложенных файлах 001 и 002 показаны скриншоты яра при работе загрузчика и уходе в прикладную программу. На 003 - прикладная программа в отладочном режиме без загрузчика.

 

Как правильно вызывать?

post-29246-1264692754_thumb.jpg

post-29246-1264692762_thumb.jpg

post-29246-1264692769_thumb.jpg

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


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

В ассемблерном коде используется BLX на адрес, 10001, хотя должен был быть 10002.

А почему, собственно, 0x10000 + 0x01 должно быть равно 0x10002?

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


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

А почему, собственно, 0x10000 + 0x01 должно быть равно 0x10002?

:cranky: наверное никак.

Сбил с толку указанный выше пример:

 

void execute_user_code(void)
{
    void (*user_code_entry)(void);
    
    /* Change the Vector Table to the USER_FLASH_START 
    in case the user application uses interrupts */
    NVIC_SetVectorTable(NVIC_VectTab_FLASH, USER_FLASH_START);

      user_code_entry = (void (*)(void))((USER_FLASH_START)+1);
    user_code_entry();

}

 

А что может находиться по адресу 0x10000 + 0x01? На сколько мне известно при 16 битных инструкциях прыгать нужно на адреса, выровненные под 16 битное пространство (т.е. в последнем бите должен быть 0).

LPC1700_USB_Bootloader.zip

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


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

А что может находиться по адресу 0x10000 + 0x01? На сколько мне известно при 16 битных инструкциях прыгать нужно на адреса, выровненные под 16 битное пространство (т.е. в последнем бите должен быть 0).

Младший бит адреса BLX выбирает режим работы процессора. В данном случае он должен быть равен "1", т.к. процессор может работать только в Thumb.

 

В приложенных файлах 001 и 002 показаны скриншоты яра при работе загрузчика и уходе в прикладную программу. На 003 - прикладная программа в отладочном режиме без загрузчика.

Судя по скриншотам, прикладная программа просто неправильно записана.

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


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

Младший бит адреса BLX выбирает режим работы процессора. В данном случае он должен быть равен "1", т.к. процессор может работать только в Thumb.

Теперь понятно.

Судя по скриншотам, прикладная программа просто неправильно записана.

Да, действительно. :smile3046:

Спасибо.

 

Рано обрадовался. Были неправильные скриншоты. После скринов будлодера я несколько изменил прошивку.

Теперь сделал все заново. Прошики совпадают.

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


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

Правильные скриншоты:

1 - дамп памяти в яре при отладке прикладной программы без загрузчика

2 - бинарь, который генерит яр при компиляции прикладной программы

3 - дамп памяти этой же прошивки, после загрузки ее загрузчиком

 

Проблема осталась таже.

post-29246-1264762790_thumb.jpg

post-29246-1264762877_thumb.jpg

post-29246-1264762995_thumb.jpg

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


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

Для STM32 применяю так:

Загрузчик находится 0х0800 0000

Программа

#define KERNEL_START_APP 0x08004000

 

__SYSJUMP(KERNEL_START_APP);

 

;*******************************************************************************

; Function Name : __SYSJUMP

; Description : Assembler function for the jump to App. from Boot

; Input : - r0 : Application Start Addres.

; Return : None

;*******************************************************************************

 

__SYSJUMP

 

MOVS R4,R0

CPSID i

LDR R0,[R4, #+0] ; set the stack pointer to app

MSR MSP, R0

LDR PC,[R4, #+4] ; load PC with reset vector from APP

 

END

 

Обратите внимание что у кортекса в начале вектора прерывания находится указатель на стек

а +4 начало программы

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


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

Для STM32 применяю так:

Загрузчик находится 0х0800 0000

Программа

#define KERNEL_START_APP 0x08004000

Обратите внимание что у кортекса в начале вектора прерывания находится указатель на стек

а +4 начало программы

 

Спасибо за код. Но для начала хочу понять весь механизм. Все знают что в иар по резету происходит переход в __iar_program_start .

Я в прикладной программе нашел адрес этой подпрограммы. И в загрузчике сделал вызов именно по этому адресу, забив адрес в регистр PC. Прошивка заработала!

Однако когда я забиваю в PC в прикладной программе начало таблицы векторов 0x10000 со смещением: 0x00000, 0x00002, 0x00004 и т.д. процессор улетает в хардваре еррор дефаулт хэндл. Т.е. ошибка состоит в том, что в вызове прикладной программы происходит переход "НЕ ТУДА".

 

Вот кусок яровского стартапа:

        EXTERN  __iar_program_start
        PUBLIC  __vector_table
        PUBLIC  __vector_table_0x1c

        DATA
__vector_table
        DCD     sfe(CSTACK)            ; Top of Stack
        DCD     __iar_program_start    ; Reset Handler
        DCD     NMI_Handler            ; NMI Handler
        DCD     HardFault_Handler         ; Hard Fault Handler
        DCD     MemManage_Handler         ; MPU Fault Handler
        DCD     BusFault_Handler          ; Bus Fault Handler
        DCD     UsageFault_Handler        ; Usage Fault Handler
__vector_table_0x1c
        DCD     0                         ; Reserved
        DCD     0                         ; Reserved
        DCD     0                         ; Reserved
        DCD     0                         ; Reserved
        DCD     SVC_Handler            ; SVCall Handler
        DCD     DebugMon_Handler          ; Debug Monitor Handler
        DCD     0                         ; Reserved
        DCD     PendSV_Handler            ; PendSV Handler
        DCD     SysTick_Handler        ; SysTick Handler
        DCD     WDT_IRQHandler            ; Watchdog Handler
        DCD     TMR0_IRQHandler        ; TIMER0 Handler
        DCD     TMR1_IRQHandler        ; TIMER1 Handler
        DCD     TMR2_IRQHandler        ; TIMER2 Handler
        DCD     TMR3_IRQHandler        ; TIMER3 Handler
        DCD     UART0_IRQHandler          ; UART0 Handler
        DCD     UART1_IRQHandler          ; UART1 Handler
        DCD     UART2_IRQHandler          ; UART2 Handler
        DCD     UART3_IRQHandler          ; UART3 Handler
        DCD     PWM1_IRQHandler        ; PWM1 Handler
        DCD     I2C0_IRQHandler        ; I2C0 Handler
        DCD     I2C1_IRQHandler        ; I2C1 Handler
        DCD     I2C2_IRQHandler        ; I2C2 Handler
        DCD     SPI_IRQHandler            ; SPI Handler
        DCD     SSP0_IRQHandler        ; SSP0 Handler
        DCD     SSP1_IRQHandler        ; SSP1 Handler
        DCD     PLL0_IRQHandler        ; PLL0 Handler
        DCD     RTC_IRQHandler            ; RTC Handler
        DCD     EINT0_IRQHandler          ; EXT Interupt 0 Handler
        DCD     EINT1_IRQHandler          ; EXT Interupt 1 Handler
        DCD     EINT2_IRQHandler          ; EXT Interupt 2 Handler
        DCD     EINT3_IRQHandler          ; EXT Interupt 3 Handler
        DCD     ADC_IRQHandler            ; ADC Handler
        DCD     BOD_IRQHandler            ; BOD Handler
        DCD     USB_IRQHandler            ; USB Handler
        DCD     CAN_IRQHandler            ; CAN Handler
        DCD     GPDMA_IRQHandler          ; General Purpose DMA Handler
        DCD     I2S_IRQHandler            ; I2S Handler
        DCD     Ethernet_IRQHandler    ; Ethernet Handler
        DCD     RIT_IRQHandler            ; Repetitive Interrupt Timer Handler
        DCD     MotorControlPWM_IRQHandler; Motor Control PWM Handler
        DCD     QE_IRQHandler             ; Quadrature Encoder Handler
        DCD     PLL1_IRQHandler        ; PLL1 Handler

 

Вопрос, на какой адрес прыгает процессор LPC1766 (и т.п.) после сброса?

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


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

Вопрос, на какой адрес прыгает процессор LPC1766 (и т.п.) после сброса?

По адресу, записанному в Reset Handler таблицы векторов:

        DCD     __iar_program_start; Reset Handler

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


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

Запись в даташите:

 

Following a hardware reset, the Boot ROM is temporarily mapped to address 0. This is

normally transparent to the user. However, if execution is halted immediately after reset by

a debugger, it should correct the mapping for the user. See Section 33–6.

 

В секции 33:

 

Following chip reset, a portion of the Boot ROM is mapped to address 0 so that it will be
automatically executed. The Boot ROM switches the map to point to Flash memory prior
to user code being executed. In this way a user normally does not need to know that this
re-mapping occurs.

However, when a debugger halts CPU execution immediately following reset, the Boot
ROM is still mapped to address 0 and can cause confusion. Ideally, the debugger should
correct the mapping automatically in this case, so that a user does not need to deal with it.

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


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

Понятно, по какому адресу?

Что по какому адресу? После сброса Reset Handler находится по адресу 0x04.

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


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

Что по какому адресу? После сброса Reset Handler находится по адресу 0x04.

Забиваю адрес 0x04 в PC при отладке, указатель начинает бежать по векторам подряд и через некоторое время вылетает в аппаратный хендел. Если забить в него адрес __iar_program_start, то программа начинает работать. Может так нельзя делать? Или проблема собственно что резет находится в этот момент не по 0х04 адресу?

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


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

PC загружается из 0x04, а не им.

 

Немного не понял что это значит. Поясните пожалуйста.

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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