Bootstrap |
Предыдущая Содержание Следующая |
|
Загрузчик первого уровня. Его задача: провести начальную инициализацию процессора, настроить управление памятью, скопировать кусок данных из указанного ему места из энергонезависимой памяти в ОЗУ и передать управление на этот адрес, считая, что он скопировал программу. Чаще всего в качестве этой программы используется загрузчик второго уровня U-Boot. Можно также сразу запускать ядро Linux.
Bootstrap также производит необходимую настройку интерфейса процессора: •PLL A и PLL B; •Частоты процессора; •шину SPI или параметры доступа к Nandflash;
Используем оригинальный AT91Bootstrap1.14 от Atmel. ftp://anonymous+at91.com:sam@www.at91.com/pub/at91bootstrap Конфигурация RAMВ файле /board/at91sam9260ek/at91sam9260ek.c в функции void hw_init(void) выставить размер шины данных RAM (если используется микросхема памяти с другой организацией, проверить и другие параметры):
/* Configure SDRAM Controller */ sdram_init( AT91C_SDRAMC_NC_9 | AT91C_SDRAMC_NR_13 | AT91C_SDRAMC_CAS_2 | AT91C_SDRAMC_NB_4_BANKS | AT91C_SDRAMC_DBW_32_BITS | AT91C_SDRAMC_TWR_2 | AT91C_SDRAMC_TRC_7 | AT91C_SDRAMC_TRP_2 | AT91C_SDRAMC_TRCD_2 | AT91C_SDRAMC_TRAS_5 | AT91C_SDRAMC_TXSR_8, /* Control Register */ (MASTER_CLOCK * 7)/1000000, /* Refresh Timer Register */ AT91C_SDRAMC_MD_SDRAM); /* SDRAM (no low power) */
В функции void sdramc_hw_init(void) проверить инициализацию шины. Для 32-х бит:
writel(0xFFFF0000, AT91C_BASE_PIOC + PIO_ASR(0)); writel(0xFFFF0000, AT91C_BASE_PIOC + PIO_PDR(0));
Для 16-ти бит:
writel(0x00000000, AT91C_BASE_PIOC + PIO_ASR(0)); writel(0x00000000, AT91C_BASE_PIOC + PIO_PDR(0)); Адаптация кода для загрузки из DataflashУказать используемую микросхему Dataflash: /driver/dataflash.c, функция df_init.
В файле /board/at91sam9260ek/dataflash/at91sam9260ek.h: Выставить рабочую частоту и параметры PLL для кварца 12 MHz:
#define MASTER_CLOCK (200000000/2) #define PLLA_SETTINGS 0x2031BF03 #define PLLB_SETTINGS 0x10073F01
Понизить при необходимости частоту SPI:
#define AT91C_SPI_CLK 4800000
Проверить адресацию микросхемы Dataflash:
#define AT91C_SPI_PCS_DATAFLASH AT91C_SPI_PCS1_DATAFLASH /* Boot on SPI NCS0 */
Проверить параметры копирования и запуска:
#define IMG_ADDRESS 0x8400 #define IMG_SIZE 0x33900 #define JUMP_ADDR 0x23F00000
IMG_ADDRESS: адрес загрузки U-Boot; IMG_SIZE: размер копируемых данных, должен быть не меньше размера u-boot.bin; JUMP_ADDR: адрес старта U-Boot, см. /u-boot/board/at91sam9260ek/config.mk;
Проверить используемую шину данных для Nandflash в /board/at91sam9260ek/at91sam9260ek.c функция void nandflash_hw_init(void):
writel((AT91C_SMC_READMODE | AT91C_SMC_WRITEMODE | AT91C_SMC_NWAITM_NWAIT_DISABLE | AT91C_SMC_DBW_WIDTH_EIGHT_BITS | AT91C_SM_TDF) Адаптация кода для загрузки из NandflashВ файле /board/at91sam9260ek/nandflash/: Выставить рабочую частоту и параметры PLL для кварца 12 MHz:
#define MASTER_CLOCK (200000000/2) #define PLLA_SETTINGS 0x2031BF03 #define PLLB_SETTINGS 0x10073F01
Проверить параметры копирования и запуска:
#define IMG_ADDRESS 0x8400 #define IMG_SIZE 0x33900 #define JUMP_ADDR 0x23F00000
IMG_ADDRESS: адрес загрузки U-Boot; IMG_SIZE: размер копируемых данных, должен быть не меньше размера u-boot.bin; JUMP_ADDR: адрес старта U-Boot, см. /u-boot/board/at91sam9260ek/config.mk;
Проверить используемую шину данных для Nandflash в /board/at91sam9260ek/at91sam9260ek.c функция void nandflash_hw_init(void):
writel((AT91C_SMC_READMODE | AT91C_SMC_WRITEMODE | AT91C_SMC_NWAITM_NWAIT_DISABLE | AT91C_SMC_DBW_WIDTH_EIGTH_BITS | AT91C_SM_TDF)
Выставить параметры используемой микросхемы NandFlash. Эти же параметры надо прописать в ядре Linux. Приведены параметры для k9k8g08u0a:
/* These timings are specific to K9K8G08U0A (samsung) MCK = 100 MHZ */
#define AT91C_SM_NWE_SETUP (1 << 0) #define AT91C_SM_NCS_WR_SETUP (0 << 8) #define AT91C_SM_NRD_SETUP (1 << 16) #define AT91C_SM_NCS_RD_SETUP (0 << 24)
#define AT91C_SM_NWE_PULSE (2 << 0) #define AT91C_SM_NCS_WR_PULSE (3 << 8) #define AT91C_SM_NRD_PULSE (2 << 16) #define AT91C_SM_NCS_RD_PULSE (2 << 24)
#define AT91C_SM_NWE_CYCLE (3 << 0) #define AT91C_SM_NRD_CYCLE (3 << 16) #define AT91C_SM_TDF (2 << 16) Сторожевой таймерПо умолчанию Bootstrap его выключает, после чего его уже не включить. Для запрета его выключения в /board/at91sam9260ek/at91sam9260ek.c в функции void hw_init(void) убрать строчку:
/* Disable watchdog */ //writel(AT91C_WDTC_WDDIS, AT91C_BASE_WDTC + WDTC_WDMR); КомпиляторИспользуется EABI компилятор. http://www.codesourcery.com/sgpp/lite/arm/portal/subscription?@template=lite. Используется не новее 2007q1-21. Причина: непонятное увеличение размера скомпилированного файла. КомпиляцияСделать файл следующего содержания, положить его в папку /dataflash или /nandflash и запустить:
#!/bin/sh export PATH=/<path to toolchain>/arm-2007q1/bin:${PATH}
make CROSS_COMPILE=arm-none-eabi-
Результат сборки: board/at91sam9260ek/dataflash/dataflash_at91sam9260ek.bin.
Смотри также Адаптация кода для прямого запуска ядра Linuxhttp://www.simtec.co.uk/products/SWLINUX/files/booting_article.pdf.
При этом метода запуска используется компрессированный образ, полученный после компиляции Linux: /<path>/arch/arm/boot/zImage.
Суть процесса: •KERNEL_PARAMS_ADDRESS задаёт адрес таблицы параметров ядра. Обычно это смещение 0x100 от начала физической памяти. Начало памяти отводится для хранения векторов и таблицы страниц. •JUMP_ADDRESS задаёт адрес, куда будет помещён компрессированный образ Linux (zImage). Некомпрессированное ядро не превышает 4 Мб. Для того, чтобы оно могло распаковаться, после zImage должно оставаться минимум 4 Мб свободной памяти. Общепринятым значением является смещение 0x8000 от начала памяти.
Параметры копирования и адреса старта и местонахождения параметров ядра /board/at91sam9260ek/dataflash/at91sam9260ek.h:
#define IMG_ADDRESS 0x42000 /* Image Address in DataFlash */ #define IMG_SIZE 0x210000 /* Image Size in DataFlash */
#define MACH_TYPE 0x44B /* AT91SAM9260-EK */
#define MEM_START 0x20000000 /* RAM base address */ #define MEM_SIZE 0x4000000 /* RAM size 64M */
#define JUMP_ADDR 0x20008000 /* kernel image address in RAM */ #define KERNEL_PARAMS_ADDRESS 0x20000100 /* kernel parameters in RAM */ /* #define BOOT_ARG "mem=64M console=ttyS0,115200"
#define BOOT_ARG "mem=64M console=ttyS0,115200 ubi.mtd=rootfs"
#define BOOT_ARG "mem=64M console=ttyS0,115200 " \ "root=ubi0:rootfs ubi.mtd=rootfs \ "rootfstype=ubifs rootflags=bulk_read,chk_data_crc rw" */ #define BOOT_ARG "mem=64M console=ttyS0,115200 " \ "root=/dev/mtdblock1 " \ "rw rootfstype=jffs2"
Добавить в main.c функции инициализации:
/* list of possible tags */ #define ATAG_NONE 0x00000000 #define ATAG_CORE 0x54410001 #define ATAG_MEM 0x54410002 #define ATAG_CMDLINE 0x54410009
/* structures for each atag */ struct atag_header { unsigned int size; /* length of tag in words including this header */ unsigned int tag; /* tag type */ };
struct atag_core { unsigned int flags; unsigned int pagesize; unsigned int rootdev; };
struct atag_mem { unsigned int size; unsigned int start; };
struct atag_cmdline { char cmdline[1]; };
struct atag { struct atag_header hdr; union { struct atag_core core; struct atag_mem mem; struct atag_cmdline cmdline; } u; };
#define tag_next( t ) ((struct atag *)((unsigned int *)( t ) + ( t ) -> hdr.size)) #define tag_size( type ) ((sizeof(struct atag_header) + sizeof(struct type)) >> 2) static struct atag *params; /* used to point at the current tag */
static void setup_core_tag() { params = (struct atag *)KERNEL_PARAMS_ADDRESS; /* Initialise parameters to start at given address */
params->hdr.tag = ATAG_CORE; /* start with the core tag */ params->hdr.size = tag_size( atag_core ); /* size the tag */
params->u.core.flags = 0; /* optional, ensure read-only */ params->u.core.pagesize = 0; /* optional, systems pagesize (4k) */ params->u.core.rootdev = 0; /* zero root device (typicaly overidden from commandline )*/
params = tag_next( params ); /* move pointer to next tag */ }
static void setup_mem_tag() { params->hdr.tag = ATAG_MEM; /* Memory tag */ params->hdr.size = tag_size( atag_mem ); /* size tag */ params->u.mem.start = RAM_BASE; /* start of physical memory */ params->u.mem.size = RAM_SIZE; /* memory size */ params = tag_next( params ); /* move pointer to next tag */ }
static void setup_cmdline_tag() { #ifdef BOOT_ARG char* line = BOOT_ARG "\0"; /* place commandline into tag */ int linelen = 0; for( ; *(line + linelen) != 0; linelen++ ) { params->u.cmdline.cmdline[linelen] = *(line + linelen);} if( !linelen ) /* do not insert a tag for an empty string */ return; params->u.cmdline.cmdline[linelen] = 0; params->hdr.tag = ATAG_CMDLINE; /* Commandline tag */ params->hdr.size = (sizeof(struct atag_header) + linelen + 1 + 4) >> 2; params = tag_next(params); /* move pointer to next tag */ #endif /* BOOT_ARG */ }
static void setup_end_tag() { params->hdr.tag = ATAG_NONE; /* Empty tag ends list */ params->hdr.size = 0; /* zero length */ }
Добавить в main.c функцию подготовки процессора к старту (запретить прерывания, выключить кэш данных):
static int cleanup_before_linux() { unsigned long i,old,temp;
/* disable interrupts */ __asm__ __volatile__("mrs %0, cpsr\n" "orr %1, %0, #0xc0\n" "msr cpsr_c, %1" : "=r" (old), "=r" (temp) : : "memory");
/* turn off I/D-cache */ asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); i &= ~(C1_DC | C1_IC); asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
/* flush I/D-cache */ i = 0; asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i));
return 0; }
Заменить запуск приложения в main.c на вызовы функций:
/* ==================== 4th step: Start the Linux =================== */ #ifdef CFG_DEBUG dbg_print("set tags\r\n"); #endif setup_core_tag(); /* standard core tag */ setup_mem_tag(); setup_cmdline_tag(); /* commandline setting root device */ setup_end_tag(); /* end of tags */ #ifdef CFG_DEBUG dbg_print("cleanup\r\n"); #endif cleanup_before_linux(); void (*theKernel)(int zero, int arch, unsigned int params); theKernel = (void (*)(int, int, unsigned int))JUMP_ADDR; #ifdef CFG_DEBUG dbg_print("start kernel\r\n"); #endif /* Jump to kernel with register set*/ theKernel( 0, MACH_TYPE, KERNEL_PARAMS_ADDRESS ); /* R0=0,R1=MACH_TYPE,R2=KERNEL_PARAMS_ADDRESS */ return 0;
| ||
Предыдущая Содержание Следующая |