全部博文(28)
分类: LINUX
2013-11-02 13:34:01
u-boot-2009.08在mini2440上的移植
增加USB功能
[日期:2011-05-14] 来源:Linux社区 作者:singleboy [字体:大 中 小]
移植环境
1,主机环境:VMare下CentOS 5.5 ,1G内存。
2,集成开发环境:Elipse IDE
3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-eabi-gcc v4.5.1。
4,开发板:mini2440,2M nor flash,128M nand flash。
5,u-boot版本:u-boot-2009.08
6,参考文章:
8.1,实现u-boot的usb slave下载功能
友善自带的dnw下的usb下载功能真的很好用,于是也想实现此功能,现参考博文为u-boot-2009.08 添加 dnw usb下载功能,操作如下(红色字体部分为修改或添加的代码):
【1】复制usb slave驱动源代码,源码下载uboot-usb_slave.tar.bz2 下载在
下载后将源码解压到u-boot-2009.08/drivers/usb/目录下:
[root@localhost ~]# cd ./u-boot-test/u-boot-2009.08/drivers/usb
[root@localhost usb]# tar -jxf /root/100109001526.bz2
[root@localhost usb]# ls
gadget host musb slave
[root@localhost usb]#
【2】用gedit打开u-boot-2009.08/Makefile,定位到243行附近,修改如下:
LIBS += drivers/usb/host/libusb_host.a
LIBS += drivers/usb/musb/libusb_musb.a
LIBS += drivers/usb/slave/libusb_slave.a
LIBS += drivers/video/libvideo.a
【3】打开/lib_arm/board.c,定位到423行附近,修改如下:
#if defined(CONFIG_MISC_INIT_R)
/* miscellaneous platform dependent initialisations */
misc_init_r ();
#endif
extern void port_init(void);
port_init();
/* enable exceptions */
enable_interrupts ();
#if defined(CONFIG_USB_DEVICE)
extern int usb_init_slave(void);
usb_init_slave();
#endif
/* Perform network card initialisation if necessary */
#ifdef CONFIG_DRIVER_TI_EMAC
这里要强调下hugerat 博主说得很对,usb_init() 应改为 usb_init_slave()。详情请参见mini2440 实现u-boot的usb slave下载功能。
【4】打开/include/configs/mini2440.h,定位到48行附近,注释掉下面代码:
#define USE_920T_MMU 1
//#undef CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
定位到173行附近,加入如下代码:
/* valid baudrates */
#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
#define CONFIG_SYS_CONSOLE_IS_IN_ENV //It's important to serial console !
//Define this if you want stdin, stdout &/or stderr to be set to usbtty
/*
USB device support
*/
#define CONFIG_USB_DEVICE 1
#ifdef CONFIG_USB_DEVICE
#define CONFIG_USE_IRQ 1
#endif
/*-----------------------------------------------------------------------
* Stack sizes
注意,#define CONFIG_SYS_CONSOLE_IS_IN_ENV 配置非常重要,不配置此项,只能看到控制台信息在LCD上的显示,而在串口终端没有输出!
【5】打开/cpu/arm920t/s3c24x0/interrupts.c,定位到文件末尾处添加arch_interrupt_init函数定义:
void do_irq (struct pt_regs *pt_regs)
{
S3C24X0_INTERRUPT * irq = S3C24X0_GetBase_INTERRUPT();
u_int32_t intpnd = irq->INTPND;
}
int arch_interrupt_init (void)
{
return 0;
}
【6】/cpu/arm920t/start.S,定位到625行附近,加入下面代码:
#ifdef CONFIG_USE_IRQ
.align 5
irq:
/*
get_irq_stack
irq_save_user_regs
bl do_irq
irq_restore_user_regs
*/
/* use IRQ for USB and DMA */
sub lr, lr, #4 @ the return address
ldr sp, IRQ_STACK_START @ the stack for irq
stmdb sp!, { r0-r12,lr } @ save registers
ldr lr, =int_return @ set the return addr
ldr pc, =IRQ_Handle @ call the isr
int_return:
ldmia sp!, { r0-r12,pc }^ @ return from interrupt
.align 5
fiq:
get_fiq_stack
/* someone ought to write a more effiction fiq_save_user_regs */
irq_save_user_regs
bl do_fiq
irq_restore_user_regs
#else
【7】打开/include/s3c24x0.h,定位到330行附近,修改如下:
S3C24X0_REG8 MAXP_REG;
S3C24X0_REG8 res10[3]; //S3C24X0_REG8 res10[7];
S3C24X0_REG8 EP0_CSR_IN_CSR1_REG;
S3C24X0_REG8 res11[3];
S3C24X0_REG8 IN_CSR2_REG;
S3C24X0_REG8 res12[7]; //S3C24X0_REG8 res12[3];
S3C24X0_REG8 OUT_CSR1_REG;
S3C24X0_REG8 res13[3]; //S3C24X0_REG8 res13[7];
S3C24X0_REG8 OUT_CSR2_REG;
S3C24X0_REG8 res14[3];
S3C24X0_REG8 OUT_FIFO_CNT1_REG;
S3C24X0_REG8 res15[3];
S3C24X0_REG8 OUT_FIFO_CNT2_REG;
S3C24X0_REG8 res16[3];
#endif /* __BIG_ENDIAN */
//S3C24X0_USB_DEV_FIFOS fifo[5];
//S3C24X0_USB_DEV_DMAS dma[5];
S3C24X0_REG32 res17[8];
S3C24X0_USB_DEV_FIFOS fifo[5];
S3C24X0_REG32 res18[11];
S3C24X0_USB_DEV_DMAS ep1;
S3C24X0_USB_DEV_DMAS ep2;
S3C24X0_REG8 res19[16];
S3C24X0_USB_DEV_DMAS ep3;
S3C24X0_USB_DEV_DMAS ep4;
} /*__attribute__((__packed__))*/ S3C24X0_USB_DEVICE;
【8】添加usbslave命令
在/common/目录下创建文件cmd_usbslave.c,然后将下面内容粘贴进去:
#include
#include
#include
#ifdef CONFIG_USB_DEVICE
#ifdef CONFIG_USE_IRQ
#define IRQ_STACK_START (_armboot_start - CONFIG_SYS_MALLOC_LEN - CONFIG_SYS_GBL_DATA_SIZE - 4)
#define FIQ_STACK_START (IRQ_STACK_START - CONFIG_STACKSIZE_IRQ)
#define FREE_RAM_END (FIQ_STACK_START - CONFIG_STACKSIZE_FIQ - CONFIG_STACKSIZE)
#define FREE_RAM_SIZE (FREE_RAM_END - PHYS_SDRAM_1)
#else
#define FREE_RAM_END (_armboot_start - CONFIG_SYS_MALLOC_LEN - CONFIG_SYS_GBL_DATA_SIZE - 4 - CONFIG_STACKSIZE)
#define FREE_RAM_SIZE (FREE_RAM_END - PHYS_SDRAM_1)
#endif
int g_bUSBWait = 1;
u32 g_dwDownloadLen = 0;
extern int download_run;
extern volatile unsigned int dwUSBBufBase;
extern volatile unsigned int dwUSBBufSize;
extern __u32 usb_receive(char *buf, size_t len, unsigned int wait);
int do_usbslave (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int i;
size_t len = ~0UL;
char buf[32];
/* download_run为1时表示将文件保存在USB Host发送工具dnw指定的位置
* download_run为0时表示将文件保存在参数argv[2]指定的位置
* 要下载程序到内存,然后直接运行时,要设置download_run=1,这也是这个参数名字的来由
*/
download_run = 1;
switch (argc) {
case 1:
{
break;
}
case 2:
{
g_bUSBWait = (int)simple_strtoul(argv[1], NULL, 16);
break;
}
case 3:
{
g_bUSBWait = (int)simple_strtoul(argv[1], NULL, 16);
load_addr = simple_strtoul(argv[2], NULL, 16);
download_run = 0;
break;
}
default:
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
}
dwUSBBufBase = load_addr;
dwUSBBufSize = (FREE_RAM_SIZE&(~(0x80000-1)));
if (g_bUSBWait)
len = FREE_RAM_SIZE;
g_dwDownloadLen = usb_receive(dwUSBBufBase, len, g_bUSBWait);
sprintf(buf, "%X", g_dwDownloadLen);
setenv("filesize", buf);
return 0;
}
U_BOOT_CMD(
usbslave, 3, 0, do_usbslave,
"usbslave - get file from host(PC)\n",
"[wait] [loadAddress]\n"
"\"wait\" is 0 or 1, 0 means for return immediately, not waits for the finish of transferring\n"
);
#endif
打开/common/Makefile,定位到163行,加入下面代码:
# others
COBJS-$(CONFIG_DDR_SPD) += ddr_spd.o
COBJS-$(CONFIG_HWCONFIG) += hwconfig.o
COBJS-$(CONFIG_CONSOLE_MUX) += iomux.o
COBJS-y += flash.o
COBJS-$(CONFIG_CMD_KGDB) += kgdb.o
COBJS-$(CONFIG_KALLSYMS) += kallsyms.o
COBJS-$(CONFIG_LCD) += lcd.o
COBJS-$(CONFIG_LYNXKDI) += lynxkdi.o
COBJS-$(CONFIG_MODEM_SUPPORT) += modem.o
COBJS-$(CONFIG_UPDATE_TFTP) += update.o
COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
COBJS-$(CONFIG_USB_DEVICE) += cmd_usbslave.o
COBJS := $(sort $(COBJS-y))
【9】打开/include/s3c2410.h,定位到198行附近,加入下面代码:
#define BIT_TICK (0x1<<8)
#define BIT_WDT (0x1<<9)
#define BIT_WDT_AC97 (0x1<<9)
#define BIT_TIMER0 (0x1<<10)
#define BIT_TIMER1 (0x1<<11)
【10】编译报错:undefined reference to `udc_disconnect'
打开/lib_arm/bootm.c定位到124行,udc_disconnect ();此句也要注释掉:
/* we assume that the kernel is in place */
printf ("\nStarting kernel ...\n\n");
#ifdef CONFIG_USB_DEVICE
{
extern void udc_disconnect (void);
//udc_disconnect ();
}
#endif
否则编译报错。
【11】解决编译告警问题:
(1)warning: suggest parentheses around arithmetic in operand of '|'
打开/drivers/usb/slave/usbsetup.c,定位到47行附近,需分别在下面表达式中加上括号,修改如下:
// ===================================================================
// All following commands will operate only in case
// - ep0_csr is valid.
// ===================================================================
//warning: suggest parentheses around arithmetic in operand of '|'
#define CLR_EP0_OUT_PKT_RDY() usbdevregs->EP0_CSR_IN_CSR1_REG=(( ep0_csr & (~EP0_WR_BITS ) ) | \
EP0_SERVICED_OUT_PKT_RDY )
#define CLR_EP0_OUTPKTRDY_DATAEND() usbdevregs->EP0_CSR_IN_CSR1_REG=( ( ep0_csr & (~EP0_WR_BITS) ) | \
(EP0_SERVICED_OUT_PKT_RDY|EP0_DATA_END) )
#define SET_EP0_IN_PKT_RDY() usbdevregs->EP0_CSR_IN_CSR1_REG=( ( ep0_csr & (~EP0_WR_BITS ) ) | \
(EP0_IN_PKT_READY) )
#define SET_EP0_INPKTRDY_DATAEND() usbdevregs->EP0_CSR_IN_CSR1_REG=( ( ep0_csr & (~EP0_WR_BITS ) ) | \
(EP0_IN_PKT_READY|EP0_DATA_END) )
#define CLR_EP0_SETUP_END() usbdevregs->EP0_CSR_IN_CSR1_REG=( ( ep0_csr & (~EP0_WR_BITS ) ) | \
(EP0_SERVICED_SETUP_END) )
#define CLR_EP0_SENT_STALL() usbdevregs->EP0_CSR_IN_CSR1_REG=( ep0_csr & (~EP0_WR_BITS)& \
(~EP0_SENT_STALL) )
#define FLUSH_EP0_FIFO() {while(usbdevregs->OUT_FIFO_CNT1_REG)usbdevregs->fifo[0].EP_FIFO_REG;}
打开/drivers/usb/slave/usbin.c,定位到35行附近,修改如下:
// ===================================================================
// All following commands will operate in case
// - in_csr1 is valid.
// ===================================================================
#define SET_EP1_IN_PKT_READY() usbdevregs->EP0_CSR_IN_CSR1_REG= ( ( in_csr1 &(~ EPI_WR_BITS ) ) \
| EPI_IN_PKT_READY )
#define SET_EP1_SEND_STALL() usbdevregs->EP0_CSR_IN_CSR1_REG= ( ( in_csr1 & (~EPI_WR_BITS ) ) \
| EPI_SEND_STALL) )
#define CLR_EP1_SENT_STALL() usbdevregs->EP0_CSR_IN_CSR1_REG= ( in_csr1 & (~EPI_WR_BITS ) \
&(~EPI_SENT_STALL) )
#define FLUSH_EP1_FIFO() usbdevregs->EP0_CSR_IN_CSR1_REG= ( ( in_csr1 & (~EPI_WR_BITS ) ) \
| EPI_FIFO_FLUSH)
打开/drivers/usb/slave/usbinit.c,定位到482行附近,修改如下:
void Clk0_Enable(int clock_sel)
{ // 0:MPLLin, 1:UPLL, 2:FCLK, 3:HCLK, 4:PCLK, 5:DCLK0
gpioregs->MISCCR = ( gpioregs->MISCCR&~(7<<4) ) | (clock_sel<<4);
gpioregs->GPHCON = ( gpioregs->GPHCON&~(3<<18) ) | (2<<18);
}
void Clk1_Enable(int clock_sel)
{ // 0:MPLLout, 1:UPLL, 2:RTC, 3:HCLK, 4:PCLK, 5:DCLK1
gpioregs->MISCCR = ( gpioregs->MISCCR&~(7<<8) ) | (clock_sel<<8);
gpioregs->GPHCON = ( gpioregs->GPHCON&~(3<<20) ) | (2<<20);
}
(2) warning: function declaration isn't a prototype ...
打开/drivers/usb/slave/interrupt.c,定位到113行附近,修改如下:
void IRQ_Handle(void)
(3) warning: implicit declaration of function 'ClearPending_my'
打开/drivers/usb/slave/usbmain.c,定位到27行,加入其引用声明:
extern S3C24X0_USB_DEVICE * usbdevregs;
extern S3C24X0_DMAS * dmaregs;
extern void ClearPending_my(int bit);
打开/drivers/usb/slave/usbout.c,定位到38行,加入其引用声明:
extern S3C24X0_INTERRUPT * intregs;
extern S3C24X0_USB_DEVICE * usbdevregs;
extern S3C24X0_DMAS * dmaregs;
extern void ClearPending_my(int bit);
(4)warning: passing argument 1 of 'usb_receive' makes pointer from integer without a cast
打开/common/cmd_usbslavet.c,分别定位到71行附近,修改如下:
dwUSBBufBase = load_addr;
dwUSBBufSize = (FREE_RAM_SIZE&(~(0x80000-1)));
if (g_bUSBWait)
len = FREE_RAM_SIZE;
g_dwDownloadLen = usb_receive( (char*) dwUSBBufBase, len, g_bUSBWait);
sprintf(buf, "%X", g_dwDownloadLen);
setenv("filesize", buf);
(5)warning:'PrintEpoPkt' defined but not used
打开/drivers/usb/slave/usbout.c,定位到27行,
#if 0
void PrintEpoPkt(U8 *pt,int cnt)
{
int i;
DbgPrintf("[BOUT:%d:",cnt);
for(i=0;i
DbgPrintf("]");
}
#endif
定位到40行附近,将其声明注释掉:
//static void PrintEpoPkt(U8 *pt,int cnt);
static void RdPktEp3_CheckSum(U8 *buf,int num);
warning: 'tempBuf' defined but not used
定位到69行,将其注释掉:
U8 ep3Buf[EP3_PKT_SIZE];
//static U8 tempBuf[64+1];
打开/cpu/arm920t/s3c24x0/interrupts.c,定位到45行附近,修改如下:
void do_irq (struct pt_regs *pt_regs)
{
S3C24X0_INTERRUPT * irq = S3C24X0_GetBase_INTERRUPT();
u_int32_t intpnd = irq->INTPND;
intpnd = intpnd;
}
其它warning: unused variable... ...处理方法相同,这里就不再列出。
8.2,usb slave 下载功能编译测试
[root@localhost u-boot-2009.08]# make distclean
[root@localhost u-boot-2009.08]# make
编译完成后得到u-boot.bin,将开发板断电,拨到nor档上电用 supervivi的a命令下载后在拨到nand档启动:
... ...
source - run script from memory
tftpboot- boot image via network using TFTP protocol
unzip - unzip a memory region
usbslave- usbslave - get file from host(PC)
version - print monitor version
[u-boot@MINI2440]# usbslave
USB host is connected. Waiting a download.
Now, Downloading [ADDRESS:31000000h,TOTAL:2022422]
[u-boot@MINI2440]# bootm 31000000
## Booting kernel from Legacy Image at 31000000 ...
Image Name: mini2440_linux
Created: 2011-05-12 3:37:00 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2022348 Bytes = 1.9 MB
Load Address: 30008000
Entry Point: 30008040
Verifying Checksum ... OK
Loading Kernel Image ... OK
OK
Starting kernel ...
可以看内核在启动。
8.3 开启usb host功能
【1】打开/include/configs/mini2440.h,定位到112行附近:加入下面代码:
/*
* Command line configuration.
*/
#include
#define CONFIG_CMD_ASKENV
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_DATE
#define CONFIG_CMD_ELF
#define CONFIG_CMD_NAND
#define CONFIG_CMD_JFFS2 /* JFFS2 Support*/
#define CONFIG_CMD_PING /*ping command support*/
#define CONFIG_CMD_USB
#define CONFIG_CMD_FAT
#define CONFIG_BOOTDELAY 3
其中相关宏定义的作用:
CONFIG_CMD_USB :使能USB相关命令的支持
CONFIG_CMD_FAT :使能FAT文件系统相关命令的支持
定位到194行附近加入下面代码:
/*
USB device support
*/
#define CONFIG_USB_DEVICE 1
#ifdef CONFIG_USB_DEVICE
#define CONFIG_USE_IRQ 1
#endif
#if 1
#define CONFIG_USB_OHCI
#define CONFIG_USB_STORAGE
#define CONFIG_DOS_PARTITION
#define CONFIG_SYS_DEVICE_DEREGISTER
#define CONFIG_SUPPORT_VFAT
#define LITTLEENDIAN
//#define CONFIG_USB_TTY
//#define CONFIG_USB_KEYBOARD
#endif
相关宏定义的作用:
CONFIG_USB_OHCI :使能USB_OHCI协议的支持
CONFIG_USB_STORAGE:使能USB存储设备的支持
CONFIG_DOS_PARTITION : 使能FAT文件系统分区的支持
CONFIG_SUPPORT_VFAT : 使能FAT32文件系统的支持
LITTLEENDIAN : 定义数据为小端模式
CONFIG_USB_TTY:使能USB终端(本次未使用)
CONFIG_USB_KEYBOARD是对USB键盘的支持(本次未使用)
【2】打开/cpu/arm920t/s3c24x0/usb_ohci.c,定位到43行附近,加入下面代码:
#ifdef CONFIG_USB_OHCI
#if defined(CONFIG_S3C2400)
#include
#elif defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440)
#include
#endif
8.4 usb host 功能编译测试:
【1】先看下USB 操作指令
指令 功能
usb reset 初始化USB 控制器
usb stop [f] 关闭USB 控制器
usb tree 已连接的USB 设备树
usb info [dev] 显示USB 设备[dev]的信息
usb storage 显示已连接的USB 存储设备
usb dev [dev] 显示和设置当前USB 存储设备
usb part [dev] 显示USB 存储设备[dev]的分区信息
usb read addr blk# cnt 读取USB 存储设备数据
【2】准备一个fat32格式的U盘
【3】在编译完成后,nor 档下载nand 档启动,操作如下:
[u-boot@MINI2440]# usb help
USB is stopped. Please issue 'usb start' first.
[u-boot@MINI2440]# usb start
(Re)start USB...
USB: scanning bus for devices... cannot reset port 2!?
2 USB Device(s) found
scanning bus for storage devices... 1 Storage Device(s) found
[u-boot@MINI2440]# usb storage
Device 0: Vendor: USB 2.0 Rev: 5.00 Prod: Flash Drive
Type: Removable Hard Disk
Capacity: 1012.5 MB = 0.9 GB (2073600 x 512)
[u-boot@MINI2440]# usb part 0
print_part of 0
Partition Map for USB device 0 -- Partition Type: DOS
Partition Start Sector Num Sectors Type
1 32 2073568 b
[u-boot@MINI2440]# fatload usb 0:1 0x30008000 uImage_T35
reading uImage_T35
................................................................................
................................................................................
.....................................
2022412 bytes read
[u-boot@MINI2440]# bootm 0x30008000
## Booting kernel from Legacy Image at 30008000 ...
Image Name: mini2440_linux
Created: 2011-05-12 3:37:00 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
可以看到内核开始启动了。
本篇文章来源于 Linux公社网站() 原文链接: