Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2122694
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: LINUX

2012-09-11 14:35:44

以前做过usb下载的东东,现在把它搞到u-boot-2010.06-rc1上去.
网上有usb下载的代码,可以在这儿下载:
一. 先编译过再说
1.下载后,解压到u-boot-2010.06-rc1/drivers/usb/slave目录
并在顶层Makefile中添加: LIBS += drivers/usb/slave/libusb_slave.a
2. 将driver/usb/slave/目录下所有C文件所个替换
  1. a. 
  2. #if defined(CONFIG_S3C2400)
  3. #include <s3c2400.h>
  4. #elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
  5. #include <s3c2410.h>
  6. #endif
  7. #include
  8. 替换为
  9. #include
  10. b. 删除driver/usb/slave/interrupt.c
  11. c. 修改driver/usb/slave/Makefile中的 COBJS, 去掉interrupt.o
3.u-boot-2010.06-rc1中结构体都是小写,跟下载的代码中结构体名字是大写的,需要将大写的名字改成小写的,这样才可以编译过去.
  1. a. 将usbin.c中
  2. L21
  3.     /*
  4.     extern S3C24X0_USB_DEVICE * usbdevregs;
  5.     extern S3C24X0_DMAS * dmaregs;
  6.     */
  7.     extern struct s3c24x0_usb_device * usbdevregs;
  8.     extern struct s3c24x0_dmas * dmaregs;
  9. L32 解决: warning: suggest parentheses around arithmetic in operand of |

  10.  #define SET_EP1_IN_PKT_READY()  usbdevregs->EP0_CSR_IN_CSR1_REG= ( (in_csr1 &(~ EPI_WR_BITS)) \
  11.          | EPI_IN_PKT_READY )
  12.  #define SET_EP1_SEND_STALL()    usbdevregs->EP0_CSR_IN_CSR1_REG= ( (in_csr1 & (~EPI_WR_BITS))\
  13.          | EPI_SEND_STALL) )
  14.  #define CLR_EP1_SENT_STALL()    usbdevregs->EP0_CSR_IN_CSR1_REG= ( (in_csr1 & (~EPI_WR_BITS))\
  15.           &(~EPI_SENT_STALL) )
  16.  #define FLUSH_EP1_FIFO()    usbdevregs->EP0_CSR_IN_CSR1_REG= ( (in_csr1 & (~EPI_WR_BITS))\
  17.           |(EPI_FIFO_FLUSH) )
  18. b. 将usblib.c中
  19. L23
  20.     /*
  21.     extern S3C24X0_INTERRUPT * intregs;
  22.     extern S3C24X0_USB_DEVICE * usbdevregs;
  23.     extern S3C24X0_DMAS * dmaregs;
  24.     */
  25.     extern struct s3c24x0_interrupt * intregs;
  26.     extern struct s3c24x0_usb_device *usbdevregs;
  27.     extern struct s3c24x0_dmas * dmaregs;
  28. c. usbinit.c 中
  29. L22
  30.     /*
  31.     extern S3C24X0_INTERRUPT * intregs;
  32.     S3C24X0_USB_DEVICE * usbdevregs;
  33.     S3C24X0_DMAS * dmaregs;
  34.     S3C24X0_CLOCK_POWER * clk_powerregs;
  35.     S3C24X0_GPIO * gpioregs;
  36.     */
  37.     extern struct s3c24x0_interrupt * intregs;
  38.     struct s3c24x0_usb_device * usbdevregs;
  39.     struct s3c24x0_dmas * dmaregs;
  40.     struct s3c24x0_clock_power * clk_powerregs;
  41.     struct s3c24x0_gpio * gpioregs;
  42. L122:
  43.     //gpioregs = S3C24X0_GetBase_GPIO();
  44.     gpioregs = s3c24x0_get_base_gpio();
  45. L222
  46.     /*
  47.     clk_powerregs = S3C24X0_GetBase_CLOCK_POWER();
  48.     usbdevregs = S3C24X0_GetBase_USB_DEVICE();
  49.     dmaregs = S3C24X0_GetBase_DMAS();
  50.     */
  51.     clk_powerregs = s3c24x0_get_base_clock_power();
  52.     usbdevregs = s3c24x0_get_base_usb_device();
  53.     dmaregs = s3c24x0_get_base_dmas();

  54. L297
  55.     //S3C24X0_INTERRUPT * intregs;
  56.     struct s3c24x0_interrupt * intregs;

  57.     //intregs = S3C24X0_GetBase_INTERRUPT();
  58.     intregs = s3c24x0_get_base_interrupt();
  59. d. usbmain.c 中
  60. L20
  61.     /*
  62.     extern S3C24X0_USB_DEVICE * usbdevregs;
  63.     extern S3C24X0_DMAS * dmaregs;
  64.     */
  65.     extern struct s3c24x0_usb_device * usbdevregs;
  66.     extern struct s3c24x0_dmas * dmaregs;
  67. L444 解决: warning: suggest parentheses around arithmetic in operand of |

  68. 444     gpioregs->MISCCR = (gpioregs->MISCCR&~(7<<4)) | (clock_sel<<4);
  69. 445     gpioregs->GPHCON = (gpioregs->GPHCON&~(3<<18)) | (2<<18);
  70. e. usbout.c中
  71. L28
  72.     /*
  73.     extern S3C24X0_INTERRUPT * intregs;
  74.     extern S3C24X0_USB_DEVICE * usbdevregs;
  75.     extern S3C24X0_DMAS * dmaregs;
  76.     */
  77.     extern struct s3c24x0_interrupt * intregs;
  78.     extern struct s3c24x0_usb_device * usbdevregs;
  79.     extern struct s3c24x0_dmas * dmaregs;
  80. L188
  81.     //ClearPending_my(BIT_DMA2);
  82.    ClearPending(BIT_DMA2);
  83. f. usbsetup.c中
  84. L19
  85.     /*
  86.     extern S3C24X0_INTERRUPT * intregs;
  87.     extern S3C24X0_USB_DEVICE * usbdevregs;
  88.     extern S3C24X0_DMAS * dmaregs;
  89.     */
  90.     extern struct s3c24x0_interrupt * intregs;
  91.     extern struct s3c24x0_usb_device * usbdevregs;
  92.     extern struct s3c24x0_dmas * dmaregs;
  93. L46 解决: warning: suggest parentheses around arithmetic in operand of |

  94. #define CLR_EP0_OUT_PKT_RDY()       usbdevregs->EP0_CSR_IN_CSR1_REG=( (ep0_csr & (~EP0_WR_BITS))| \
  95.         EP0_SERVICED_OUT_PKT_RDY )
  96. #define CLR_EP0_OUTPKTRDY_DATAEND()     usbdevregs->EP0_CSR_IN_CSR1_REG=( (ep0_csr & (~EP0_WR_BITS) )| \
  97.         (EP0_SERVICED_OUT_PKT_RDY|EP0_DATA_END) )

  98. #define SET_EP0_IN_PKT_RDY()        usbdevregs->EP0_CSR_IN_CSR1_REG=( (ep0_csr & (~EP0_WR_BITS) ) | \
  99.         (EP0_IN_PKT_READY) )
  100. #define SET_EP0_INPKTRDY_DATAEND()  usbdevregs->EP0_CSR_IN_CSR1_REG=( (ep0_csr & (~EP0_WR_BITS))| \
  101.         (EP0_IN_PKT_READY|EP0_DATA_END) )

  102. #define CLR_EP0_SETUP_END()         usbdevregs->EP0_CSR_IN_CSR1_REG=( (ep0_csr & (~EP0_WR_BITS)) | \
  103.         (EP0_SERVICED_SETUP_END) )

  104. #define CLR_EP0_SENT_STALL()        usbdevregs->EP0_CSR_IN_CSR1_REG=( (ep0_csr & (~EP0_WR_BITS) )& \
  105.         (~EP0_SENT_STALL) )

  106. #define FLUSH_EP0_FIFO()        {while(usbdevregs->OUT_FIFO_CNT1_REG)usbdevregs->fifo[0].EP_FIFO_REG;}
4.arch/arm/include/asm/arch/s3c24x0.h中
  1. a. 添加两个宏定义
  2.     #define BIT_DMA2 (0x1<<19)
  3.     #define BIT_USBD (0x1<<25)

  4. b. 修改s3c24x0_usb_device结构体
  5.     //u8 res10[7]
  6.     u8 res10[3];
  7.     //u8 res12[3]
  8.     u8 res12[7];
  9.     //u8 res13[7]
  10.     u8 res13[3];
  11.     /*
  12.     struct s3c24x0_usb_dev_fifos fifo[5];
  13.     struct s3c24x0_usb_dev_dmas dma[5];
  14.     */
  15.     u32 res17[8];
  16.     struct s3c24x0_usb_dev_fifos fifo[5];
  17.     u32 res18[11];
  18.     struct s3c24x0_usb_dev_dmas ep1;
  19.     struct s3c24x0_usb_dev_dmas ep2;
  20.     u8 res19[16];
  21.     struct s3c24x0_usb_dev_dmas ep3;
  22.     struct s3c24x0_usb_dev_dmas ep4;

  23. c. 修改 struct s3c24x0_gpio
  24. L481 添加:
  25.     /* s3c2440 */
  26.     u32 res9[4];
  27.     u32 GPJCON;
  28.     u32 GPJDAT;
  29.     u32 GPJUP;
5. usbmain.c中void IsrUsbd(void)调用了ClearPending,其实现如下:
  1. arch/arm/cpu/arm920t/interrupt.c
  2. //添加 ClearPending的实现:
  3. void ClearPending(int bit)
  4. {
  5.     intregs->SRCPND = bit;
  6.     intregs->INTPND = bit;
  7. }
  8. 并修改driver/usb/slave/usbmain.c
  9.  //ClearPending_my(BIT_USBD);
  10.  ClearPending(BIT_USBD);
6. usbmain.c的usb_init_slave(void)调用了Isr_Init(),其实现如下
arch/arm/cpu/arm920t/interrupt.c中添加
  1. #include <asm/arch/s3c24x0_cpu.h>

  2. struct s3c24x0_interrupt * intregs;
  3. void (*isr_handle_array[50])(void);
  4. extern void IsrUsbd(void);
  5. extern void IsrDma2(void);
  6. void Dummy_isr(void)
  7. {
  8.     printf("Dummy_isr error, interrupt number: %d, INTMSK = 0x%x\n", intregs->INTOFFSET, intregs->INTMSK);
  9.     while(1);
  10. }
  11. //初始化irq的中断向量表
  12. void Isr_Init(void)
  13. {
  14.     int i = 0;
  15.     intregs = s3c24x0_get_base_interrupt();

  16.     for (i = 0; i < sizeof(isr_handle_array) / sizeof(isr_handle_array[0]); i++ )
  17.     {
  18.         isr_handle_array[i] = Dummy_isr;
  19.     }

  20.     intregs->INTMOD=0x0;     // All=IRQ mode
  21.     intregs->INTMSK=BIT_ALLMSK;     // All interrupt is masked.

  22. #ifdef CONFIG_USB_DEVICE
  23.     isr_handle_array[ISR_USBD_OFT] = IsrUsbd;
  24.     isr_handle_array[ISR_DMA2_OFT] = IsrDma2;
  25.     ClearPending(BIT_DMA2);
  26.     ClearPending(BIT_USBD);
  27. #endif
  28. }
  29. b. 同时在 arch/arm/include/asm/arch/s3c24x0.h中添加

  30. #define ISR_DMA2_OFT      19
  31. #define ISR_USBD_OFT      25
  32.  
  33. c. 并在 include/configs/smdk2410.h 中添加
  34.  #define CONFIG_USB_DEVICE 1
  35. d. arch/arm/lib/bootm.c中,注掉udc_disconnect,否则编译不过

  36. #ifdef CONFIG_USB_DEVICE
  37. {
  38. extern void udc_disconnect (void);
  39. //udc_disconnect ();
  40. }
  41. #endif
7. 开启中断
start_armboot --> 调用enable_interrupts ();
在include/configs/smdk2410.h 中添加 
  1. //#undef CONFIG_USE_IRQ            /* we don't need IRQ/FIQ stuff */
  2. #define CONFIG_USE_IRQ    1
这会导致arch/arm/cpu/arm920t/s3c24x0/interrupt.c 因为缺少readl而出错
同时报错说没有arch_interrupt_init的定义
在arch/arm/cpu/arm920t/s3c24x0/interrupt.c 中添加
  1. #include <asm/io.h>

  2. int arch_interrupt_init(void)
  3. {
  4.     return (0);
  5. }
8.还要在arch/arm/lib/board.c中添加
  1. /* enable exceptions */
  2. enable_interrupts ();

  3. //调用usb 初始化函数
  4. usb_init_slave();
10. 还编译不过,需要在arch/arm/cpu/arm920t/interrupt.c中添加
  1. static int intCount;

  2. void Timer_InitEx(void)
  3. {
  4.     intCount=0;
  5.     intregs->SUBSRCPND    = (1<<13);
  6.     ClearPending(BIT_WDT_AC97/*BIT_WDT*/);
  7.     intregs->INTMSK&=~(BIT_WDT_AC97 /*BIT_WDT*/);
  8.     intregs->INTSUBMSK &= ~(1<<13);
  9. }

  10. void Timer_StartEx(void)
  11. {
  12.     //S3C24X0_WATCHDOG * const wdtregs = S3C24X0_GetBase_WATCHDOG();
  13.     struct s3c24x0_watchdog * const wdtregs = s3c24x0_get_base_watchdog();
  14.     wdtregs->WTCON=((get_PCLK()/1000000-1)<<8)|(0<<3)|(1<<2);    // 16us
  15.     wdtregs->WTDAT=0xffff;
  16.     wdtregs->WTCNT=0xffff;

  17.     // 1/16/(65+1),interrupt enable,reset disable,watchdog enable
  18.     wdtregs->WTCON=((get_PCLK()/1000000-1)<<8)|(0<<3)|(1<<2)|(0<<0)|(1<<5);
  19. }
  20. unsigned int Timer_StopEx(void)
  21. {
  22.     int count;
  23.     //S3C24X0_WATCHDOG * const wdtregs = S3C24X0_GetBase_WATCHDOG();
  24.     struct s3c24x0_watchdog * const wdtregs = s3c24x0_get_base_watchdog();

  25.     wdtregs->WTCON=((get_PCLK()/1000000-1)<<8);
  26.     intregs->INTMSK|=BIT_WDT_AC97; //BIT_WDT;
  27.     intregs->INTSUBMSK |= (1<<13);

  28.     count=(0xffff-wdtregs->WTCNT)+(intCount*0xffff);
  29.     return ((unsigned int)count*16/1000000);
  30. }
11. 加入usbslave命令
Common/Makefile中
  1. 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
  1. irq:
  2. /*
  3.     get_irq_stack
  4.     irq_save_user_regs
  5.     bl    do_irq
  6.     irq_restore_user_regs
  7. */

  8.     sub lr, lr, #4                    @ the return address
  9.     /*@在完成保存堆栈的操作后,跳到中断处理函数IRQ_Handle中*/
  10.     ldr sp, IRQ_STACK_START         @ the stack for irq
  11.     stmdb        { r0-r12,lr }    @ save registers

  12.     ldr lr, =int_return             @ set the return addr
  13.     ldr pc, =IRQ_Handle             @ call the isr
  14. int_return:
  15.     ldmia        { r0-r12,pc }^    @ return from interrupt
arch/arm/cpu/arm920t/interrupt.c //irq的中断服务程序
  1. void IRQ_Handle()
  2. {
  3.     unsigned long oft = intregs->INTOFFSET;
  4.     //S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
  5.     struct s3c24x0_gpio *const gpio = s3c24x0_get_base_gpio();

  6.     //清中断
  7.     if( oft == 4 ) gpio->EINTPEND = 1<<7;        //EINT4-7合用IRQ4,注意EINTPEND[3:0]保留未用,向这些位写入1可能导致未知结果
  8.     intregs->SRCPND = 1<<oft;
  9.     intregs->INTPND    = intregs->INTPND;

  10.     /* run the isr */
  11.     isr_handle_array[oft]();
  12. }
在Isr_init()中    
   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中断.
  1. /* enable IRQ interrupts */
  2. void enable_interrupts (void)
  3. {
  4.     unsigned long temp;
  5.     __asm__ __volatile__("mrs %0, cpsr\n"
  6.              "bic %0, %0, #0x80\n"
  7.              "msr cpsr_c, %0"
  8.              : "=r" (temp)
  9.              :
  10.              : "memory");
  11. }
当调用enable_interrupts函数之后,irq中断这条路就己经通了,当有usb中断发生时就会进入自己写的usb中断服务程序.

二.调试
2.1 当编译好之后,下载到板子上运行,usb设备枚举正常,但在下载时出现问题
  1. SMDK2410 # usbslave 1 0x30000000
  2. USB host is connected. Waiting a download.

  3. Now, Downloading [ADDRESS:30000000h,TOTAL:1942578]
  4. RECEIVED FILE SIZE: 65536Dummy_isr error, interrupt number: 9, INTMSK = 0xfff7fdff
2.2 加入watchdog和timer中断
  1. int g_TimerIntHappen;
  2. static int intCount;
  3. void IsrTimer4(void)
  4. {
  5.    ClearPending(BIT_TIMER4);
  6.    *(volatile int *)&g_TimerIntHappen = 1;
  7. }


  8. void Dummy_isr(void)
  9. {
  10. printf("Dummy_isr error, interrupt number: %d, INTMSK = 0x%x\n", intregs->INTOFFSET, intregs->INTMSK);
  11. while(1);
  12. }
  13. void Isr_Init(void) //加入中断处理函数
  14. {
  15.    isr_handle_array[ISR_TIMER4_OFT] = IsrTimer4;  
  16.    isr_handle_array[ISR_WDT_OFT] = IsrWatchdog;
    }
[参考文章]http://singleboy.blog.163.com/blog/static/549001942011417917635/
阅读(2758) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~