8 usbslave 下载功能实现
网上有很多关于在u-boot中添加usbslave功能的教程,我主要是参照了一位叫tekkamanninja的网友的实现,在u-boot-v2012.04上实现了usbslave下载功能。下面是我移植的步骤:
1) 添加driver/usb/slave目录:
这个目录里的代码是usbslave的驱动具体实现,我是从tekkamanninja的github上下载的代码,将driver/usb/slave里的代码拷贝过来的。由于新u-boot里2440寄存器结构体的变量名全部改成小写了,所以需要将slave目录下关于寄存器的变量全改成小写的。具体代码可以查看我的github目录。
然后再修改顶层Makefile,加入对usbslave驱动的编译:
LIBS += drivers/usb/phy/libusb_phy.o
LIBS += drivers/usb/slave/libusb_slave.o
LIBS += drivers/usb/ulpi/libusb_ulpi.o
LIBS += drivers/video/libvideo.o
2) 修改arch/arm/cpu/arm920t/s3c24x0/interrupts.c,加入arch_interrupt_init
的实现:
void do_irq (struct pt_regs *pt_regs)
{
struct s3c24x0_interrupt *irq = s3c24x0_get_base_interrupt();
readl(&irq->intpnd);
}
int arch_interrupt_init (void)
{
return 0;
}
3) 修改arch/arm/cpu/arm920t/start.S:
#ifdef CONFIG_USE_IRQ
.align5
irq:
/*
get_irq_stack
irq_save_user_regs
bl do_irq
irq_restore_user_regs
*/
sub lr, lr, #4
ldr sp, IRQ_STACK_START
stmdb sp!, {r0-r12, lr}
ldr lr, =int_return
ldr pc, =IRQ_Handle
int_return:
ldmia sp!, {r0-r12, pc}^
.align5
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
4) 修改arch/arm/lib/board.c,在init_board_r函数中加入usbslave的初始化操作:
/* set up exceptions */
interrupt_init();
/* enable exceptions */
enable_interrupts();
#ifdef CONFIG_USB_DEVICE
usb_init_slave();
#endif
5) 修改board/samsung/micro2440/micro2440.c中的gpio初始化部分,设置gpc5引脚为usb_en功能:
/* set up the I/O ports */
writel(0x007FFFFF, &gpio->gpacon);
writel(0x00044555, &gpio->gpbcon);
writel(0x000007FF, &gpio->gpbup);
writel(0xAAAAA6AA, &gpio->gpccon);
writel(0x0000FFFF, &gpio->gpcup);
writel(readl(&gpio->gpcdat)&~(1<<5), &gpio->gpcdat);
writel(0xAAAAAAAA, &gpio->gpdcon);
writel(0x0000FFFF, &gpio->gpdup);
writel(0xAAAAAAAA, &gpio->gpecon);
writel(0x0000FFFF, &gpio->gpeup);
writel(0x000055AA, &gpio->gpfcon);
writel(0x000000FF, &gpio->gpfup);
writel(0xFF95FFBA, &gpio->gpgcon);
writel(0x0000FFFF, &gpio->gpgup);
writel(0x002AFAAA, &gpio->gphcon);
writel(0x000007FF, &gpio->gphup);
6) 加入cmd_usbslave支持:
修改common/Makefile,添加COBJS-$(CONFIG_USB_DEVICE) += cmd_usbslave.o,cmd_usbslave.c的具体实现可以查看我的github.
7) 修改micro2440.h,加入IRQ和usb device的配置:
/* input clock of PLL (the MICRO2440 has 12MHz input clock) */
#define CONFIG_SYS_CLK_FREQ 12000000
//#undef CONFIG_USE_IRQ/* we don't need IRQ/FIQ stuff */
#define CONFIG_CMDLINE_TAG /* enable passing of ATAGs */
…
/************************************************************
* USB support (currently only works with D-cache off)
************************************************************/
#define CONFIG_USB_OHCI
#define CONFIG_USB_KEYBOARD
#define CONFIG_USB_STORAGE
#define CONFIG_DOS_PARTITION
#define CONFIG_USB_DEVICE 1
#ifdef CONFIG_USB_DEVICE
#define CONFIG_USE_IRQ 1
#endif
8) 最后是对头文件s3c24x0.h的修改:
这里需要注意的是新版的u-boot s3c2440的struct s3c24x0_dma的定义是有问题的,我们需要对该结构体的定义针对2440加以修改。我最开始时参照网上的教程移植好usbslave后,发现usb传输的dma中断怎么也收不到,调试了好久才发现的这个问题。
/* DMAS (see manual chapter 8) */
struct s3c24x0_dma {
u32 disrc;
#if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
u32 disrcc;
#endif
u32 didst;
#if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
u32 didstc;
#endif
u32 dcon;
u32 dstat;
u32 dcsrc;
u32 dcdst;
u32 dmasktrig;
#if defined(CONFIG_S3C2400)
u32 res[1];
#endif
#if defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440)
u32 res[7];
#endif
};
…
struct s3c24x0_usb_device {
…
#else /* little endian */
u8 func_addr_reg;
u8 res1[3];
u8 pwr_reg;
u8 res2[3];
u8 ep_int_reg;
u8 res3[15];
u8 usb_int_reg;
u8 res4[3];
u8 ep_int_en_reg;
u8 res5[15];
u8 usb_int_en_reg;
u8 res6[3];
u8 frame_num1_reg;
u8 res7[3];
u8 frame_num2_reg;
u8 res8[3];
u8 index_reg;
u8 res9[7];
u8 maxp_reg;
u8 res10[3];
u8 ep0_csr_in_csr1_reg;
u8 res11[3];
u8 in_csr2_reg;
u8 res12[7];
u8 out_csr1_reg;
u8 res13[3];
u8 out_csr2_reg;
u8 res14[3];
u8 out_fifo_cnt1_reg;
u8 res15[3];
u8 out_fifo_cnt2_reg;
u8 res16[3];
#endif /* __BIG_ENDIAN */
u32 res17[8];
struct s3c24x0_usb_dev_fifos fifo[5];
u32 res18[11];
//struct s3c24x0_usb_dev_dmas dma[5];
struct s3c24x0_usb_dev_dmas ep1;
struct s3c24x0_usb_dev_dmas ep2;
u8 res19[16];
struct s3c24x0_usb_dev_dmas ep3;
struct s3c24x0_usb_dev_dmas ep4;
};