Отвечаем (иар подразумеваю, для других компилеров товарищи добавят описание)
1. Ставим процессор +обвязку+питание и по Жтагу заливаем минимальный код для проверки работоспособности ...
2. Ставим СДРАМ и минимальным кодом проверем работоспособность памяти.
Код
unsigned int volatile *pSDRAM;
unsigned int wCount;
unsigned int wRead,
wWrite;
printf ("CPU %d MHz\n",GetCPUFrequencyMhz() );
printf ("PCK %d MHz\n",GetPCKFrequencyMhz() );
while (1){
printf("-T WR- 0x00000000\n");
pSDRAM = (unsigned int *) BASE_EBI_CS1_ADDRESS;
for ( wCount = 0,wWrite=0x0;wCount < 0x800000;wCount ++ ){
*pSDRAM = wWrite;
wRead = *pSDRAM;
if (wWrite != wRead )
printf ("[0x%08X] = 0x%08X ( 0x%08X,0x%08X)\n",wCount,wRead^wWrite,wRead,wWrite );
pSDRAM++;
}
}
unsigned int wCount;
unsigned int wRead,
wWrite;
printf ("CPU %d MHz\n",GetCPUFrequencyMhz() );
printf ("PCK %d MHz\n",GetPCKFrequencyMhz() );
while (1){
printf("-T WR- 0x00000000\n");
pSDRAM = (unsigned int *) BASE_EBI_CS1_ADDRESS;
for ( wCount = 0,wWrite=0x0;wCount < 0x800000;wCount ++ ){
*pSDRAM = wWrite;
wRead = *pSDRAM;
if (wWrite != wRead )
printf ("[0x%08X] = 0x%08X ( 0x%08X,0x%08X)\n",wCount,wRead^wWrite,wRead,wWrite );
pSDRAM++;
}
}
Здесь c помощью простого осцилографа можно определить - залипания и не пропай по линиям, конечно же, ставим сначала одну микросхему, потом другую, что бы проще отлаживать было.
далее отладили ... теперь очень хочется залить что-нибудь в SDRAM и выполнить оттуда. НО
1. Контроллер SDRAM не инициализирован
2. Частоты ПЛЛ не выставлены.
Вот здесь на помощь нам приходит инструмент Жлинка , а именно его mac файл
привожу его
Код
//---- Инициализация PLLA = 200 MHz , PLLB = 48 MHz , PCK = 100MHz
init_PLL()
{
__var tmp,
var;
__message("Init Clock");
__writeMemory32(0x0000FF01,0xFFFFFC20,"Memory"); // PMC_MOR: MOSCEN = 1, enable main clock
while( (( var =__readMemory32(0xFFFFFC24,"Memory")) & (0x1 << 16)) == 0 ) { }; // wait time out
// AT91C_BASE_CKGR->CKGR_PLLAR = PLLAR_Register;
__writeMemory32(0x2030BF04,0xFFFFFC28,"Memory");
tmp = 0;
while( !(( var=__readMemory32(0xFFFFFC68,"Memory")) & ( 0x1 << 1)) && (tmp++ < 100) ) {};
var = __readMemory32(0xFFFFFC28,"Memory");
__message "PLLAR=",var;
//AT91C_BASE_CKGR->CKGR_PLLBR = PLLBR_Register;
__writeMemory32(0x10533F0E,0xFFFFFC2C,"Memory");
tmp = 0;
while( !((var = __readMemory32(0xFFFFFC68,"Memory")) & ( 0x1 << 2)) && (tmp++ < 100) ) {};
__writeMemory32( 0x1 ,0xFFFFFC30,"Memory");
tmp = 0;
while( !((var = __readMemory32(0xFFFFFC68,"Memory")) & (0x1 << 3)) && (tmp++ < 100) ) {};
// AT91C_BASE_PMC->PMC_MCKR = MCKR_Register;
__writeMemory32(0x00000102,0xFFFFFC30,"Memory");
tmp = 0;
while( !((var = __readMemory32(0xFFFFFC68,"Memory")) & (0x1 << 3)) && (tmp++ < 100) ) {};
}
//----------- Инициализация SDRAM 2х8х16 (2х MT48LC8M16A2-75)
init_SDRAM ()
{
__var i;
__message("Init SDRAM");
__writeMemory32(0xFFFF0000,0xFFFFF800 +0x0070,"Memory");
__writeMemory32(0x0,0xFFFFF800 +0x0074,"Memory");
__writeMemory32(0xFFFF0000,0xFFFFF804,"Memory");
i = __readMemory32(0xFFFFFF60,"Memory");
__writeMemory32(i|(0x1 << 1),0xFFFFFF60,"Memory");
__writeMemory32( 0x0 ,0xFFFFFF64,"Memory");
__writeMemory32( 0x2A99C255,0xFFFFFF98,"Memory");
__writeMemory32(0x02,0xFFFFFF90,"Memory");
__writeMemory32(0x0,0x20000000,"Memory");
__writeMemory32(0x04,0xFFFFFF90,"Memory");
for(i=0;i<8;i++)
__writeMemory32(0x0,0x20000000,"Memory");
__writeMemory32(0x3,0xFFFFFF90,"Memory");
__writeMemory32(0x0,0x20000000,"Memory");
__writeMemory32(0x610,0xFFFFFF94,"Memory");
__writeMemory32(0x00,0x20000000,"Memory");
__writeMemory32(0x0,0xFFFFFF90,"Memory");
__writeMemory32(0x0,0x20000000,"Memory");
}
execUserPreload()
{
init_PLL();
__writeMemory32(0xAAAAAAAA,0x00000000,"Memory");
if(__readMemory32(0x00000000,"Memory") != 0xAAAAAAAA)
{
__writeMemory32(0x01,0xFFFFFF00,"Memory"); // MC_RCR: toggle remap bit
}
init_SDRAM ();
__message("Target init macro complete");
}
init_PLL()
{
__var tmp,
var;
__message("Init Clock");
__writeMemory32(0x0000FF01,0xFFFFFC20,"Memory"); // PMC_MOR: MOSCEN = 1, enable main clock
while( (( var =__readMemory32(0xFFFFFC24,"Memory")) & (0x1 << 16)) == 0 ) { }; // wait time out
// AT91C_BASE_CKGR->CKGR_PLLAR = PLLAR_Register;
__writeMemory32(0x2030BF04,0xFFFFFC28,"Memory");
tmp = 0;
while( !(( var=__readMemory32(0xFFFFFC68,"Memory")) & ( 0x1 << 1)) && (tmp++ < 100) ) {};
var = __readMemory32(0xFFFFFC28,"Memory");
__message "PLLAR=",var;
//AT91C_BASE_CKGR->CKGR_PLLBR = PLLBR_Register;
__writeMemory32(0x10533F0E,0xFFFFFC2C,"Memory");
tmp = 0;
while( !((var = __readMemory32(0xFFFFFC68,"Memory")) & ( 0x1 << 2)) && (tmp++ < 100) ) {};
__writeMemory32( 0x1 ,0xFFFFFC30,"Memory");
tmp = 0;
while( !((var = __readMemory32(0xFFFFFC68,"Memory")) & (0x1 << 3)) && (tmp++ < 100) ) {};
// AT91C_BASE_PMC->PMC_MCKR = MCKR_Register;
__writeMemory32(0x00000102,0xFFFFFC30,"Memory");
tmp = 0;
while( !((var = __readMemory32(0xFFFFFC68,"Memory")) & (0x1 << 3)) && (tmp++ < 100) ) {};
}
//----------- Инициализация SDRAM 2х8х16 (2х MT48LC8M16A2-75)
init_SDRAM ()
{
__var i;
__message("Init SDRAM");
__writeMemory32(0xFFFF0000,0xFFFFF800 +0x0070,"Memory");
__writeMemory32(0x0,0xFFFFF800 +0x0074,"Memory");
__writeMemory32(0xFFFF0000,0xFFFFF804,"Memory");
i = __readMemory32(0xFFFFFF60,"Memory");
__writeMemory32(i|(0x1 << 1),0xFFFFFF60,"Memory");
__writeMemory32( 0x0 ,0xFFFFFF64,"Memory");
__writeMemory32( 0x2A99C255,0xFFFFFF98,"Memory");
__writeMemory32(0x02,0xFFFFFF90,"Memory");
__writeMemory32(0x0,0x20000000,"Memory");
__writeMemory32(0x04,0xFFFFFF90,"Memory");
for(i=0;i<8;i++)
__writeMemory32(0x0,0x20000000,"Memory");
__writeMemory32(0x3,0xFFFFFF90,"Memory");
__writeMemory32(0x0,0x20000000,"Memory");
__writeMemory32(0x610,0xFFFFFF94,"Memory");
__writeMemory32(0x00,0x20000000,"Memory");
__writeMemory32(0x0,0xFFFFFF90,"Memory");
__writeMemory32(0x0,0x20000000,"Memory");
}
execUserPreload()
{
init_PLL();
__writeMemory32(0xAAAAAAAA,0x00000000,"Memory");
if(__readMemory32(0x00000000,"Memory") != 0xAAAAAAAA)
{
__writeMemory32(0x01,0xFFFFFF00,"Memory"); // MC_RCR: toggle remap bit
}
init_SDRAM ();
__message("Target init macro complete");
}
теперь можите компилить код с загрузкой в сдрам и выполнять его отуда.
Замечу , что с адреса 0х0 распологается SRAM и в стартап коде надо перенести в область 0х0 - 0х38
вектора прерывания.
пример стартапа at91_cstartup.s79
Код
MODULE ?RESET
; COMMON INTVEC:CODE:NOROOT(2); Я убрал, линкер подразумевает эту секцию с 0 , но её мы будем копировать в SRAM
RSEG ICODE:CODE:NOROOT(2)
PUBLIC __program_start
EXTERN ?cstartup
; EXTERN undef_handler, swi_handler, prefetch_handler
; EXTERN data_handler, irq_handler, fiq_handler
CODE32; Always ARM mode after reset
ADRSTART:
org 0x00+ADRSTART
__program_start
ldr pc,=?cstartup; Absolute jump
org 0x04+ADRSTART
undef_handler:
ldr pc,=undef_handler
org 0x08+ADRSTART
swi_handler:
ldr pc,=swi_handler
org 0x0c+ADRSTART
prefetch_handler:
ldr pc,=prefetch_handler
org 0x10+ADRSTART
data_handler:
ldr pc,=data_handler
org 0x18+ADRSTART
ldr pc, [pc,#-0xF20] ; IRQ : read the AIC
org 0x1c+ADRSTART
fiq_handler:
ldr pc,=fiq_handler
; Constant table entries (for ldr pc) will be placed at 0x20
org 0x20+ADRSTART
LTORG
; ENDMOD __program_start
ENDMOD
;---------------------------------------------------------------
; ?CSTARTUP
;---------------------------------------------------------------
MODULE ?CSTARTUP
RSEG IRQ_STACK:DATA(2)
RSEG SVC_STACK:DATA:NOROOT(2)
RSEG CSTACK:DATA(2)
RSEG ICODE:CODE:NOROOT(2)
PUBLIC ?cstartup
EXTERN ?main
; Execution starts here.
; After a reset, the mode is ARM, Supervisor, interrupts disabled.
CODE32
?cstartup
; Add initialization nedded before setup of stackpointers here
; Initialize the stack pointers.
; The pattern below can be used for any of the exception stacks:
; FIQ, IRQ, SVC, ABT, UND, SYS.
; The USR mode uses the same stack as SYS.
; The stack segments must be defined in the linker command file,
; and be declared above.
mrs r0,cpsr ; Original PSR value
bic r0,r0,#MODE_BITS ; Clear the mode bits
.... дальше как было
; COMMON INTVEC:CODE:NOROOT(2); Я убрал, линкер подразумевает эту секцию с 0 , но её мы будем копировать в SRAM
RSEG ICODE:CODE:NOROOT(2)
PUBLIC __program_start
EXTERN ?cstartup
; EXTERN undef_handler, swi_handler, prefetch_handler
; EXTERN data_handler, irq_handler, fiq_handler
CODE32; Always ARM mode after reset
ADRSTART:
org 0x00+ADRSTART
__program_start
ldr pc,=?cstartup; Absolute jump
org 0x04+ADRSTART
undef_handler:
ldr pc,=undef_handler
org 0x08+ADRSTART
swi_handler:
ldr pc,=swi_handler
org 0x0c+ADRSTART
prefetch_handler:
ldr pc,=prefetch_handler
org 0x10+ADRSTART
data_handler:
ldr pc,=data_handler
org 0x18+ADRSTART
ldr pc, [pc,#-0xF20] ; IRQ : read the AIC
org 0x1c+ADRSTART
fiq_handler:
ldr pc,=fiq_handler
; Constant table entries (for ldr pc) will be placed at 0x20
org 0x20+ADRSTART
LTORG
; ENDMOD __program_start
ENDMOD
;---------------------------------------------------------------
; ?CSTARTUP
;---------------------------------------------------------------
MODULE ?CSTARTUP
RSEG IRQ_STACK:DATA(2)
RSEG SVC_STACK:DATA:NOROOT(2)
RSEG CSTACK:DATA(2)
RSEG ICODE:CODE:NOROOT(2)
PUBLIC ?cstartup
EXTERN ?main
; Execution starts here.
; After a reset, the mode is ARM, Supervisor, interrupts disabled.
CODE32
?cstartup
; Add initialization nedded before setup of stackpointers here
; Initialize the stack pointers.
; The pattern below can be used for any of the exception stacks:
; FIQ, IRQ, SVC, ABT, UND, SYS.
; The USR mode uses the same stack as SYS.
; The stack segments must be defined in the linker command file,
; and be declared above.
mrs r0,cpsr ; Original PSR value
bic r0,r0,#MODE_BITS ; Clear the mode bits
.... дальше как было
понятно , что в lowlevelinit пишите перемещение области памяти 0х2000000 - 0х20000038 на 0 адрес
или прямо в стартапном коде перемещение делаете.
хотя можно и использовать TTB для ремпаирования, но это вы дальше будете делать...