分享

USB Device Port的低级初始化

 lchjczw 2012-03-15

第1步
低级初始化由函数 void AT91F_LowLevelInit() 执行,定义于init.c.
低级初始化主要包括初始化高级中断控制器,为DEBUG打开并设置PIO,使能字符传输寄存器等。
第1.1步
初始化高级中断控制器由lib_AT91RM9200.h中的函数
 __inline void AT91F_AIC_Open(
  AT91PS_AIC pAic,        // \arg pointer to the AIC registers
  void (*IrqHandler) (),  // \arg Default IRQ vector exception
  void (*FiqHandler) (),  // \arg Default FIQ vector exception
  void (*DefaultHandler)  (), // \arg Default Handler set in ISR
  void (*SpuriousHandler) (), // \arg Default Spurious Handler
  unsigned int protectMode)   // \arg Debug Control Register
完成。

首先屏蔽原先摄制的中断,
 __inline void AT91F_AIC_DisableIt (
  AT91PS_AIC pAic,      // \arg pointer to the AIC registers
  unsigned int irq_id ) // \arg interrupt number to initialize
并重新设置中断,将其优先级全部置最低,
 __inline unsigned int AT91F_AIC_ConfigureIt (
  AT91PS_AIC pAic,  // \arg pointer to the AIC registers
  unsigned int irq_id,     // \arg interrupt number to initialize
  unsigned int priority,   // \arg priority to give to the interrupt
  unsigned int src_type,   // \arg activation and sense of activation
  void (*newHandler) (void) ) // \arg address of the interrupt handler
中断处理函数设为未定义
 void AT91F_UndefHandler()
 {
  AT91F_DBGU_Printk("-F- Undef detected\n\r");
  while (1);
 }
然后设置外部中断异常向量和快速中断异常向量
 AT91F_AIC_SetExceptionVector((unsigned int *) 0x18, IrqHandler);
 AT91F_AIC_SetExceptionVector((unsigned int *) 0x1C, FiqHandler);
最后设置伪向量寄存器和调试控制寄存器
 pAic->AIC_SPU = (unsigned int) SpuriousHandler;
 pAic->AIC_DCR = protectMode;
此处SpuriousHandler为函数
 void AT91F_SpuriousHandler()
 {
  AT91F_DBGU_Printk("-F- Spurious Interrupt detected\n\r");
  while (1);
 }
的地址
此处protectMode值为0,意为The Protection Mode is disabled,and the nIRQ and nFIQ lines are normally controlled by the AIC.(见

AT91RM9200手册252页)

第1.2步
然后Perform 8 End Of Interrupt Command to make sure AIC will not Lock out nIRQ

第1.3步
接着设置中断向量表
 AT91F_AIC_SetExceptionVector((unsigned int *)0x0C, AT91F_FetchAbort);
 AT91F_AIC_SetExceptionVector((unsigned int *)0x10, AT91F_DataAbort);
 AT91F_AIC_SetExceptionVector((unsigned int *)0x4, AT91F_Undef);
其第一个参数的含义见AT91RM9200手册244页
其第一个参数的含义见init.c

第1.4步
最后为DBGU打开并配置PIO
由函数__inline void AT91F_DBGU_CfgPIO (void)
和函数__inline void AT91F_US_Configure (
 AT91PS_USART pUSART,     // \arg pointer to a USART controller
 unsigned int mainClock,  // \arg peripheral clock
 unsigned int mode ,      // \arg mode Register to be programmed
 unsigned int baudRate ,  // \arg baudrate to be programmed
 unsigned int timeguard ) // \arg timeguard to be programmed
完成(两个函数在lib_AT91RM9200.h中定义)
第1.4.1步
调用函数
 __inline void AT91F_DBGU_CfgPIO (void)
 {
  // Configure PIO controllers to periph mode
  AT91F_PIO_CfgPeriph(
   AT91C_BASE_PIOA, // PIO controller base address
   ((unsigned int) AT91C_PA31_DTXD    ) |
   ((unsigned int) AT91C_PA30_DRXD    ), // Peripheral A
   0); // Peripheral B
 }
AT91C_PA31_DTXD 和 AT91C_PA30_DRXD均定义在AT91RM9200_inc.h,分别表示DBGU模式下的发送、接收数据的字段
该函数继续调用函数
 __inline void AT91F_PIO_CfgPeriph(
  AT91PS_PIO pPio,             // \arg pointer to a PIO controller
  unsigned int periphAEnable,  // \arg PERIPH A to enable
  unsigned int periphBEnable)  // \arg PERIPH B to enable
 {
  pPio->PIO_ASR = periphAEnable;
  pPio->PIO_BSR = periphBEnable;
  pPio->PIO_PDR = (periphAEnable | periphBEnable); // Set in Periph mode
 }

第1.4.2步
各参数如下AT91PS_USART) AT91C_BASE_DBGU,        // DBGU base address
 60000000,                // 48 MHz
 AT91C_US_ASYNC_MODE,      // mode Register to be programmed
 115200 ,                 // baudrate to be programmed
 0                  // timeguard to be programmed

第1.5步
使用函数void AT91F_DBGU_Printk(char *buffer) // \arg pointer to a string ending by \0
 {
  while(*buffer != '\0') {
   while (!AT91F_US_TxReady((AT91PS_USART)AT91C_BASE_DBGU));
   AT91F_US_PutChar((AT91PS_USART)AT91C_BASE_DBGU, *buffer++);
  }
 }
输出"-I- AT91F_LowLevelInit() done\n\r"表示低级初始化成功
函数    __inline void AT91F_US_PutChar (AT91PS_USART pUSART,int character )
 {
      pUSART->US_THR = (character & 0x1FF);
 }
将要输出的字符写入USART的Transmitter Holding Register,然后由超级终端接受

以上步骤完成后,回到cstartup_ads.s,继续维护一些堆栈,然后进行设备初始化。

USB Device Port的设备初始化

                                      

第2步
设备初始化由main.c的函数void AT91F_InitDrivers()完成,
首先配置电源管理控制器,然后为每个端点开启DMA服务,接着配置高级中断控制器,使能UDP相应的中断,使能UDP的上拉电阻。
第2.1步
配置电源管理控制器由lib_AT91RM9200.h的函数__inline void AT91F_UDP_CfgPMC (void)完成
 __inline void AT91F_UDP_CfgPMC (void)
 {
  AT91F_PMC_EnablePeriphClock(
   AT91C_BASE_PMC, // PIO controller base address
   ((unsigned int) 1 << AT91C_ID_UDP));
 }
其中AT91C_ID_UDP的定义如下
#define AT91C_ID_UDP    ((unsigned int) 11) // USB Device Port
函数AT91F_UDP_CfgPMC 调用了下面的函数
 __inline void AT91F_PMC_EnablePeriphClock (
  AT91PS_PMC pPMC, // \arg pointer to PMC controller
  unsigned int periphIds)  // \arg IDs of peripherals to enable
 {
  pPMC->PMC_PCER = periphIds; //Peripheral Clock Enable Register
 }
其中PMC_PCER是外设时钟使能寄存器
接着通过System Clock Enable Register置位为UDP开启系统时钟,代码如下:
 AT91C_BASE_PMC->PMC_SCER |= AT91C_PMC_UDP; // Enable 48 MHz

第2.2步
然后为每个端点开启DMA服务
第2.2.1步
首先为USB的控制端点开启DMA服务,由AT91_SVC_USBCTL.c中的函数
 AT91PS_SVC_USBCTL AT91F_SVC_USBCTL_Open(
  AT91PS_SVC_USBCTL pSvcUdp,  // \arg Pointer to an USBCTL service previously allocated
  AT91PS_UDP pUdp)            // \arg Pointer to UDP registers
完成。其中pUdp的值是AT91C_BASE_UDP,为UDP相关的寄存器的基地址;pSvcUdp是定义在AT91_SVC_USBCTL.h里的结构体。
函数AT91F_SVC_USBCTL_Open注册了相应的服务,Handler,Read,Write;初始化了其他相关的数据。
然后为控制服务指定了请求分派程序,usb_enumerate.c中的AT91F_USB_DispatchRequest函数

第2.2.2步
为USB的IN端点开启DMA服务,由AT91_SVC_USBIN.c中的函数
 AT91PS_SVC_USBIN AT91F_SVC_USBIN_Open(
  AT91PS_SVC_USBIN pSvcUdp,  // \arg Pointer to an USBIN service previously allocated
  AT91PS_UDP pUdp,            // \arg Pointer to UDP registers
  unsigned char epNb,         // \arg Endpoint Number
  unsigned char epSize,       // \arg Endpoint Size
  unsigned char nbBanks)      // \arg UDP DPR banks
完成。其中pUdp的值是AT91C_BASE_UDP,为UDP相关的寄存器的基地址;pSvcUdp是定义在AT91_SVC_USBIN.h里的结构体。
函数AT91F_SVC_USBCTL_Open注册了相应的服务,Handler,Write;初始化了其他相关的数据,包括缓冲、数据块等。

第2.2.3步
为USB的OUT端点开启DMA服务,由AT91_SVC_USBCTL.c中的函数
 AT91PS_SVC_USBIN AT91F_SVC_USBIN_Open(
  AT91PS_SVC_USBIN pSvcUdp,  // \arg Pointer to an USBIN service previously allocated
  AT91PS_UDP pUdp,            // \arg Pointer to UDP registers
  unsigned char epNb,         // \arg Endpoint Number
  unsigned char epSize,       // \arg Endpoint Size
  unsigned char nbBanks)      // \arg UDP DPR banks
完成。其中pUdp的值是AT91C_BASE_UDP,为UDP相关的寄存器的基地址;pSvcUdp是定义在AT91_SVC_USBCTL.h里的结构体。
函数AT91F_SVC_USBCTL_Open注册了相应的服务,Handler,Read;初始化了其他相关的数据,包括缓冲、数据块等。

第2.2.4步
为USB的另一个IN端点开启DMA服务,由AT91_SVC_USBCTL.c中的函数
 AT91PS_SVC_USBCTL AT91F_SVC_USBCTL_Open(
  AT91PS_SVC_USBCTL pSvcUdp,  // \arg Pointer to an USBCTL service previously allocated
  AT91PS_UDP pUdp)            // \arg Pointer to UDP registers
完成。其中pUdp的值是AT91C_BASE_UDP,为UDP相关的寄存器的基地址;pSvcUdp是定义在AT91_SVC_USBCTL.h里的结构体。
函数AT91F_SVC_USBCTL_Open注册了相应的服务,Handler,Write;初始化了其他相关的数据,包括缓冲、数据块等。

第2.3步
配置高级中断控制器以处理UDP相应的中断,由lib_AT91RM9200.h中的函数
 __inline unsigned int AT91F_AIC_ConfigureIt (
  AT91PS_AIC pAic,  // \arg pointer to the AIC registers
  unsigned int irq_id,     // \arg interrupt number to initialize
  unsigned int priority,   // \arg priority to give to the interrupt
  unsigned int src_type,   // \arg activation and sense of activation
  void (*newHandler) (void) ) // \arg address of the interrupt handler
完成。其中newHandler的值为AT91F_ASM_UDP_Handler,表示main.h中的函数extern void AT91F_UDP_Handler(void),该函数的定义在c_isr.c里。中断信号由寄存器Interrupt Mask Register和Interrupt Status Register按位与得到。
然后将这些中断使能。

第2.4步
使能UDP的上拉电阻,代码如下:
 AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, AT91C_PIO_PA10);
 AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, AT91C_PIO_PA10);
这两个函数都定义在lib_AT91RM9200.h

这样,整个UDP设备就完成了初始化。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多