This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TM4C123GH6PM:将 TM4C123 USB 用于记忆棒应用

Guru**** 2459550 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/649814/tm4c123gh6pm-using-tm4c123-usb-for-memory-stick-application

器件型号:TM4C123GH6PM

您好!

我目前正在处理一个需要与记忆棒连接并将 csv 文件写入其中的应用。 我正在使用 TIVAware dk-tm4c123文件夹下的 QS-logger 示例。 我会得到它的一些部分。 但真正令我困惑的是 USBOTGMain 函数的使用。 我粘贴了下面部分示例代码。 我用红色粗体突出显示了函数调用。 下面是用户指南对该函数的介绍。 以下是一些我不理解的内容:

1) 1)说明必须定期调用。 为什么?  从该示例中、它看起来像是在每次 while 循环重复时调用的、但迭代时间并不总是相等? 为什么不在计时器处理程序中调用此函数? 也许我在这里真的很困惑。 为什么定期调用该函数?  

2)我对 FreeRTOS 有一定的了解、其中每个任务都像一个"小主函数"、我将根据下面的说明尝试将这个概念联系起来。 请有人澄清这一点吗? 描述中提到"合作社系统"我对合作社调度的理解是、任务会一直运行、直到它明确产生、而这是发生上下文切换的时候。 我正在尝试将这种理解与描述联系起来。 这是否意味着当这个 USB 主系统正在运行时、其它任务不能运行? 当该函数运行时、发生中断(例如按下按钮)时会发生什么情况?  

3)另外、如果我在程序中使用 FreeRTOS、那么在我有 RTOS 存在的情况下、该函数调用将如何发挥作用?

我的想法和想法都是事先道歉的地方。 我对该函数的用途感到非常困惑。  

非常感谢。  

AJ

USBOTGMain
此函数是 OTG 控制器驱动程序的主例程。


原型:
无效
USBOTGMain (uint32_t ui32MsTicks)


参数:
ui32MsTicks 是自上次此函数以来经过的毫秒数
进行了调用。


描述:
此函数是在 OTG 模式下使用库时 USB 控制器的主例程。
主应用程序必须在回调上下文之外定期调用此例程。
ui32MsTicks 值用于 USB 库在中运行时所需的基本计时
OTG 模式。 这使得一个简单的协同系统能够访问 OTG 控制器驱动程序
而无需 RTOS。 所有时间关键操作在中断中处理
上下文、但所有更长的操作都从该函数运行、以允许它们阻止和等待
完成、而不会中断其他中断。


返回:
无。

 while (1)
   {

       //
       //每次计时器节拍发生时,处理任何按钮事件。
       //
       if (g_ui32TickCount!= ui32LastTickCount)
       {
           //
           //记住最后一个节拍计数
           //
           ui32LastTickCount = g_ui32TickCount;

           //
           //读取按钮的消抖状态。
           //
           ui8ButtonState = ButtonPoll (&ui8ButtonChanged、0);

           //
           //将任何按钮按压传递到小工具消息
           //处理机制。  具有按钮事件的小工具
           //焦点(可能是菜单小工具)将捕获这些按钮事件。
           //
           if (button_pressed (select_button、ui8ButtonState、ui8ButtonChanged))
           {
               SendWidgetKeyMessage (widget_MSG_KEY_SELECT);
           }
           if (button_pressed (up_button、ui8ButtonState、ui8ButtonChanged))
           {
               SendWidgetKeyMessage (widget_MSG_KEY_UP);
           }
           if (button_pressed (DOWN_Button、ui8ButtonState、ui8ButtonChanged))
           {
               SendWidgetKeyMessage (widget_MSG_KEY_DOWN);
           }
           if (button_pressed (left_button、ui8ButtonState、ui8ButtonChanged))
           {
               SendWidgetKeyMessage (widget_MSG_KEY_LEFT);
           }
           if (button_pressed (right_button、ui8ButtonState、ui8ButtonChanged))
           {
               SendWidgetKeyMessage (widget_MSG_KEY_right);
           }
       }

       //
       //告诉 OTG 库代码经过了多少时间(以毫秒为单位)
       //自上次调用以来。
       //
       USBOTGMain (GetTickms());

       //
       //根据需要调用功能,以使主机或设备模式保持运行。
       //
       if (g_iCurrentUSBMode = eUSBModeDevice)
       {
           USBSerialRun();
       }
       否则、IF (g_iCurrentUSBMode = eUSBModeHost)
       {
           USBStickRun();
       }

       //
       //如果处于日志记录状态,则调用记录器运行函数。  这种情况
       //保持数据采集运行。
       //
       if ((g_iLoggerState == gest_logging)||
          (g_iLoggerState == ARGE_Viewing))
       {
           if (AcquireRun ()& g_sConfigState.ui32Sleep 日志记录)
           {
               //
               //如果启用了睡眠日志记录,则此时我们有
               //存储第一个数据项,现在保存状态并开始
               //休眠。  等待电源切断。
               //
               SetSavedState (&g_sConfigState);
               HibernateWakeSet (HIBERNATE_WAKE_PIN | HIBERNATE_WAKE_RTC);
               HibernateRequest();
               for (;;)
               {
               }
           }

           //
           //如果查看而不是记录,则请求重新喷漆以保留
           //查看窗口已更新。
           //
           if (g_iLoggerState == ARGE_Viewing)
           {
               WidgetPaint (widget_root);
           }
       }

       //
       //如果处于保存状态,则将数据从闪存存储保存到
       // USB 记忆棒。
       //
       if (g_iLoggerState == ARGE_Saving)
       {
           //
           //将数据从闪存保存到 USB
           //
           FlashStoreSave();

           //
           //返回空闲状态
           //
           G_iLoggerState = ARGE_IDLE;
       }

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好、AJ、

    [引用 user="AJ_e"]1)说明必须定期调用。 为什么?[/报价]

    此函数处理不适合计时器的任务、但在 USB 堆栈超时之前需要调用这些任务。 传递的变量用于确定调用之间是否发生超时。

    [引用 USER="AJ_ee "]为什么不在计时器处理程序内调用此函数?

    在这种情况下、周期性地调用并不意味着需要在特定的间隔内调用函数、更重要的是、函数本身不适合从 ISR 中调用、因为它会导致 ISR 长时间处于活动状态。

    描述中没有直接表述这一点:"所有时间关键型操作在中断上下文中处理、但从该函数运行所有更长的操作、以允许它们在不中断的情况下阻止并等待完成。"

    我认为代码中的合作调度注释并不是为了与 RTOS 相关、所以我认为您的类比也不会适用您认为的类比。

    就 RTOS 问题而言、它只需要作为周期性任务来处理。 需要为其分配一个低于时间关键任务的优先级、但也不在梯级的底部。 这正是应用特定的适用范围、但总的来说、您希望避免它经常超时。