bootloader---19.usb下载之设备枚举

原创 2016年08月29日 13:58:56
    在实现了读取内核并引导内核之后,下一步要实现的功能是内核下载。内核下载可以通过网络和usb下载,正好最近学习了usb的一些东东,现在就把usb下载的功能加入到myboot中,这样myboot看起来就像是那么回事了,呵呵。
    usb主机要与usb设备进行通信,这儿要完成的是usb设备部分,那么usb主机部分肿么办呢?windows下的dnw没有代码的,而且还老蓝屏,但是linux下有基于libusb的源程序(dnw2)。 usb主机部分临时先用这个代码,等把usb设备完成之后,再自己动手写一下这个dnw2的代码,这样上下位机咱就都会了。
    下面说一下思路,usb 设备部分主要实现如下功能:
1.实现usb的枚举
   a. 以前代码中没有用到中断,所以这儿要实现中断
       a.1 建立arm的中断向量表 (start.S中添加)
当发生 irq中断时,mcu跳到中断向量表的irq入口处,执行ldr pc, _irq命令。
因为定义了 _irq: .word irq, 所以程序跳到irq函数去执行。

点击(此处)折叠或打开

  1. _start:
  2.     b reset
  3.     ldr pc, _undefined_instruction
  4.     ldr pc, _software_interrupt
  5.     ldr pc, _prefetch_abort
  6.     ldr pc, _data_abort 
  7.     ldr pc, _not_used
  8.     ldr pc, _irq
  9.     ldr pc, _fiq

  10. _undefined_instruction:
  11.     .word undefined_instruction
  12. _software_interrupt:
  13.     .word software_interrupt
  14. _prefetch_abort:
  15.     .word prefetch_abort
  16. _data_abort:
  17.     .word data_abort
  18. _not_used:
  19.     .word not_used
  20. _irq:
  21.     .word irq
  22. _fiq:
  23.     .word fiq
       a.2 arm的中断服务程序,这儿只用到了irq (start.S中添加)

点击(此处)折叠或打开

  1. undefined_instruction:
  2.     nop
  3. software_interrupt:
  4.     nop
  5. prefetch_abort:
  6.     nop
  7. data_abort:
  8.     nop
  9. not_used:
  10. nop

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

  15.     ldr lr, =int_return  set the return addr
  16.     ldr pc, =irq_handle  call the isr
  17. int_return:
  18.     ldmia { r0-r12,pc }^  @ return from interrupt

  19. fiq:
  20. nop

  21. .globl IRQ_STACK_START
  22. IRQ_STACK_START:
  23.     .word 0x33FF7000
      a.3 irq的中断服务程序

点击(此处)折叠或打开

  1. void (*isr_handle_array[50])(void);
  2. void irq_handle(void)
  3. {
  4.     unsigned long oft = INTOFFSET; 
  5.     SRCPND = 1<<oft;
  6.     INTPND = 1<<oft;
  7.     (isr_handle_array[oft])();
  8.     return ;
  9. }
      a.4 初始化irq的中断向量表

点击(此处)折叠或打开

  1. //这里只用usb中断和dma2
  2. void Isr_Init(void)
  3. {
  4.     u32 i = 0;
  5.     for(i=0; i<sizeof(isr_handle_array); i++)
  6.     {
  7.         isr_handle_array[i] = Dummy_isr;
  8.     }
  9.     
  10.     //将所有中断设为IRQ模式,并屏闭所有中断
  11.     INTMOD = 0x0; 
  12.     INTMSK = BIT_ALLMSK;

  13.     isr_handle_array[ISR_USBD_OFT] = IsrUsbd;
  14.     isr_handle_array[ISR_DMA2_OFT] = IsrDma2;

  15.     ClearPending(BIT_DMA2);
  16.     ClearPending(BIT_USBD);
  17.     return ;
  18. }
     a.5 最关键的一步,打开irq中断,重启复位时默认进入0xd3模式,并不开启irq中断。

点击(此处)折叠或打开

  1. 开启irq中断
  2. void enable_irq(void) 
  3. {
  4.     asm volatile 
  5.     (
  6.         "mrs r4,cpsr\n\t"
  7.         "bic r4,r4,#0x80\n\t"
  8.         "msr cpsr,r4\n\t"
  9.         :::"r4"
  10.     );
  11. }
   b. irq中断这条路己经通了,当有usb中断时就会进入usb中断服务程序,这一步要实现产生usb中断的所有准备
      b.1 配置usb寄存器, 让usb设备工作起来

点击(此处)折叠或打开

  1. void Init_Usb_Reg(void)
  2. {
  3. // *** End point information ***
  4. // EP0: control
  5. // EP1: bulk in end point
  6. // EP2: not used
  7. // EP3: bulk out end point
  8. // EP4: not used
  9.     #define PWR_REG_DEFAULT_VALUE (DISABLE_SUSPEND)

  10.     PWR_REG=PWR_REG_DEFAULT_VALUE;    //disable suspend mode //0x00

  11.     INDEX_REG=0;
  12.     MAXP_REG=FIFO_SIZE_8;     //EP0 max packit size = 8 //datasheet:For EP1~4, MAXP=64 is recommended.
  13.     EP0_CSR_IN_CSR1_REG=EP0_SERVICED_OUT_PKT_RDY|EP0_SERVICED_SETUP_END; //EP0_CSR EP0:clear OUT_PKT_RDY & SETUP_END
  14.     INDEX_REG=1;
  15.     MAXP_REG=FIFO_SIZE_32;    //EP1:max packit size = 32

  16.     EP0_CSR_IN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT;
  17.     IN_CSR2_REG=EPI_MODE_IN|EPI_IN_DMA_INT_MASK|EPI_BULK; //IN mode, IN_DMA_INT=masked
  18.     OUT_CSR1_REG=EPO_CDT;
  19.     OUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;

  20.     INDEX_REG=2;
  21.     MAXP_REG=FIFO_SIZE_64;    //EP2:max packit size = 64
  22.     EP0_CSR_IN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT|EPI_BULK;
  23.     IN_CSR2_REG=EPI_MODE_IN|EPI_IN_DMA_INT_MASK; //IN mode, IN_DMA_INT=masked
  24.     OUT_CSR1_REG=EPO_CDT;
  25.     OUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;

  26.     INDEX_REG=3;
  27.     MAXP_REG=FIFO_SIZE_32;    //EP3:max packit size = 32
  28.     EP0_CSR_IN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT|EPI_BULK;
  29.     IN_CSR2_REG=EPI_MODE_OUT|EPI_IN_DMA_INT_MASK; //OUT mode, IN_DMA_INT=masked
  30.     OUT_CSR1_REG=EPO_CDT;
  31.     //clear OUT_PKT_RDY, data_toggle_bit.
  32.     //The data toggle bit should be cleared when initialization.
  33.     OUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;

  34.     INDEX_REG=4;
  35.     MAXP_REG=FIFO_SIZE_64;    //EP4:max packit size = 64
  36.     EP0_CSR_IN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT|EPI_BULK;
  37.     IN_CSR2_REG=EPI_MODE_OUT|EPI_IN_DMA_INT_MASK; //OUT mode, IN_DMA_INT=masked
  38.     OUT_CSR1_REG=EPO_CDT;
  39.         //clear OUT_PKT_RDY, data_toggle_bit.
  40.     //The data toggle bit should be cleared when initialization.
  41.     OUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;

  42.     EP_INT_REG=EP0_INT|EP1_INT|EP2_INT|EP3_INT|EP4_INT;
  43.     USB_INT_REG=RESET_INT|SUSPEND_INT|RESUME_INT;
  44.     //Clear all usbd pending bits

  45.     //EP0,1,& reset interrupt are enabled
  46.     EP_INT_EN_REG=EP0_INT|EP1_INT|EP3_INT;
  47.     USB_INT_EN_REG=RESET_INT;
  48.     //ep0State=EP0_STATE_INIT;
  49. }
     b.2 产生usb复位信号,进入usb枚举过程

点击(此处)折叠或打开

  1. void usb_reconnect(void)
  2. {
  3.     //tq2440: 在USB设备的信号线D+上接了一个1.5K的一个上拉电阻,这个上拉电阻是由usb_en控制的,当GPG12输出高电平的时候,主机的集线器才能检测到设备,从而给复位信号
  4.     //GPG12-->usb_en
  5.     GPGCON |= (OUTPUT_PIN<<24); //set GPG12 output
  6.     GPGDAT |= (1<<12);            //enable USB Device
  7. }
    b.3 usb中断最关键的一步

点击(此处)折叠或打开

  1. INTMSK &= ~(BIT_USBD); //打开usb中断
   c. 产生了usb中断了,但是usb中断服务程序还没有完成,马上。
注意: usb枚举过程是有时间限制的,如果printf打印的太多,会导致枚举失败。

点击(此处)折叠或打开

  1. void IsrUsbd(void)
  2. {
  3.     u8 usbdIntpnd,epIntpnd;
  4.     u8 saveIndexReg=INDEX_REG;
  5.     usbdIntpnd=USB_INT_REG;
  6.     epIntpnd=EP_INT_REG;
  7.     //uart_printf( "[INT:EP_I=%x,USBI=%x]",epIntpnd,usbdIntpnd );

  8.     if(usbdIntpnd&SUSPEND_INT)        //出现suspend_int中断之后,直接清中断
  9.     {
  10.         USB_INT_REG=SUSPEND_INT;    //向寄存器写1,清除该位
  11.     //    uart_puts( "<sus]\n");
  12.     }
  13.     if(usbdIntpnd&RESUME_INT)        //出现resume_int中断之后,直接清中断
  14.     {
  15.         USB_INT_REG=RESUME_INT;        //向寄存器写1,清除该位
  16.     //    uart_puts("<rsm]\n");
  17.     }
  18.     if(usbdIntpnd&RESET_INT)        //出现reset_int中断之后,复位usb
  19.     {
  20.         //uart_puts( "<rst] init_usb_reg\n");
  21.         //ResetUsbd();
  22.         Init_Usb_Reg();
  23.         USB_INT_REG=RESET_INT; //clear RESET_INT
  24.        // PrepareEp1Fifo();
  25.     }

  26.     if(epIntpnd&EP0_INT)
  27.     {
  28.      EP_INT_REG=EP0_INT;        //向寄存器写1,清除该位
  29.         Ep0Handler();
  30.     }
  31.     if(epIntpnd&EP1_INT)
  32.     {
  33.         EP_INT_REG=EP1_INT;        //向寄存器写1,清除该位
  34.         Ep1Handler();
  35.     }

  36.     if(epIntpnd&EP2_INT)
  37.     {
  38.         EP_INT_REG=EP2_INT;        //向寄存器写1,清除该位
  39.         uart_puts("<2:TBD]\n"); //not implemented yet
  40.         //Ep2Handler();
  41.     }

  42.     if(epIntpnd&EP3_INT)
  43.     {
  44.         EP_INT_REG=EP3_INT;
  45.         Ep3Handler();
  46.     }

  47.     if(epIntpnd&EP4_INT)
  48.     {
  49.         EP_INT_REG=EP4_INT;
  50.         uart_puts("<4:TBD]\n"); //not implemented yet
  51.         //Ep4Handler();
  52.     }

  53.     ClearPending(BIT_USBD);

  54.     INDEX_REG=saveIndexReg;
  55. }

   d.
   e.
   f.
2.实现数据的收取 
   a.
   b.
   c.
   d.
   e.
   f.
参考文章:
1. s3c2440的USB主机控制器
http://blog.csdn.net/zhaocj/article/details/6083162
2. S3C2440之USB设备篇
http://blog.csdn.net/xuxg2005/article/details/6172412
3. S3C2440 USB设备控制器
http://blog.csdn.net/yaozhenguo2006/article/details/7405825
版权声明:本文为博主原创文章,转载请注明出处。

C#:USB设备枚举(五)生成TreeView数据源

/* ---------------------------------------------------------- 文件名称:TreeViewUsbItem.cs 作者:秦建辉 MSN:s...
  • jhqin
  • jhqin
  • 2011年11月09日 11:32
  • 2500

图解USB设备的枚举 过程

视频讲解:http://v.youku.com/v_show/id_XMzE5MzI3MTM2.html#paction

[vc++]枚举USB设备

#include #pragma comment(lib,"shlwapi.lib") #include #pragma comment(lib,"setupapi.lib") /* * 函数名称...

C#:USB设备枚举(六)生成ListView数据源

/* ---------------------------------------------------------- 文件名称:ListViewUsbItem.cs 作者:秦建辉 MSN:s...
  • jhqin
  • jhqin
  • 2011年11月09日 11:33
  • 2042

C#:USB设备枚举(四)Kernel32的PInvoke

/* ---------------------------------------------------------- 文件名称:Kernel32.cs 作者:秦建辉 MSN:splashcn...
  • jhqin
  • jhqin
  • 2011年11月03日 10:57
  • 2951

USB设备枚举[转载]

USB设备枚举[转载]  USB架构中, hub负责检测设备的连接和断开,利用其中断IN端点(Interrupt IN Endpoint)来向主机(Host)报告。在系统启动时,主机轮询它的根hub...

USB设备枚举过程

(1)集线器检测新设备 主机集线器监视着每个端口的信号电压,当有新设备接入时便可觉察。(集线器端口的两根信号线的每一根都有15kΩ的下拉电 阻,而每一个设备在D+都有一个1.5kΩ的上拉电阻。当用US...

Linux USB Gadget--设备枚举

前面介绍了Linux USB Gadget的软件结构与各软件层的整合过程。经过各种注册函数,Gadget功能驱动层,USB设备层与UDC底层结合在了一起形成了一个完整的USB设备。而这个设备已经准备好...

stm32USB设备的连接枚举过程

1) USB 的插入检测   当12脚短接,Q1截止,Q2导通,D+上拉,windows 就会认为 USB 接口有一个全速设备,马上复位总线,并开始枚举设备。   如果23脚短接,则 ...

USB设备的枚举

我最近在做一个操作USB设备的程序,但在打开设备时遇到了问题.步骤如下, 1.调用SetupDiGetClassDevs.这一部正常获得句柄 2.调用SetupDiEnumDeviceIn...
  • wdt3385
  • wdt3385
  • 2012年08月30日 14:30
  • 963
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:bootloader---19.usb下载之设备枚举
举报原因:
原因补充:

(最多只允许输入30个字)