Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: LPC1114.
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
_Артём_
Вечер добрый.
Вопрос следующий:
Скачал с сайта Yagarto (пример для lpc1114).
Сделал в файле main.c нём такое изменение:
Код
#include <stdint.h>
#include "LPC11xx.h"
#include "core_cm0.h"

void DelayTick(uint32_t delay)
{
    while (delay) {
        while ((SysTick->CTRL&(1<<SysTick_CTRL_COUNTFLAG_Pos))==0);
        SysTick->CTRL = 0
            | (1 << SysTick_CTRL_ENABLE_Pos)    // Enable timer
            | (0 << SysTick_CTRL_TICKINT_Pos)   // Disable SysTick interrupts
            | (0 << SysTick_CTRL_CLKSOURCE_Pos); // System clock/2
        delay--;
    }
}

int main (void)
{
    LPC_GPIO0->DIR=1<<7;

    // setup SysTick timer
    SysTick->LOAD = 48000000 / 100-1;
    SysTick->VAL = 0;   // reset counter
    SysTick->CTRL = 0
        | (1 << SysTick_CTRL_ENABLE_Pos)    // Enable timer
        | (0 << SysTick_CTRL_TICKINT_Pos)   // Disable SysTick interrupts
        | (0 << SysTick_CTRL_CLKSOURCE_Pos) // System clock/2
;
    
    while (1) {
        LPC_GPIO0->DATA&=~(1<<7);
        DelayTick(100);
        LPC_GPIO0->DATA|=(1<<7);
        DelayTick(5);

    }
}


То есть всё выкинул и вставил моргание светодиодом с частотой ~1Гц. Запустил на отладку - увидел то что ожидал.
Дальше заменил в makefile строку
Код
RUN_FROM_FLASH = 1


Код
RUN_FROM_FLASH = 0


Ожидал увидеть, что программа начнёт исполнятся из ОЗУ - нет, не увидел: контроллер перешёл в какое-то неизвестное мне состояние и отлаживаться отказался(выдал сообщение: No source available for "").
Дальше, запрограммировал test_ram.elf - морганий не увидел.
Программатор/отладчик - LPCXpresso.

Как правильно запускать программу в ОЗУ? Можно ли отлаживать программу расположенную в ОЗУ?
Видимо, я хочу получить от этого примера то, для чего он совсем не предназначен. Для чего он тогда?

Спасибо.

Сергей Борщ
QUOTE (_Артём_ @ Mar 19 2012, 20:48) *
Дальше заменил в makefile строку
CODE
RUN_FROM_FLASH = 1


CODE
RUN_FROM_FLASH = 0

1) В скрипте линкера отсутствует строка
CODE
ENTRY(Reset_Handler)
В вашем архиве то же самое делает команда monitor reg pc = (0x10000004), но ENTRY - более прямой путь.
2) В crt.c идет обращение к Vector Offset Register, которого в Cortex-M0 не существует (там ремап через регистр SYSMEMREMAP как в "обычных" ARM).
3) При старте дебаггера надо прописать в указатель стека значение из таблицы векторов. Либо в командах дебаггера, либо в начале Reset_Handler. В вашем архиве это делает команда monitor reg r13 = (0x10000000). Разберитесь, куда ее надо вписать в LPCXpresso.
QUOTE (_Артём_ @ Mar 19 2012, 20:48) *
Ожидал увидеть, что программа начнёт исполнятся из ОЗУ - нет, не увидел: контроллер перешёл в какое-то неизвестное мне состояние и отлаживаться отказался(выдал сообщение: No source available for "").
Посмотрите содержимое PC. Вероятно он улетел в адреса, для которых у вас действительно нет исходного кода. Можно воспользоваться окном дизассемблера чтобы посмотреть содержимое памяти.
QUOTE (_Артём_ @ Mar 19 2012, 20:48) *
Как правильно запускать программу в ОЗУ? Можно ли отлаживать программу расположенную в ОЗУ?
Да, можно. Вам нужно заставить отладчик перед стартом выполнить то, что при старте из флеша делает ядро - инициализировать указатель стека из таблицы векторов и занести в PC адрес начала программы (опять же либо из таблицы векторов либо директивой ENTRY() скрипта линкера).
QUOTE (_Артём_ @ Mar 19 2012, 20:48) *
Видимо, я хочу получить от этого примера то, для чего он совсем не предназначен. Для чего он тогда?
Это надо в его описании читать. Я предпочитаю читать документацию и писать подобный пример сам. Да, требует времени, но приходит детальное понимание процесса.
_Артём_
Спасибо, что-то начало запускаться (пока не понял что).

Цитата(Сергей Борщ @ Mar 20 2012, 09:51) *
1) В скрипте линкера отсутствует строка
Код
ENTRY(Reset_Handler)
В вашем архиве то же самое делает команда monitor reg pc = (0x10000004), но ENTRY - более прямой путь.


Пока добавил в lpc1114_ram.ld
Код
ENTRY(ResetHandler)

Запустилось. Не знаю откуда - разбираюсь.

Цитата(Сергей Борщ @ Mar 20 2012, 09:51) *
то же самое делает команда monitor reg pc = (0x10000004)

Это видимо относится к jlink-e которого у меня нет.

Цитата(Сергей Борщ @ Mar 20 2012, 09:51) *
2) В crt.c идет обращение к Vector Offset Register, которого в Cortex-M0 не существует

А это тогда кто:
Код
*((uint32_t*)0xE000ED08) = (uint32_t)&_stext


Нажмите для просмотра прикрепленного файла
?

Цитата(Сергей Борщ @ Mar 20 2012, 09:51) *
Посмотрите содержимое PC. Вероятно он улетел в адреса, для которых у вас действительно нет исходного кода. Можно воспользоваться окном дизассемблера чтобы посмотреть содержимое памяти.
Это надо в его описании читать. Я предпочитаю читать документацию и писать подобный пример сам. Да, требует времени, но приходит детальное понимание процесса.

Посмотрю. Спасибо.
Цитата(Сергей Борщ @ Mar 20 2012, 09:51) *
Это надо в его описании читать. Я предпочитаю читать документацию и писать подобный пример сам. Да, требует времени, но приходит детальное понимание процесса.

Самый надёжный метод. Не поспоришь.
Сергей Борщ
QUOTE (_Артём_ @ Mar 20 2012, 13:38) *
Это видимо относится к jlink-e которого у меня нет.
Это относится к любому gdb серверу. monitor - обращение к серверу, смысл "reg pc = (0x10000004)" думаю понятен.
QUOTE (_Артём_ @ Mar 20 2012, 13:38) *
А это тогда кто:
А в документации он где? SYSMEMREMAP в документации есть и работает как описано (проверено). VECT_OFFSET есть в документации Cortex-M3, в документации M0 такого регистра нет.
_Артём_
Попробывал использовать в проекте функции расположенные и в RAM и во flash:
Код
__attribute__ ((__section__(".data.WaitTimer0_16BInterrupt")))
void WaitTimer0_16BInterrupt()
{
    unsigned long counter_value=Timer0_16BCounter;

    while (counter_value==Timer0_16BCounter);
}


Судя по содержимому pc выполняется из ОЗУ.

Но выдаётся warning:
Цитата
Warning: setting incorrect section attributes for .data.WaitTimer0_16BInterrupt


Или есть какие-то другие способы, более прямые?
Сергей Борщ
QUOTE (_Артём_ @ Mar 22 2012, 00:15) *
Или есть какие-то другие способы, более прямые?
Секции .data не имеют атрибута x (executable). Надо завести свою секцию и разместить ее в выходную секцию .data:
CODE
    .data :
    {
        . = ALIGN(4);
        _sdata = .;                /* start of .data label */
        *(.ramfunc*)
        *(.data*)
        . = ALIGN(4);
        _edata = .;                /* end of .data label */
    } > RAM AT > TEXT
    _sidata = LOADADDR(.data);    /* start of initialized data label */
_Артём_
Цитата(Сергей Борщ @ Mar 22 2012, 08:39) *
Секции .data не имеют атрибута x (executable). Надо завести свою секцию и разместить ее в выходную секцию .data:

Попробовал: warning пропал. Способ - более прямой.
Спасибо.


Цитата(Сергей Борщ @ Mar 20 2012, 18:54) *
А в документации он где? SYSMEMREMAP в документации есть и работает как описано (проверено). VECT_OFFSET есть в документации Cortex-M3, в документации M0 такого регистра нет.


Да, похоже так - регистра VECT_OFFSET в M0 нет.
Значит в примере от Yagarto и LPCXpresso ошибка.

AHTOXA
Цитата(Сергей Борщ @ Mar 22 2012, 12:39) *
Код
    *(.data*)

Сергей, может, всё же вот так:
Код
        *(.data)
        *(.data.*)

? Иначе в секцию .data попадут секции с именами .datablablabla, а это может быть неправильно.
Сергей Борщ
QUOTE (AHTOXA @ Mar 23 2012, 05:37) *
? Иначе в секцию .data попадут секции с именами .datablablabla, а это может быть неправильно.
Хм. О таком варианте не задумывался. И все удивлялся - зачем люди везде пишут по две строки? Спасибо, буду лечить свои скрипты.
_Артём_
Цитата(AHTOXA @ Mar 23 2012, 05:37) *
Сергей, может, всё же вот так:
Код
        *(.data)
        *(.data.*)

? Иначе в секцию .data попадут секции с именами .datablablabla, а это может быть неправильно.


То есть в результате пишется так:
Код
.data :
    {
        . = ALIGN(4);
        _sdata = .;                /* start of .data label */
        *(.ramfunc)
        *(.ramfunc.*)
        *(.data)
        *(.data.*)
        . = ALIGN(4);
        _edata = .;                /* end of .data label */
    } > RAM AT > TEXT
    _sidata = LOADADDR(.data);    /* start of initialized data label */
.

Спасибо, AHTOXA.
AHTOXA
Кстати, заметил интересный глюк {arm-none-eabi,arm-kgp-eabi-}size. Как только я добавляю таким макаром хоть одну RAM-функцию, size начинает рапортовать, что размер data = 0.
_Артём_
Цитата(AHTOXA @ Mar 23 2012, 20:03) *
Кстати, заметил интересный глюк {arm-none-eabi,arm-kgp-eabi-}size. Как только я добавляю таким макаром хоть одну RAM-функцию, size начинает рапортовать, что размер data = 0.


Кстати да:
Цитата
text data bss dec hex filename
17028 0 5228 22256 56f0 ./exe/lcp11_test_proj.elf
Errors: none


Непорядок, однако.
А если в скрипте пишешь так
Цитата
*(.ramfunc)
*(.data)


То
Цитата
text data bss dec hex filename
17012 12 5228 22252 56ec ./exe/lcp11_test_proj.elf
Errors: none
AHTOXA
Цитата(_Артём_ @ Mar 24 2012, 00:11) *
А если в скрипте пишешь так
Код
*(.ramfunc)
*(.data)

Ну, так совсем неправильно, звёздочки в конце таки нужны. (При -ffunction-sections -fdata-sections секции называются .data.имя_переменной и .ramfunc.что-то_там).
Ещё поэкспериментировал. С ключом -A size выдаёт совсем другие цифры! Вот например:
arm-none-eabi-size STM32VLD.elf :
Код
   text       data        bss        dec        hex    filename
  11732          0       3972      15704       3d58    STM32VLD.elf

arm-none-eabi-size -A STM32VLD.elf
Код
STM32VLD.elf  :
section             size        addr
.isr_vector          464   134217728
.text              11180   134218192
.text.align            4   134229372
.data                 84   536870912
.bss                3716   536870996
._usrstack           256   536874712
.comment              83           0

Эти цифры больше похожи на правду.
_Артём_
Цитата(AHTOXA @ Mar 23 2012, 20:49) *
Ну, так совсем неправильно, звёздочки в конце таки нужны.

Не спорю - неправильно: не то скопировал.

Цитата(AHTOXA @ Mar 23 2012, 20:49) *
Ещё поэкспериментировал. С ключом -A size выдаёт совсем другие цифры!


Куда ключ-то вставлять? Он от какого замка?
AHTOXA
Цитата(_Артём_ @ Mar 24 2012, 01:03) *
Куда ключ-то вставлять? Он от какого замка?

Дык, я же написал командную строку перед цитатой. А еcли в makefile, то вот сюда:
Код
$(OK): $(ELF)
    @$(SIZE) -A $(ELF)
Сергей Борщ
QUOTE (AHTOXA @ Mar 23 2012, 20:03) *
Как только я добавляю таким макаром хоть одну RAM-функцию, size начинает рапортовать, что размер data = 0.
Может быть потому, что мы поступаем с ним не совсем честно?
Вот так показывает правильно:
CODE
    .ramfunc :
    {
        . = ALIGN(4);
        _sdata = .;                /* start of .data label */
        *(.ramfunc)
        *(.ramfunc.*)
    } > RAM AT > TEXT
    _sidata = LOADADDR(.ramfunc);    /* start of initialized data label */
    .data :
    {
        . = ALIGN(4);
        *(.data)
        *(.data.*)
        . = ALIGN(4);
        _edata = .;                /* end of .data label */
    } > RAM AT > TEXT

Мучает другой вопрос - линкер зачем-то добавляет промежуточную функцию, и как его заставить не делать этого я пока не нашел:
CODE
int main()
{
    260c:    b508          push    {r3, lr}
    test();
    260e:    f001 fe73     bl    42f8 <___Z4testv_veneer>
==================================
000042f8 <___Z4testv_veneer>:
    42f8:    b401          push    {r0}
    42fa:    4802          ldr    r0, [pc, #8]; (4304 <___Z4testv_veneer+0xc>)
    42fc:    4684          mov    ip, r0
    42fe:    bc01          pop    {r0}
    4300:    4760          bx    ip
    4302:    bf00          nop
    4304:    100000c1     .word    0x100000c1
==================================
Disassembly of section .ramfunc:

100000c0 <test()>:
volatile int u;

NOINLINE __attribute__((section(".ramfunc.hhh")))
void test()
{
    u = 0;
100000c0:    4b01          ldr    r3, [pc, #4]; (100000c8 <test()+0x8>)
100000c2:    2200          movs    r2, #0
100000c4:    601a          str    r2, [r3, #0]
}
100000c6:    4770          bx    lr
100000c8:    100003a0     .word    0x100003a0
AHTOXA
Цитата(Сергей Борщ @ Mar 24 2012, 02:44) *
Вот так показывает правильно:

Да, теперь порядок, спасибо.
Цитата
Мучает другой вопрос - линкер зачем-то добавляет промежуточную функцию

Угу, я тоже заметил. Вот тут что-то есть про это. И ещё вот.
В первой ссылке пишут, что это относится только к M0, но это не так, я компилирую для M3, и то же самое.
Причём в обе стороны, при вызове из RAM-функции FLASH-функции тоже генерируется переходная функция.
_Артём_
Ещё странность:
Код
// файл ram_functions.h
void WaitTimer0_16BInterrupt(unsigned char delay_cycles);

// файл
__attribute__ ((__section__(".ramfunc")))
void WaitTimer0_16BInterrupt(unsigned char delay_cycles)
{
    unsigned long counter_value=Timer0_16BCounter;
    counter_value+=(delay_cycles+1);

    while (counter_value!=Timer0_16BCounter)
;
}

// main.cpp

#include "ram_functions.h"
int main() {
    WaitTimer0_16BInterrupt(10);
    while (1) {
    }
}


Программа в функцию WaitTimer0_16BInterrupt попадает, дожидается окончания паузы ...и улетает куда-то нетуда.
После выхода из отладки запустить программу на отладку не удаётся.

Цитата
15: Target error from Commit Flash write: Et: Flash driver not ready.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.