Chinaunix首页 | 论坛 | 博客
  • 博客访问: 82770
  • 博文数量: 28
  • 博客积分: 65
  • 博客等级: 民兵
  • 技术积分: 115
  • 用 户 组: 普通用户
  • 注册时间: 2012-08-04 11:06
文章分类

全部博文(28)

文章存档

2014年(22)

2013年(5)

2012年(1)

我的朋友

分类: 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("%x,",pt[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公社网站()  原文链接:

阅读(1370) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~