以前做过usb下载的东东,现在把它搞到u-boot-2010.06-rc1上去.
3.u-boot-2010.06-rc1中结构体都是小写,跟下载的代码中结构体名字是大写的,需要将大写的名字改成小写的,这样才可以编译过去.
4.arch/arm/include/asm/arch/s3c24x0.h中
5. usbmain.c中void IsrUsbd(void)调用了ClearPending,其实现如下:
6. usbmain.c的usb_init_slave(void)调用了Isr_Init(),其实现如下
这会导致arch/arm/cpu/arm920t/s3c24x0/interrupt.c 因为缺少readl而出错
8.还要在arch/arm/lib/board.c中添加
10. 还编译不过,需要在arch/arm/cpu/arm920t/interrupt.c中添加
11. 加入usbslave命令
当调用enable_interrupts函数之后,irq中断这条路就己经通了,当有usb中断发生时就会进入自己写的usb中断服务程序.
2.2 加入watchdog和timer中断
[参考文章]
http://singleboy.blog.163.com/blog/static/549001942011417917635/
网上有usb下载的代码,可以在这儿下载:
一. 先编译过再说
1.下载后,解压到u-boot-2010.06-rc1/drivers/usb/slave目录
并在顶层Makefile中添加:
LIBS += drivers/usb/slave/libusb_slave.a
2. 将driver/usb/slave/目录下所有C文件所个替换
- a.
- #if defined(CONFIG_S3C2400)
- #include <s3c2400.h>
- #elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
- #include <s3c2410.h>
- #endif
- #include
- 替换为
- #include
- b. 删除driver/usb/slave/interrupt.c
- c. 修改driver/usb/slave/Makefile中的 COBJS, 去掉interrupt.o
- a. 将usbin.c中
- L21
- /*
- extern S3C24X0_USB_DEVICE * usbdevregs;
- extern S3C24X0_DMAS * dmaregs;
- */
- extern struct s3c24x0_usb_device * usbdevregs;
- extern struct s3c24x0_dmas * dmaregs;
- L32 解决: warning: suggest parentheses around arithmetic in operand of |
-
- #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) )
- b. 将usblib.c中
- L23
- /*
- extern S3C24X0_INTERRUPT * intregs;
- extern S3C24X0_USB_DEVICE * usbdevregs;
- extern S3C24X0_DMAS * dmaregs;
- */
- extern struct s3c24x0_interrupt * intregs;
- extern struct s3c24x0_usb_device *usbdevregs;
- extern struct s3c24x0_dmas * dmaregs;
- c. usbinit.c 中
- L22
- /*
- extern S3C24X0_INTERRUPT * intregs;
- S3C24X0_USB_DEVICE * usbdevregs;
- S3C24X0_DMAS * dmaregs;
- S3C24X0_CLOCK_POWER * clk_powerregs;
- S3C24X0_GPIO * gpioregs;
- */
- extern struct s3c24x0_interrupt * intregs;
- struct s3c24x0_usb_device * usbdevregs;
- struct s3c24x0_dmas * dmaregs;
- struct s3c24x0_clock_power * clk_powerregs;
- struct s3c24x0_gpio * gpioregs;
- L122:
- //gpioregs = S3C24X0_GetBase_GPIO();
- gpioregs = s3c24x0_get_base_gpio();
- L222
- /*
- clk_powerregs = S3C24X0_GetBase_CLOCK_POWER();
- usbdevregs = S3C24X0_GetBase_USB_DEVICE();
- dmaregs = S3C24X0_GetBase_DMAS();
- */
- clk_powerregs = s3c24x0_get_base_clock_power();
- usbdevregs = s3c24x0_get_base_usb_device();
- dmaregs = s3c24x0_get_base_dmas();
-
- L297
- //S3C24X0_INTERRUPT * intregs;
- struct s3c24x0_interrupt * intregs;
-
- //intregs = S3C24X0_GetBase_INTERRUPT();
- intregs = s3c24x0_get_base_interrupt();
- d. usbmain.c 中
- L20
- /*
- extern S3C24X0_USB_DEVICE * usbdevregs;
- extern S3C24X0_DMAS * dmaregs;
- */
- extern struct s3c24x0_usb_device * usbdevregs;
- extern struct s3c24x0_dmas * dmaregs;
- L444 解决: warning: suggest parentheses around arithmetic in operand of |
-
- 444 gpioregs->MISCCR = (gpioregs->MISCCR&~(7<<4)) | (clock_sel<<4);
- 445 gpioregs->GPHCON = (gpioregs->GPHCON&~(3<<18)) | (2<<18);
- e. usbout.c中
- L28
- /*
- extern S3C24X0_INTERRUPT * intregs;
- extern S3C24X0_USB_DEVICE * usbdevregs;
- extern S3C24X0_DMAS * dmaregs;
- */
- extern struct s3c24x0_interrupt * intregs;
- extern struct s3c24x0_usb_device * usbdevregs;
- extern struct s3c24x0_dmas * dmaregs;
- L188
- //ClearPending_my(BIT_DMA2);
- ClearPending(BIT_DMA2);
- f. usbsetup.c中
- L19
- /*
- extern S3C24X0_INTERRUPT * intregs;
- extern S3C24X0_USB_DEVICE * usbdevregs;
- extern S3C24X0_DMAS * dmaregs;
- */
- extern struct s3c24x0_interrupt * intregs;
- extern struct s3c24x0_usb_device * usbdevregs;
- extern struct s3c24x0_dmas * dmaregs;
- L46 解决: 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;}
- a. 添加两个宏定义
- #define BIT_DMA2 (0x1<<19)
- #define BIT_USBD (0x1<<25)
-
- b. 修改s3c24x0_usb_device结构体
- //u8 res10[7]
- u8 res10[3];
- //u8 res12[3]
- u8 res12[7];
- //u8 res13[7]
- u8 res13[3];
- /*
- struct s3c24x0_usb_dev_fifos fifo[5];
- struct s3c24x0_usb_dev_dmas dma[5];
- */
- u32 res17[8];
- struct s3c24x0_usb_dev_fifos fifo[5];
- u32 res18[11];
- 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;
-
- c. 修改 struct s3c24x0_gpio
- L481 添加:
- /* s3c2440 */
- u32 res9[4];
- u32 GPJCON;
- u32 GPJDAT;
- u32 GPJUP;
- arch/arm/cpu/arm920t/interrupt.c
- //添加 ClearPending的实现:
- void ClearPending(int bit)
- {
- intregs->SRCPND = bit;
- intregs->INTPND = bit;
- }
- 并修改driver/usb/slave/usbmain.c
- //ClearPending_my(BIT_USBD);
- ClearPending(BIT_USBD);
arch/arm/cpu/arm920t/interrupt.c中添加
- #include <asm/arch/s3c24x0_cpu.h>
-
- struct s3c24x0_interrupt * intregs;
- void (*isr_handle_array[50])(void);
- extern void IsrUsbd(void);
- extern void IsrDma2(void);
- void Dummy_isr(void)
- {
- printf("Dummy_isr error, interrupt number: %d, INTMSK = 0x%x\n", intregs->INTOFFSET, intregs->INTMSK);
- while(1);
- }
- //初始化irq的中断向量表
- void Isr_Init(void)
- {
- int i = 0;
- intregs = s3c24x0_get_base_interrupt();
-
- for (i = 0; i < sizeof(isr_handle_array) / sizeof(isr_handle_array[0]); i++ )
- {
- isr_handle_array[i] = Dummy_isr;
- }
-
- intregs->INTMOD=0x0; // All=IRQ mode
- intregs->INTMSK=BIT_ALLMSK; // All interrupt is masked.
-
- #ifdef CONFIG_USB_DEVICE
- isr_handle_array[ISR_USBD_OFT] = IsrUsbd;
- isr_handle_array[ISR_DMA2_OFT] = IsrDma2;
- ClearPending(BIT_DMA2);
- ClearPending(BIT_USBD);
- #endif
- }
- b. 同时在 arch/arm/include/asm/arch/s3c24x0.h中添加
-
- #define ISR_DMA2_OFT 19
- #define ISR_USBD_OFT 25
- c. 并在 include/configs/smdk2410.h 中添加
- #define CONFIG_USB_DEVICE 1
- d. arch/arm/lib/bootm.c中,注掉udc_disconnect,否则编译不过
-
- #ifdef CONFIG_USB_DEVICE
- {
- extern void udc_disconnect (void);
- //udc_disconnect ();
- }
- #endif
7. 开启中断
start_armboot --> 调用enable_interrupts ();
在include/configs/smdk2410.h 中添加
- //#undef CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
- #define CONFIG_USE_IRQ 1
同时报错说没有arch_interrupt_init的定义
在arch/arm/cpu/arm920t/s3c24x0/interrupt.c 中添加
- #include <asm/io.h>
-
- int arch_interrupt_init(void)
- {
- return (0);
- }
- /* enable exceptions */
- enable_interrupts ();
-
- //调用usb 初始化函数
- usb_init_slave();
- static int intCount;
-
- void Timer_InitEx(void)
- {
- intCount=0;
- intregs->SUBSRCPND = (1<<13);
- ClearPending(BIT_WDT_AC97/*BIT_WDT*/);
- intregs->INTMSK&=~(BIT_WDT_AC97 /*BIT_WDT*/);
- intregs->INTSUBMSK &= ~(1<<13);
- }
-
- void Timer_StartEx(void)
- {
- //S3C24X0_WATCHDOG * const wdtregs = S3C24X0_GetBase_WATCHDOG();
- struct s3c24x0_watchdog * const wdtregs = s3c24x0_get_base_watchdog();
- wdtregs->WTCON=((get_PCLK()/1000000-1)<<8)|(0<<3)|(1<<2); // 16us
- wdtregs->WTDAT=0xffff;
- wdtregs->WTCNT=0xffff;
-
- // 1/16/(65+1),interrupt enable,reset disable,watchdog enable
- wdtregs->WTCON=((get_PCLK()/1000000-1)<<8)|(0<<3)|(1<<2)|(0<<0)|(1<<5);
- }
- unsigned int Timer_StopEx(void)
- {
- int count;
- //S3C24X0_WATCHDOG * const wdtregs = S3C24X0_GetBase_WATCHDOG();
- struct s3c24x0_watchdog * const wdtregs = s3c24x0_get_base_watchdog();
-
- wdtregs->WTCON=((get_PCLK()/1000000-1)<<8);
- intregs->INTMSK|=BIT_WDT_AC97; //BIT_WDT;
- intregs->INTSUBMSK |= (1<<13);
-
- count=(0xffff-wdtregs->WTCNT)+(intCount*0xffff);
- return ((unsigned int)count*16/1000000);
- }
Common/Makefile中
- COBJS-$(CONFIG_USB_DEVICE) += usb_storage.o
common/cmd_usbslave.c
cmd_usbslave.c.txt (改名为: cmd_usbslave.c, 放在common/目录下)
12 打通中断的路
arch/arm/cpu/arm920t/start.S
L399
arch/arm/cpu/arm920t/interrupt.c //
irq的中断服务程序
在Isr_init()中
- irq:
- /*
- get_irq_stack
- irq_save_user_regs
- bl do_irq
- irq_restore_user_regs
- */
-
- sub lr, lr, #4 @ the return address
- /*@在完成保存堆栈的操作后,跳到中断处理函数IRQ_Handle中*/
- ldr sp, IRQ_STACK_START @ the stack for irq
- stmdb { r0-r12,lr } @ save registers
-
- ldr lr, =int_return @ set the return addr
- ldr pc, =IRQ_Handle @ call the isr
- int_return:
- ldmia { r0-r12,pc }^ @ return from interrupt
- void IRQ_Handle()
- {
- unsigned long oft = intregs->INTOFFSET;
- //S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
- struct s3c24x0_gpio *const gpio = s3c24x0_get_base_gpio();
-
- //清中断
- if( oft == 4 ) gpio->EINTPEND = 1<<7; //EINT4-7合用IRQ4,注意EINTPEND[3:0]保留未用,向这些位写入1可能导致未知结果
- intregs->SRCPND = 1<<oft;
- intregs->INTPND = intregs->INTPND;
-
- /* run the isr */
- isr_handle_array[oft]();
- }
isr_handle_array[ISR_USBD_OFT] = IsrUsbd;
isr_handle_array[ISR_DMA2_OFT] = IsrDma2;
所以当有usb中断时,就会调用IsrUsbd()函数.
13. 最关键的一步, 打开irq中断,重启复位时默认进入0xD3模式,并不开启irq中断,
在start_armboot中完成Port_init之后就要打开irq中断.
- /* enable IRQ interrupts */
- void enable_interrupts (void)
- {
- unsigned long temp;
- __asm__ __volatile__("mrs %0, cpsr\n"
- "bic %0, %0, #0x80\n"
- "msr cpsr_c, %0"
- : "=r" (temp)
- :
- : "memory");
- }
二.调试
2.1 当编译好之后,下载到板子上运行,usb设备枚举正常,但在下载时出现问题
- SMDK2410 # usbslave 1 0x30000000
- USB host is connected. Waiting a download.
-
- Now, Downloading [ADDRESS:30000000h,TOTAL:1942578]
- RECEIVED FILE SIZE: 65536Dummy_isr error, interrupt number: 9, INTMSK = 0xfff7fdff
- int g_TimerIntHappen;
- static int intCount;
- void IsrTimer4(void)
- {
- ClearPending(BIT_TIMER4);
- *(volatile int *)&g_TimerIntHappen = 1;
- }
-
-
- void Dummy_isr(void)
- {
- printf("Dummy_isr error, interrupt number: %d, INTMSK = 0x%x\n", intregs->INTOFFSET, intregs->INTMSK);
- while(1);
- }
- void Isr_Init(void) //加入中断处理函数
- {
- isr_handle_array[ISR_TIMER4_OFT] = IsrTimer4;
- isr_handle_array[ISR_WDT_OFT] = IsrWatchdog;
}