zoukankan      html  css  js  c++  java
  • 【STM32F429】第3章 ThreadX USBX协议栈移植到STM32F429

    教程更新中:http://www.armbbs.cn/forum.php?mod=viewthread&tid=108546

    第3章   ThreadX USBX协议栈移植到STM32F429

    本章节为大家讲解USBX协议栈移植到STM32F429。

    3.1 初学者重要提示

    3.2 USBX移植步骤

    3.3 USBX的模拟U盘移植接口文件ux_device_msc.c。

    3.4 使用的MicroUSB接口并注意跳线帽设置

    3.5 实验例程

    3.6 总结

    3.1   初学者重要提示

    1、  本章使用的ST专门为STM32F4提供的软件包:

    http://www.armbbs.cn/forum.php?mod=viewthread&tid=108636 .

    2、  本章配套例子使用SD卡模拟一个U盘,使用的MicroUSB接口。

    3.2   USBX移植步骤

    ThreadX USBX的移植步骤如下:

    3.2.1      第1步,了解整体设计框架

    为了方便大家移植,需要大家先对移植好的工程有个整体认识:

     

     

    3.2.2      第2步,添加USBX和USB驱动到工程

    这里我们在FileX教程做的模板例子基础上添加USBX文件和USB驱动文件,大家可以直接从本章教程提供的例子里面复制。

    •   模拟U盘驱动文件ux_device_msc.c/.h和ux_device_descriptors.c/.h添加到自己的工程里面,路径不限。

    配套例子是放在Userusb文件。

    •   USB驱动文件stm32f4xx_hal_hcd.c,stm32f4xx_hal_pcd.c,stm32f4xx_hal_pcd_ex.c和stm32f4xx_ll_usb.c。

    这个是STM32F4的HAL库自带的。

    •   USBX相关源文件。

    大家可以将所有相关文件都复制到自己的工程里面,配套例子是放在USBX。

    3.2.3      第3步,添加工程路径

    大家根据自己添加的源文件位置,添加相关路径即可:

     

     

    3.2.4      第4步,禁止掉添加进来一些文件

    之所以要禁止掉是因为这些文件要用到NetXDUO网络协议栈,或者大家不添加进来都是可以的。添加进来后再禁止的优势是添加时候可以全选添加。

     

     

    禁止的方法是右击此文件去掉如下对钩即可:

     

     

    3.2.5      第4步,配置GPIO和时钟

    USB时钟配置在bsp.c文件的函数SystemClock_Config里面:

        /* 芯片内部的LDO稳压器输出的电压范围,选用的PWR_REGULATOR_VOLTAGE_SCALE1 */
        __HAL_RCC_PWR_CLK_ENABLE();
        __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
    
        /* 使能HSE,并选择HSE作为PLL时钟源 */
        RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
        RCC_OscInitStruct.HSEState = RCC_HSE_ON;
        RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
        RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
        RCC_OscInitStruct.PLL.PLLM = 8;
        RCC_OscInitStruct.PLL.PLLN = 336;
        RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
        RCC_OscInitStruct.PLL.PLLQ = 7;  这个分频很重要,分频出48MHz
        if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
        {
            Error_Handler(__FILE__, __LINE__);
        }

    USB的GPIO,NVIC初始化在demo_sd_usbx.c:

        /* 配置USB GPIO, NVIC */
        {
            GPIO_InitTypeDef  GPIO_InitStruct = {0};
    
            __HAL_RCC_GPIOA_CLK_ENABLE();
    
            GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_11;
            GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
            GPIO_InitStruct.Pull = GPIO_NOPULL;
            GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
            GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
            HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
            
    
            /* 使能USB FS时钟 */
            __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
    
            
            /* 配置USB FS中断 */
            HAL_NVIC_SetPriority(OTG_FS_IRQn, 0, 0); 
            HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
        }
    
        /* 初始化USB */
        {
            memset(&hpcd_USB_OTG_FS, 0x0, sizeof(PCD_HandleTypeDef));
          hpcd_USB_OTG_FS.Instance = USB_OTG_FS;
          hpcd_USB_OTG_FS.Init.dev_endpoints = 4;
          hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;
          hpcd_USB_OTG_FS.Init.dma_enable = DISABLE;
          hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
          hpcd_USB_OTG_FS.Init.Sof_enable = DISABLE;
          hpcd_USB_OTG_FS.Init.low_power_enable = DISABLE;
          hpcd_USB_OTG_FS.Init.lpm_enable = DISABLE;
          hpcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE;
          hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = DISABLE;
    
            /* 初始化USB  */
            HAL_PCD_Init(&hpcd_USB_OTG_FS);
    
            /* 设置TX FIFO和RX FIFO */
            HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 128);
            HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 64);
            HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 128);
    
            /* 注册STM32到USBX协议栈并初始化 */
            status =  ux_dcd_stm32_initialize((ULONG)USB_OTG_FS, (ULONG)&hpcd_USB_OTG_FS);
    
            if (status != FX_SUCCESS)
            {
                return;
            }
            
        }

    3.2.6      第7步,添加应用代码(USB中断,打开U盘和关闭U盘)

    USB操作专门整理到了文件demo_sd_usbx.c。主要三部分,打开U盘,关闭U盘和USB中断服务程序。这三个函数基本是通用的,大家直接复制粘贴使用即可

    特别注意USB中断服务程序别忘了添加。

    3.3   USBX的模拟U盘移植接口文件ux_device_msc.c说明

    这里将USBX的底层接口文件ux_device_msc.c的实现为大家简单做个说明。

    3.3.1  状态函数app_usb_device_thread_media_status

    代码如下:

    UINT  app_usb_device_thread_media_status(VOID *storage, ULONG lun, ULONG media_id, ULONG *media_status)
    {
    
      /* The ATA drive never fails. This is just for app_usb_device only !!!! */
      return (UX_SUCCESS);
    }

    此函数主要用于获取SD卡模拟U盘的状态。

    3.3.2  读取函数app_usb_device_thread_media_read

    代码如下:

    /**
      * @brief  Function implementing app_usb_device_thread_media_read.
      * @param  storage : Not used
      * @param  lun: Logical unit number
      * @param  lba: Logical block address
      * @param  number_blocks: Blocks number
      * @param  data_pointer: Data
      * @param  media_status: Not used
      * @retval Status (0 : OK / -1 : Error)
      */
    UINT  app_usb_device_thread_media_read(VOID *storage, ULONG lun,
                                           UCHAR *data_pointer,
                                           ULONG number_blocks,
                                           ULONG lba, ULONG *media_status)
    {
    #if 0
        UINT status = 0U;
    
        BSP_SD_ReadBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);                                    
        status = check_sd_status(0);    
        return (status);
    
    #else
        UINT status;
        if(check_sd_status(0) != BSP_ERROR_NONE)
        {
            
        }
        
        status = BSP_SD_ReadBlocks_DMA((uint32_t*)data_pointer, lba, number_blocks);
    
        if (status == BSP_ERROR_NONE)
        {
            if(tx_semaphore_get(&transfer_semaphore, DEFAULT_TIMEOUT) == TX_SUCCESS)
            {
                status = FX_SUCCESS;
            }
            else
            {
                status =  FX_BUFFER_ERROR;
            }
        }
    
        return status;
    #endif
    }

    用于实现SD模拟U盘的读取功能。

    3.3.3  写入函数app_usb_device_thread_media_write

    代码如下:

    /**
      * @brief  Function implementing app_usb_device_thread_media_write.
      * @param  storage : Not used
      * @param  lun: Logical unit number
      * @param  lba: Logical block address
      * @param  number_blocks: Blocks number
      * @param  data_pointer: Data
      * @param  media_status: Not used
      * @retval Status (0 : OK / -1 : Error)
      */
    UINT  app_usb_device_thread_media_write(VOID *storage, ULONG lun,
                                            UCHAR *data_pointer,
                                            ULONG number_blocks,
                                            ULONG lba, ULONG *media_status)
    {
    #if 0
        UINT status = 0U;
    
        BSP_SD_WriteBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);
        status = check_sd_status(0);
        
        return (status);
    
    #else
        UINT status;
        
        if(check_sd_status(0) != BSP_ERROR_NONE)
        {
            
        }
    
        status = BSP_SD_ReadBlocks_DMA((uint32_t*)data_pointer, lba, number_blocks);
    
        if (status == BSP_ERROR_NONE)
        {
            if(tx_semaphore_get(&transfer_semaphore, DEFAULT_TIMEOUT) == TX_SUCCESS)
            {
                status = FX_SUCCESS;
            }
            else
            {
                status =  FX_BUFFER_ERROR;
            }
        }
    
    #endif
    
        return status;
    }

    用于实现SD模拟U盘的写入功能。

    3.3.4  接口函数注册

    接口函数的注册是在文件demo_sd_usbx.c里面:

    storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_read  =  app_usb_device_thread_media_read;
    
    storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_write  =  app_usb_device_thread_media_write; 
    
    storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_status =  app_usb_device_thread_media_status;

    3.4   使用的MicroUSB接口并注意跳线帽设置

    本周教程移植的例子使用内部RAM模拟了一个U盘,效果如下:

     

     

    注意使用的是MicroUSB接口:

     

     

    注意板子左下角跳线帽的设置:

     

     

    这里是用于选择CAN1 TX使用PB9或者PA12引脚,CAN1 RX使用PB8或者PA11引脚。大家这里可以什么都不接,或者CAN1 TX通过跳线帽短接PA12,CAN1 RX通过跳线帽短接PA11。切记不可以短接到PA12和PA11引脚上,USB要使用这两个引脚。

    3.5   实验例程

    配套例子:

    V6-2401_ThreadX USBX Template

    实验目的:

    1. 学习USBX模板,通过SD来模拟U盘。

    实验内容:

    1、共创建了如下几个任务,通过按下按键K1可以通过串口或者RTT打印任务堆栈使用情况                                  

    ========================================================

             CPU利用率 =  0.89%

             任务执行时间 = 0.586484645s

             空闲执行时间 = 85.504470575s

             中断执行时间 = 0.173225395s

             系统总执行时间 = 86.264180615s              

    =======================================================

            任务优先级 任务栈大小 当前使用栈  最大栈使用   任务名

              Prio     StackSize   CurStack    MaxStack   Taskname

              2         4092        303         459      App Task Start

              5         4092        167         167      App Msp Pro

              4         4092        167         167      App Task UserIF

               5         4092        167         167      App Task COM

               0         1020        191         191      System Timer Thread           

    串口软件可以使用SecureCRT或者H7-TOOL RTT查看打印信息。

    App Task Start任务  :启动任务,这里用作BSP驱动包处理。

    App Task MspPro任务 :消息处理。

    App Task UserIF任务 :按键消息处理。

    App Task COM任务   :这里用作LED闪烁。

    System Timer Thread任务:系统定时器任务

    2、(1) 凡是用到printf函数的全部通过函数App_Printf实现。

    (2) App_Printf函数做了信号量的互斥操作,解决资源共享问题。

    3、默认上电是通过串口打印信息,如果使用RTT打印信息

    (1)   MDK AC5,MDK AC6或IAR通过使能bsp.h文件中的宏定义为1即可

    #define Enable_RTTViewer  1

    (2)   Embedded Studio继续使用此宏定义为0, 因为Embedded Studio仅制作了调试状态RTT方式查看。

    实验操作:

    1. 测试前务必将SD卡插入到开发板左上角的卡座中。
    2. 支持以下6个功能,用户通过电脑端串口软件发送数字1-6给开发板即可
    3. printf("1 - 显示根目录下的文件列表 ");
    4. printf("2 - 创建一个新文件armfly.txt ");
    5. printf("3 - 读armfly.txt文件的内容 ");
    6. printf("4 - 创建目录 ");
    7. printf("5 - 删除文件和目录 ");
    8. printf("6 - 读写文件速度测试 ");
    9. printf("a - 打开SD卡模拟U盘 ");
    10. printf("b - 关闭SD卡模拟U盘 ");

    串口打印的信息:

    波特率 115200,数据位 8,奇偶校验位无,停止位 1

     

     

    RTT打印:

     

     

    3.6   总结

    本章节就为大家讲解这么多,后面章节再为大家详细讲解USBX的玩法。

    微信公众号:armfly_com 安富莱论坛:www.armbbs.cn 安富莱淘宝:https://armfly.taobao.com
  • 相关阅读:
    (Good Bye 2019) Codeforces 1270B Interesting Subarray
    (Good Bye 2019) Codeforces 1270A Card Game
    Codeforces 1283D Christmas Trees(BFS)
    Codeforces 1283C Friends and Gifts
    Codeforces 1283B Candies Division
    1095 Cars on Campus (30)
    1080 Graduate Admission (30)
    1099 Build A Binary Search Tree (30)
    1018 Public Bike Management (30)
    1087 All Roads Lead to Rome (30)
  • 原文地址:https://www.cnblogs.com/armfly/p/15421204.html
Copyright © 2011-2022 走看看