The website "dmilvdv.narod.ru." is not registered with uCoz.
If you are absolutely sure your website must be here,
please contact our Support Team.
If you were searching for something on the Internet and ended up here, try again:

About uCoz web-service

Community

Legal information

Bootstrap

Bootstrap

Предыдущая  Содержание  Следующая  V*D*V

Загрузчик первого уровня. Его задача: провести начальную инициализацию процессора, настроить управление памятью, скопировать кусок данных из указанного ему места из энергонезависимой памяти в ОЗУ и передать управление на этот адрес, считая, что он скопировал программу. Чаще всего в качестве этой программы используется загрузчик второго уровня 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.

 

Внимание!

размер файла не должен превышать 4096 байта!!!

 

Смотри также

Расчёт параметров PLL

Расчёт таймингов Nandflash

Адаптация кода для прямого запуска ядра Linux

http://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;

 

Предыдущая  Содержание  Следующая