第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设备就完成了初始化。
|