大家好,此文内容紧跟《FSL USB Stack 简介》一文,如果网友们先前没有浏览过《FSLUSB Stack 简介》,建议先下载浏览,然后再浏览本篇内容。本篇是以飞思卡尔的USB协议栈Freescale USB Stack v4.1.1中的鼠标HID例程为例,介绍USB Stack层式架构中的USB Applicati on、HID Class Drivers 和 USB Drivers是如何各司其职,相互配合确保例程,本例程路径:USBFreescale USBStack v4.1.1 SourceDeviceapphidcw10kinetis_l2k 1. USBStack文件介绍
图1为在CW10.6中打开的kinetis_l2k例程, 从中可看出,在USB Stack层式架构中,USB Application、HID ClassDrivers 和 USB Drivers都有属于本层的文件,表一则对各层的文件进行了归纳。
图 1 USB Stack 文件
表一
1. 鼠标HID例程代码
主程序
***************************************************************************** * This function initializes the system, enables the interrupts and calls the * application *****************************************************************************/ #ifdef __GNUC__ int main(void) #else void main(void) #endif { /* Initialize the system */ SYS_Init(); //时钟配置:PEE模式,CORE_CLOCK、SYSTEM_CLOCK、BUS_CLOCK、FLASH_CLOCK为48MHz #ifdef SERIAL_DEBUG sci_init(); #endif #ifndef _SERIAL_AGENT_ /* Initialize USB module */ #if HIGH_SPEED_DEVICE USB_Init(ULPI); #else USB_Init(MAX3353);//USB模块初始化 #endif #else SIM_SOPT2 |= (SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK); #endif /* Initialize GPIO pins */ GPIO_Init(); //按键引脚初始化:PTA4、PTC3 #if MAX_TIMER_OBJECTS (void)TimerQInitialize(0); #endif /* Initialize the USB Test Application */ TestApp_Init();//鼠标HID应用运行开始,内含USB_Class_HID_Init()函数 while(TRUE) { Watchdog_Reset(); /* Call the application task */ TestApp_Task();//应用任务函数 } #ifdef __GNUC__ return 0; #endif }
[color=rgb(51, 102, 153) !important]复制代码
pll_init()
SYS_Init()函数中包含pll_init()函数用于配置PEE时钟模式和
各个时钟源的频率。
static int pll_init() { #elif (defined MCU_MKL25Z4) /* Update system prescalers */ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV4(1); SIM_CLKDIV1 |= SIM_CLKDIV1_OUTDIV1(1); /* First FEI must transition to FBE mode Enable external oscillator, RANGE=02, HGO=, EREFS=, LP=, IRCS= */ MCG_C2 = MCG_C2_RANGE0(2) | MCG_C2_EREFS0_MASK | MCG_C2_IRCS_MASK; /* Select external oscillator and Reference Divider and clear IREFS * to start external oscillator * CLKS = 2, FRDIV = 3, IREFS = 0, IRCLKEN = 0, IREFSTEN = 0 */ MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(3); /* MCG_C4: DMX32=0,DRST_DRS=0 */ MCG_C4 &= (uint8_t)~(uint8_t)0xE0U; /* MCG_C5: ??=0,PLLCLKEN=0,PLLSTEN=1,PRDIV=0x3, external clock reference = 8/4 = 2MHz */ MCG_C5 = (uint8_t)0x23U; /* MCG_C6: LOLIE=0,PLLS=0,CME=0,VDIV=0x18 */ MCG_C6 = (uint8_t)0x18U; while((MCG_S & MCG_S_IREFST_MASK) != 0x00U) { /* Check that the source of the FLL reference clock is the external reference clock. */ } while((MCG_S & 0x0CU) != 0x08U) { /* Wait until external reference clock is selected as MCG output */ } /* Switch to PBE Mode */ /* MCG_C1: CLKS=2,FRDIV=3,IREFS=0,IRCLKEN=0,IREFSTEN=0 */ MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(3); /* MCG_C2: ??=0,??=0,RANGE=2,HGO=0,EREFS=0,LP=0,IRCS=1 */ MCG_C2 = MCG_C2_RANGE0(2) | MCG_C2_EREFS0_MASK | MCG_C2_IRCS_MASK; /* MCG_C5: ??=0,PLLCLKEN=0,PLLSTEN=1,PRDIV=0x03 */ MCG_C5 = (uint8_t)0x23U; /* MCG_C6: LOLIE=0,PLLS=1,CME=0,VDIV=0x18 */ MCG_C6 = (uint8_t)0x58U; while((MCG_S & 0x0CU) != 0x08U) { /* Wait until external reference clock is selected as MCG output */ } while((MCG_S & MCG_S_LOCK0_MASK) == 0x00U) { /* Wait until locked */ } /* Switch to PEE Mode */ /* MCG_C1: CLKS=0,FRDIV=3,IREFS=0,IRCLKEN=0,IREFSTEN=0 */ MCG_C1 = (uint8_t)0x18U; /* MCG_C2: ??=0,??=0,RANGE=2,HGO=0,EREFS=0,LP=0,IRCS=1 */ MCG_C2 = MCG_C2_RANGE0(2) | MCG_C2_EREFS0_MASK | MCG_C2_IRCS_MASK; /* MCG_C5: ??=0,PLLCLKEN=0,PLLSTEN=1,PRDIV=0x03 */ MCG_C5 = (uint8_t)0x23U; /* MCG_C6: LOLIE=0,PLLS=1,CME=0,VDIV=0x18 */ MCG_C6 = (uint8_t)0x58U; while((MCG_S & 0x0CU) != 0x0CU) { /* Wait until output of the PLL is selected */ } /* MCG_C6: CME=1 */ MCG_C6 |= (uint8_t)0x20U; /* Enable the clock monitor */ /*** End of PE initialization code after reset ***/ return 0; /* end MCU_MKL25Z4 */ }
[color=rgb(51, 102, 153) !important]复制代码
USB_Init()
static void USB_Init(uint_8 controller_ID) { if(controller_ID == MAX3353) { #ifdef MCU_MK70F12 /* MPU is disabled. All accesses from all bus masters are allowed */ MPU_CESR=0; SIM_SOPT2 |= SIM_SOPT2_PLLFLLSEL(1) /** PLL0 reference */ | SIM_SOPT2_USBFSRC(0) /** MCGPLLCLK as CLKC source */ | SIM_SOPT2_USBF_CLKSEL_MASK; /** USB fractional divider like USB reference clock */ SIM_CLKDIV2 = USB_FRAC | USB_DIV; /** Divide reference clock to obtain 48MHz */ /* Enable USB-OTG IP clocking */ SIM_SCGC4 |= SIM_SCGC4_USBFS_MASK; #else #ifndef MCU_MKL25Z4 SIM_CLKDIV2 &= (uint32_t)(~(SIM_CLKDIV2_USBFRAC_MASK | SIM_CLKDIV2_USBDIV_MASK)); #endif /* MCU_MKL25Z4 */ #ifdef MCGOUTCLK_72_MHZ /* Configure USBFRAC = 0, USBDIV = 0 => frq(USBout) = 2 / 3 * frq(PLLin) */ SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(2) | SIM_CLKDIV2_USBFRAC_MASK; #else #ifndef MCU_MKL25Z4 /* Configure USBFRAC = 0, USBDIV = 0 => frq(USBout) = 1 / 1 * frq(PLLin) */ SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(0); #endif /* MCU_MKL25Z4 */ #endif /* MCGOUTCLK_72_MHZ */ /* 1. Configure USB to be clocked from PLL */ SIM_SOPT2 |= SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK; #if PLL_96 /* 2. USB freq divider */ SIM_CLKDIV2 = 0x02; #endif /* PLL_96 */ /* 3. Enable USB-OTG IP clocking */ SIM_SCGC4 |= (SIM_SCGC4_USBOTG_MASK); /* old documentation writes setting this bit is mandatory */ USB0_USBTRC0 = 0x40; /* Configure enable USB regulator for device */ #if(defined MCU_MK20D5) SIM_SOPT1CFG |= SIM_SOPT1CFG_URWE_MASK; /* Enable SOPT1 to be written */ #endif SIM_SOPT1 |= SIM_SOPT1_USBREGEN_MASK; } #endif
[color=rgb(51, 102, 153) !important]复制代码
GPIO_Init()
static void GPIO_Init() { #if defined(MCU_MKL25Z4) /* Enable clock gating to PORTA, PORTB, PORTC, PORTD and PORTE */ SIM_SCGC5 |= (SIM_SCGC5_PORTA_MASK | SIM_SCGC5_PORTB_MASK | SIM_SCGC5_PORTC_MASK | SIM_SCGC5_PORTD_MASK | SIM_SCGC5_PORTE_MASK); /* LEDs settings */ PORTA_PCR5 = PORT_PCR_MUX(1); PORTA_PCR16 = PORT_PCR_MUX(1); PORTA_PCR17 = PORT_PCR_MUX(1); PORTB_PCR8 = PORT_PCR_MUX(1); GPIOA_PDDR |= (1<<5) | (1<<16) | (1<<17); GPIOB_PDDR |= (1<<8); /* Switch buttons settings */ /* Set input on PORTC pin 3 */ #ifndef _USB_BATT_CHG_APP_H_ PORTC_PCR3 = PORT_PCR_MUX(1); GPIOC_PDDR &= ~((uint_32)1 << 3); /* Pull up enabled */ PORTC_PCR3 |= PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; /* GPIO_INT_EDGE_HIGH */ PORTC_PCR3 |= PORT_PCR_IRQC(9); /* Set input on PORTA pin 4 */ PORTA_PCR4 = PORT_PCR_MUX(1); GPIOA_PDDR &= ~((uint_32)1 << 4); /* Pull up */ PORTA_PCR4 |= PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; /* GPIO_INT_EDGE_HIGH */ PORTA_PCR4 |= PORT_PCR_IRQC(9); /* Clear interrupt flag */ PORTC_ISFR = (1 << 3); PORTA_ISFR = (1 << 4); /* Enable interrupt port A */ NVIC_ICPR = 1 << 30; NVIC_ISER = 1 << 30; #endif #endif }
[color=rgb(51, 102, 153) !important]复制代码
参考文献:
0