Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Помогите пожалуйста написать "Hello World!" для SAM9260
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
mashler
Всем доброго дня!
Я сам в МК полный чайник, но в программировании вроде бы далеко не валенок (умею писать на С и Tasm). Уже мучаюсь 2 месяца, никак не могу написать простейшую программу которая будет загружаться с помощю Bootstrap из Dataflash CS0 и выводить сообщение на DBGU.
Может у когонибудь есть пример, или просто кто то подскажет что нужно делать.
Суть в том что первичный Bootstrap стартует и видит программу (8 векторов). Программа загружается по адресу 0х8000 из CS0.

А дальше ничего не происходит.

Код
>Start AT91Bootstrap...
Copy application ...
Run ...


Я так понимаю дело в C-Startup который я взял из Bootstrap 1.6 sources. Просто до меня никак не дойдет как вообще должнен быть огранизован запуск моей программы, должен ли я повторно сделать Remap и должен ли я инициализировать осцилятор если эти действия уже были сделаны в Bootstrap. И вообще что минимально я должен сделать чтобы она запустилась?

Вот мой код C-Startup и моя программа. Стыдно тут такое спрашивать, но очень прошу помогите кто чем сможет. crying.gif
CODE

.section start
.text

#include "include/part.h"

/*----------------------------------------------------------------------------
Area Definition
----------------
Must be defined as function to put first in the code as it must be mapped
at offset 0 of the flash EBI_CSR0, ie. at address 0 before remap.
_---------------------------------------------------------------------------*/

/* Application startup entry point */

.globl reset
.align 4
reset:

/* Exception vectors (should be a branch to be detected as a valid code by the rom */
_exception_vectors:
b reset_vector /* reset */
b undef_vector /* Undefined Instruction */
b swi_vector /* Software Interrupt */
b pabt_vector /* Prefetch Abort */
b dabt_vector /* Data Abort */
b rsvd_vector /* reserved */
b irq_vector /* IRQ : read the AIC */
b fiq_vector /* FIQ */

undef_vector:
b undef_vector
swi_vector:
b swi_vector
pabt_vector:
b pabt_vector
dabt_vector:
b dabt_vector
rsvd_vector:
b rsvd_vector
irq_vector:
b irq_vector
fiq_vector:
b fiq_vector
reset_vector:

/* Init the stack */
_init_stack:
ldr sp,=TOP_OF_MEM

/* Test if main oscillator is enabled */
ldr r0,=AT91C_PMC_SR
ldr r1, [r0]
ldr r2,=AT91C_PMC_MOSCS
ands r1, r1, r2
bne _switch_to_mosc


/* Enable the main oscillator */
_enable_mosc:
ldr r0,=AT91C_PMC_MOR
mov r1, #(0x40 << 8)
ldr r2,=AT91C_CKGR_MOSCEN
orr r1, r1, r2
str r1, [r0]
ldr r0,=AT91C_PMC_SR
1:
ldr r1, [r0]
ldr r2,=AT91C_PMC_MOSCS
ands r1, r1, r2
beq 1b

/* Test if MCK == SLOW CLOCK */
_switch_to_mosc:
ldr r0,=AT91C_PMC_MCKR
ldr r1,=AT91C_PMC_CSS
ldr r2, [r0]
and r2, r2, r1
mov r1, #0
cmp r1, r2
/* No => Do nothing */
bne _init_bss
/* Yes => Switch to the main oscillator */
ldr r1,=AT91C_PMC_CSS_MAIN_CLK
ldr r2,=AT91C_PMC_PRES_CLK
orr r1, r1, r2
str r1, [r0]
ldr r0,=AT91C_PMC_SR
1:
ldr r1, [r0]
ldr r2,=AT91C_PMC_MCKRDY
ands r1, r1, r2
beq 1b

/* Copy the data section in RAM at .data link address */
_init_data:
ldr r2, =_lp_data
ldmia r2, {r1, r3, r4}
1:
cmp r3, r4
ldrcc r2, [r1], #4
strcc r2, [r3], #4
bcc 1b

/* Initialize the bss segment */
_init_bss:
adr r2, _lp_bss
ldmia r2, {r3, r4}
mov r2, #0
1:
cmp r3, r4
strcc r2, [r3], #4
bcc 1b

/* Branch on C code Main function (with interworking) */
_branch_main:
ldr r4, = main
mov lr, pc
bx r4

/* Branch to the application at the end of the bootstrap init */
//_go:
// ldr r1, =MACH_TYPE
// mov lr, pc
// bx r0

.align
_lp_data:
.word _etext
.word _sdata
.word _edata

_lp_bss:
.word _sbss
.word _ebss


Код
#include "include/part.h"
#include "include/main.h"
#include "include/debug.h"

int main () {
    hw_init();

    dbg_print("Hello World!...\n\r");
    return 0;
}
aaarrr
Цитата(mashler @ Jun 19 2009, 14:32) *
Я так понимаю дело в C-Startup который я взял из Bootstrap 1.6 sources. Просто до меня никак не дойдет как вообще должнен быть огранизован запуск моей программы, должен ли я повторно сделать Remap и должен ли я инициализировать осцилятор если эти действия уже были сделаны в Bootstrap. И вообще что минимально я должен сделать чтобы она запустилась?

Почитайте раздел 13 AT91SAM9260 Boot Program даташита. Загрузчик сам делает remap и копирует данные из dataflash по адресу 0, туда же и передает управление. При этом резервный вектор (адрес 0x14) должен содержать длину загружаемого блока.
Откуда взялся адрес 0x8000?
mashler
Спасибо большое что отозвались =)

Цитата(aaarrr @ Jun 19 2009, 15:14) *
Почитайте раздел 13 AT91SAM9260 Boot Program даташита. Загрузчик сам делает remap и копирует данные из dataflash по адресу 0, туда же и передает управление. При этом резервный вектор (адрес 0x14) должен содержать длину загружаемого блока.
Откуда взялся адрес 0x8000?


Да загрузчик делает remap. Так в том то и дело что я не понимаю нужно ли его еще раз делать или нет? А по поводу осцилятора?

Это модифицированный загрузчик от Starterkit (производителя платы)
Цитата
Код первичного загрузчика обычно поставляется производителем конкретного устройства. Например, плата Starterkit SAM9-S3E содержит в памяти DataFlash DD2 версию AT91Bootstrap 1.6, имеющую следующие отличия:

* Частота процессора устанавливается равной 200 МГц
* Системная частота MCLK равна 100 МГц
* PLLB настроена на 96 МГц
* Загружаемая программа извлекается из DataFlash DD2 с адреса 0x8000 размером 0x30000 (192 килобайта).
* Загружаемая программа помещается в ОЗУ по адресу 0x21D00000.
* Временная диаграмма внешней памяти SDRAM настроена под параметры используемых микросхем.
aaarrr
Пардон, не заметил, что тут еще Bootstrap используется.

Тогда получается, что Вам нужно просто скомпилировать программу для работы по адресу 0x21D00000. Выполнен или нет remap легко проверить - нужно записать что-нибудь по адресу 0, а затем считать и сравнить содержимое. Если совпадает, значит remap выполнен и можно копировать в эту область свои вектора прерываний.

Но может проще будет для начала стартовать без Bootstrap'а.
mashler
Цитата(aaarrr @ Jun 19 2009, 15:31) *
Пардон, не заметил, что тут еще Bootstrap используется.

Тогда получается, что Вам нужно просто скомпилировать программу для работы по адресу 0x21D00000. Выполнен или нет remap легко проверить - нужно записать что-нибудь по адресу 0, а затем считать и сравнить содержимое. Если совпадает, значит remap выполнен и можно копировать в эту область свои вектора прерываний.

Но может проще будет для начала стартовать без Bootstrap'а.


Да, есть тут у меня ошибка.
Вот что я моменял из Makefile:
Код
# Link Address and Top_of_Memory
#LINK_ADDR=0x200000
#TOP_OF_MEMORY=0x301000
LINK_ADDR=0x21D00000
TOP_OF_MEMORY=0x301000


Но программа все так же не стартует.

Я в правильную сторону смотрю?

А вот как копировать вектрора прерываний я не пойму, и вообще зачем надо это делать?

Без Bootstrap стартовать можно, и у меня в принципе получается, но суть в том что размер первой программы ограничивается размером 4KB... а это очень мало если хочешь начать изучение сего процессора, поэтому я и пытаюсь передать управление своей программе которая будет подключать всю перефирию и с которой можно начать изучение.
aaarrr
Цитата(mashler @ Jun 19 2009, 15:43) *
Я в правильную сторону смотрю?

LINK_ADDR больше TOP_OF_MEMORY получился.

Цитата(mashler @ Jun 19 2009, 15:43) *
А вот как копировать вектрора прерываний я не пойму, и вообще зачем надо это делать?

Ваш CStartup содержит в начале вектора прерываний, после загрузки они окажутся по адресу 0x21D00000, а должны быть по адресу 0, иначе работать не будут.
Но если прерывания пока не используются, не заморачивайтесь.

Да, и лучше сначала светодиодом поморгать вместо "hello, world!".

Цитата(mashler @ Jun 19 2009, 15:43) *
Без Bootstrap стартовать можно, и у меня в принципе получается, но суть в том что размер первой программы ограничивается размером 4KB... а это очень мало если хочешь начать изучение сего процессора

Ну, чтобы именно начать как раз достаточно.
mashler
А как можно расчитать TOP_OF_MEMORY? или его можно тупо поставить например TOP_OF_MEMORY=0x30100000 а потом уже разбираться?
aaarrr
Можно.
mashler
Всеравно ничего не получается, с настройками

Makefile
Код
# Link Address and Top_of_Memory
LINK_ADDR=0x21D00000
TOP_OF_MEMORY=0x30100000


такая же ерунда:
Код
>Start AT91Bootstrap...
Copy application ...
Run ...

только единственное что появилось это - перенос строки после Run ...

У меня такое ощущение что вообще у меня сам код не начинает стартовать.
Вообщем я тут накачал кучу литературы, попробую на выходных по изучать.
aaarrr
Пином, пином помигайте. Мало ли что у Вас еще с dbg_print или UART'ом не так. Или просто попробуйте плюнуть что-нибудь в US_THR.
mashler
Цитата(aaarrr @ Jun 19 2009, 17:21) *
Пином, пином помигайте. Мало ли что у Вас еще с dbg_print или UART'ом не так. Или просто попробуйте плюнуть что-нибудь в US_THR.


Я просто наверное не на столько профи =)) можно со мной попроще))) Я даже не знаю что такое US_THR =))
aaarrr
Цитата(mashler @ Jun 19 2009, 17:38) *
Я даже не знаю что такое US_THR =))

US_THR - Transmit Holding Register UART'а. Так как UART (в данном случае DBGU) уже настроен Bootstrap'ом, то можно выдать наружу символ простой процедурой:
Код
void dbgu_send_byte(char byte)
{
    while(!(AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_TXRDY));
    AT91C_BASE_DBGU->DBGU_THR = byte;
}

Сделайте для начала совсем простой main, типа:
Код
int main(void)
{
    dbgu_send_byte('A');
    dbgu_send_byte('B');
    dbgu_send_byte('C');
    dbgu_send_byte('\r');
    dbgu_send_byte('\n');
    ...
}

безо всяких init'ов.
DpInRock
Цитата
перенос строки после Run

Обычно это означает, что загрузчик распознал, что загружаемая программа стартовала. А распознает он это, если примет какой-нибудь символ по уарту. Обычно ентер. Либо грязь, похожую на энтер.

Лучше не хелло ворд, а зацикленный хело ворд.

---
Не исключено, что загрузчик может устанавливать все регистры по дефолту....
aaarrr
Цитата(DpInRock @ Jun 19 2009, 18:14) *
Обычно это означает, что загрузчик распознал, что загружаемая программа стартовала. А распознает он это, если примет какой-нибудь символ по уарту. Обычно ентер. Либо грязь, похожую на энтер.

Да это же терминал просто, что он распознает? Просто раньше процессор расклинивался насмерть еще до того, как успевал отправиться последний CR, переданный Bootstrap'ом.

Цитата(DpInRock @ Jun 19 2009, 18:14) *
Не исключено, что загрузчик может устанавливать все регистры по дефолту....

Этим никто себя не утруждает. Тем более что было написано в каком состоянии процессор выходит после бута - с настроенными клоками, памятью и т.д.
DpInRock
У меня самба грузит проц с автовыходом (скрипт такой, чтобы самбовский уарт не мешал моему). Так вот. Если после старта программы я на выход уарта ничего не выдаю - самба висит секунды 3 после реального старта программы. А еслли выдаю строку # чего-нибудь, то самба уходит мгновенно.
mashler
Вообщем с помощью ваших заклинаний всетки мне удалось вывести "Hello World!" на DBGU

aaarrr ты оказался прав, инициализация DBGU уже была поэтому я просто написал:

CODE
#include "include/part.h"
#include "include/main.h"
#include "include/debug.h"

int main () {

while (1) {
dbg_print("Hello World!\n\r");
}

return 0;
}[/code]

и соответственно получил вывод в цикле.

Только единственное я кое что не понял, у меня все заработало только после того как я убрал инициализацию стека и Text, Data сегментов из cstartup.s

Cstartup у меня сейчас выглядит следующим образом:
[code].section start
.text

#include "include/part.h"

/*----------------------------------------------------------------------------
Area Definition
----------------
Must be defined as function to put first in the code as it must be mapped
at offset 0 of the flash EBI_CSR0, ie. at address 0 before remap.
_---------------------------------------------------------------------------*/

/* Application startup entry point */

.globl reset
.align 4
reset:

/* Exception vectors (should be a branch to be detected as a valid code by the rom */
_exception_vectors:
b reset_vector /* reset */
b undef_vector /* Undefined Instruction */
b swi_vector /* Software Interrupt */
b pabt_vector /* Prefetch Abort */
b dabt_vector /* Data Abort */
b rsvd_vector /* reserved */
b irq_vector /* IRQ : read the AIC */
b fiq_vector /* FIQ */

undef_vector:
b undef_vector
swi_vector:
b swi_vector
pabt_vector:
b pabt_vector
dabt_vector:
b dabt_vector
rsvd_vector:
b rsvd_vector
irq_vector:
b irq_vector
fiq_vector:
b fiq_vector
reset_vector:

/* Branch on C code Main function (with interworking) */
_branch_main:
ldr r0, = main
mov lr, pc
bx r0

/* Branch to the application at the end of the bootstrap init */
//_go:
// ldr r1, =MACH_TYPE
// mov lr, pc
// bx r0

.align
_lp_data:
.word _etext
.word _sdata
.word _edata

_lp_bss:
.word _sbss
.word _ebss


Почему мне не понадобилась инициализация сегментов и стека? Неужели мне ее не нужно выполнять?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.