TI am335x U-boot移植(正常啟動)
******************************************************************
深圳南山 2017/09/26
*******************************************************************
Ti am335x u_boot 啟動:利用串列埠(UART)寫。
http://processors.wiki.ti.com/index.php/AM335x_U-Boot_User%27s_Guide#NAND_2
http://processors.wiki.ti.com/index.php/Linux_Kernel_Users_Guide
1. U-boot原始碼中的遮蔽i2c的程式碼:
static structam335x_baseboard_id __attribute__((section (".data"))) header;
static intread_eeprom(void) //讀取eeprom的引數。
{
/* Check if baseboard eeprom is available */
puts("board/ti/am335x/board.c/read_eeprom()\n"); //列印資訊
memcpy(header.name,"A335X_SK",HDR_NAME_LEN); //賦予全域性變數header結構體中的name變數為A335X_SK
#if 0
if(i2c_probe(CONFIG_SYS_I2C_EEPROM_ADDR)) {
puts("Could not probethe EEPROM; something fundamentally "
"wrong on theI2C bus.\n");
return -ENODEV;
}
/* read the eeprom using i2c */
if(i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, 2, (uchar *)&header,
sizeof(header))){
puts("Could not read theEEPROM; something fundamentally"
" wrong on theI2C bus.\n");
return -EIO;
}
if (header.magic != 0xEE3355AA) {
/*
* read the eeprom using i2c again,
* but use only a 1 byte address
*/
if(i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, 1,
(uchar*)&header, sizeof(header))) {
puts("Could notread the EEPROM; something "
"fundamentallywrong on the I2C bus.\n");
return -EIO;
}
if (header.magic !=0xEE3355AA) {
printf("Incorrectmagic number (0x%x) in EEPROM\n",
header.magic);
return -EINVAL;
}
}
#endif
return 0;
}
void s_init(void)
{
//__maybe_unused structam335x_baseboard_id header; 將定義的區域性變數註釋掉
#if 0
if(i2c_probe(CONFIG_SYS_I2C_EEPROM_ADDR)) {
puts("Could not probethe EEPROM; something fundamentally "
"wrong on theI2C bus.\n");
}
/* read the eeprom using i2c */
if(i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, 2, (uchar *)&header,
sizeof(header))){
puts("Could not read theEEPROM; something fundamentally"
" wrong on theI2C bus.\n");
}
if (header.magic != 0xEE3355AA) {
/*
* read the eeprom using i2c again,
* but use only a 1 byte address
*/
if (i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR,0, 1,
(uchar*)&header, sizeof(header))) {
puts("Could notread the EEPROM; something "
"fundamentallywrong on the I2C bus.\n");
hang();
}
if (header.magic !=0xEE3355AA) {
printf("Incorrectmagic number (0x%x) in EEPROM\n",
header.magic);
hang();
}
}
#endif
if (!strncmp("A335XS",header.name, HDR_NAME_LEN))
/* 將A335X_SK改名 A335XS,和header.name 比較,更改預設的DDR3啟動*/
config_ddr(303, MT41J128MJT125_IOCTRL_VALUE,&ddr3_data,
&ddr3_cmd_ctrl_data, &ddr3_emif_reg_data);
else if (!strncmp("A335BNLT", header.name, 8))
config_ddr(400, MT41K256M16HA125E_IOCTRL_VALU
#endif
}
2. 編譯原始碼:寫個指令碼start.sh自動編譯
該指令碼放在u-boot原始碼的根目錄下面:start.sh
#!/bin/sh
cd/usr/local/ti-sdk-am335x-evm/board-support/u-boot-2013.01.01-psp06.00.00.00
[ -d ./am335x ] && sudo rm -rf./am335x
make O=am335xCROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm am335x_evm
cp/usr/local/ti-sdk-am335x-evm/board-support/u-boot-2013.01.01-psp06.00.00.00/am335x/spl/u-boot-spl.bin/mnt/hgfs/share/
cp/usr/local/ti-sdk-am335x-evm/board-support/u-boot-2013.01.01-psp06.00.00.00/am335x/u-boot.img/mnt/hgfs/share
cp/usr/local/ti-sdk-am335x-evm/board-support/u-boot-2013.01.01-psp06.00.00.00/am335x/MLO/mnt/hgfs/share/
具體的路徑和自身的目錄進行修改。
*如果不用獨立的目錄放生成檔案的,用下命令清除生成的檔案:
$ make CROSS_COMPILE=arm-linux-gnueabihf- distclean
*如果用獨立的目錄放生成的檔案,直接刪除目錄就好了,O=am335x_evm :
$ rm -rf ./am335x_evm
3.用工具下載編譯生成的檔案
建議選擇超級終端作為軟體。
*The release package does not contain thebinary for UART boot. Please follow the steps mentioned herefor compiling u-boot and use the spl/u-boot-spl.bin file that isproduced.
1. Switch ON EVM withswitch settings for UARTboot. When “CCCC” characters appear on TeraTerm window, from the File Menuselect Transfer --> XMODEM --> Send (1K mode)
2. Select “u-boot-spl.bin” for the transfer
3. After image issuccessfully downloaded, the ROM code will boot it.
4. When “CCCC”characters appear on TeraTerm window, from the File Menu select Transfer -->YMODEM --> Send (1K mode)
5. Select “u-boot.img” for the transfer
6. After image is successfullydownloaded, U-Boot will boot it.
7. Hit enter and getto u-boot prompt “U-Boot# ”
3.1Flash SPL (MLO) to NAND by executing the followingcommands
nand erase 0x0 0x20000
loadb 0x82000000 ( tftp 0x82000000 MLO )
- From TeraTerm Menu click “File -> Transfer -> Kermit -> Send”.
- Select the 1st stage u-boot image “MLO” and click “OPEN” button
- Wait for download to complete and then run following commands in u-boot prompt
nand write 0x82000000 0x0 0x20000
nand erase 0x80000 0x1E0000
loadb 0x82000000 ( tftp 0x82000000 u-boot.img )
- From TeraTerm Menu click “File -> Transfer -> Kermit -> Send”.
- Select the 2nd stage u-boot image “u-boot.img” and click “OPEN” button
- Wait for download to complete and then run following commands in U-Boot prompt
nand write 0x82000000 0x80000 0x1E0000
不出問題的,就可以:boot了。
然後將撥動到NAND啟動。
核心的下載:
nand erase 0x280000 0x500000
loadb 0x82000000 ( tftp 0x82000000 uImage )
nand write 0x82000000 0x280000 0x500000
3.2利用am3358開發產品,開始是在SD卡中除錯,沒問題後都燒寫到nand中。命令如下:(有待驗證)
http://www.deyisupport.com/question_answer/dsp_arm/sitara_arm/f/25/t/62170.aspx
4.U-Boot Network configuration
To set a different MAC address use thefollowing command
U-Boot# set ethaddr <random MAC address eg- 08:11:23:32:12:77>
In case a static ip is not available run the dhcp command to obtain the ip address from the DHCP server on the network to which the EVM is connected
U-Boot# setenv serverip <tftp server in your network>
U-Boot# setenv ipaddr xxx.xxx.x.xx
U-Boot# setenv netmask 255.255.255.0
U-Boot# setenv gatewayip 192.168.1.1
U-Boot# dhcp
U-Boot# saveenv
U-Boot# mtdparts 檢視NAND的分割槽段
nand erase.part <partition name>
U-Boot# nand erase.part NAND.kernel
U-Boot# nand erase.chip 擦除晶片NAND
U-Boot# env default –f –a 恢復預設的環境變數
In case a static ip is available run the following commands
U-Boot# setenv ipaddr <your static ip>
U-Boot# saveenv
5.Flash Kernel
TFTP the kernel uImage to DDR.
U-Boot# tftp 0x82000000 <kernel_image>
U-Boot# nand erase 0x00280000 0x500000
U-Boot# nand write 0x82000000 0x00280000 0x500000
*Image_size should be aligned to page size of 2048 (0x800) bytes
6.移植uboot時乙太網的修改
乙太網部分修改很簡單,修改乙太網引腳配置,在mux.c檔案裡面,然後在evm.c檔案裡面修改evm_phy_init(),cpsw_slaves[],cpsw_data,board_eth_init()
6.1 引腳配置:
1./board/ti/am335x裡面的Board.c 中的s_init()函式呼叫enable_board_pin_mux();
2./board/ti/am335x裡面的Mux.c 中的enable_board_pin_mux()呼叫configure_module_pin_mux(rmii1_pin_mux)配置引腳;
/* Mux.c */
static structmodule_pin_mux rmii1_pin_mux[]={
{OFFSET(mii1_txen), MODE(1)}, /*RMII1_TXEN */
{OFFSET(mii1_txd1), MODE(1)}, /*RMII1_TXD1 */
{OFFSET(mii1_txd0), MODE(1)}, /*RMII1_TXD1 */
{OFFSET(mii1_rxd1), MODE(1) |RXACTIVE}, /* RMII1_RXD1 */
{OFFSET(mii1_rxd0), MODE(1) |RXACTIVE}, /* RMII1_RXD1 */
{OFFSET(mdio_data), MODE(0) | RXACTIVE| PULLUP_EN},/* MDIO_DATA */
{OFFSET(mdio_clk), MODE(0) |PULLUP_EN}, /* MDIO_CLK */
{OFFSET(mii1_crs), MODE(1) | RXACTIVE},/* RMII1_CRS_DV */
{OFFSET(rmii1_refclk), MODE(0) |RXACTIVE}, /* RMII1_REFCLK */
{-1},
};
6.2 乙太網初始化
2.Board.c(board/ti/am335x)中的board_eth_init(),先讀MAC地址,在寫暫存器選擇模式的值,最後註冊cpsw_register();
board_eth_init(){
···
if (board_is_bone() || board_is_bone_lt() ||board_is_idk()) {
writel(MII_MODE_ENABLE,&cdev->miisel);
cpsw_slaves[0].phy_if =cpsw_slaves[1].phy_if =
PHY_INTERFACE_MODE_MII;
}else {
writel(RMII_MODE_ENABLE,&cdev->miisel);
printf("MII isseted RMII\n"); //----Tbao---
cpsw_slaves[0].phy_if= cpsw_slaves[1].phy_if =
PHY_INTERFACE_MODE_RMII;
}
···
}
註釋如下:
writel(RMII_MODE_ENABLE,&cdev->miisel); 將選擇的RMII模式寫到暫存器裡面。
定義巨集:#define RMII_MODE_ENABLE 0xC5
在晶片手冊裡找到暫存器miisel,看每個管腳位的配置,根據硬體確定0xC5值:
有兩個slave,cpsw_slaves[0]/ cpsw_slaves[1].
/* Board.c (Board/ti/am335x) */
static struct cpsw_slave_data cpsw_slaves[] = {
{
.slave_reg_ofs = 0x208,
.sliver_reg_ofs = 0xd80,
.phy_id =1, //phy_id =1 -----Tbao-----
},
{
.slave_reg_ofs = 0x308,
.sliver_reg_ofs = 0xdc0,
.phy_id = 2, //phy_id=2 -----Tbao-----
},
};
所以將結構體中的cpsw_data的slaves 改成2。
Static struct cpsw_platform_data cpsw_data = {
.mdio_base = AM335X_CPSW_MDIO_BASE,
.cpsw_base = AM335X_CPSW_BASE,
.mdio_div = 0xff,
.channels = 8,
.cpdma_reg_ofs = 0x800,
.slaves = 2, //hacve 2 slaves ----Tbao---
.slave_data = cpsw_slaves,
.ale_reg_ofs = 0xd00,
.ale_entries = 1024,
.host_port_reg_ofs = 0x108,
.hw_stats_reg_ofs = 0x900,
.mac_control = (1 << 5),
.control = cpsw_control,
.host_port_num = 0,
.version = CPSW_CTRL_VERSION_2,
};
#endif
6.3. arch/arm/lib/中的函式Board.c中的board_init_r()開始:
1. #if defined(CONFIG_CMD_NET) // InitialNet ---Tbao----
puts("Net: ");
printf("File=%s,Function=%s,Line=%d\n",__FILE__,__FUNCTION__,__LINE__);
eth_initialize(gd->bd);
#ifdefined(CONFIG_RESET_PHY_R)
debug("Reset EthernetPHY\n");
reset_phy();
#endif
#endif
3. Eth.c 中的eth_initialize()
eth_initialize(){
······
miipyy_init();
phy_init();
board_eth_init();(回到/ti/am335x中的board.c函式)
·····
}
4. 在phy_init()(drivers/net/phy)中初始化
初始化DP83848i晶片。
static struct phy_driver DP83848_driver = {
.name = "NatSemi DP83848",
.uid = 0x20005c90,
.mask = 0x2000ff90,
.features = PHY_BASIC_FEATURES,
.config = &dp838xx_config,
.startup = &dp83848_startup,
.shutdown = &genphy_shutdown,
};
int phy_natsemi_init(void)
{
//phy_register(&DP83630_driver);
//phy_register(&DP83865_driver);
phy_register(&DP83848_driver);
return 0;
}
8. 檔案系統的建立
8.1檔案系統的燒寫
http://processors.wiki.ti.com/index.php/UBIFS_Support#Creating_UBIFS_file_system
在燒u-boot或者核心、檔案系統之前,應先將NAND flash 擦除一下,否則後面可能有問題。
nand erase.chip 或者暴力擦除: nand scrub.chip (慎用)
nand erase 0x0 0x10000000
U-BOOT# nand erase 0x780000 0xf880000
U-BOOT# tftp 0x82000000 ubi.img