【问题标题】:Multithreading using C on PIC18在 PIC18 上使用 C 进行多线程
【发布时间】:2010-12-10 02:26:57
【问题描述】:

由于没有操作系统,如何在编程PIC18 时创建并行运行的线程?

【问题讨论】:

  • 你用的是什么编译器?有些具有用于此目的的功能。
  • 单独的执行上下文在没有操作系统的情况下是可能的,使用诸如定时器中断或其他基于事件的中断之类的技巧,但是 线程:没有操作系统是不可能的。
  • 您使用的是占用空间小的 RTOS。
  • 这个问题真的很开放。

标签: c multithreading embedded pic pic18


【解决方案1】:

Protothreads 库是多任务、跨平台的简单方法:http://dunkels.com/adam/pt/

具有任务同步、计时器和用户数据的 PT 最小调度程序示例:https://github.com/edartuz/c-ptx

【讨论】:

    【解决方案2】:

    我正在做(严格来说,在固定调用堆栈深度的协作式多任务处理)。

    它有效,但 Hitec-c 编译器对我不利——它重用内存位置来存储它认为永远不会同时运行的函数中的临时变量。基本上线程会相互破坏。如果我想办法解决这个问题,我会用示例代码更新这个答案。

    【讨论】:

      【解决方案3】:

      我想分享我用 C 编程语言编写的微型内核来管理微控制器上的任务。您可以随时创建带周期的任务、暂停、恢复和更改任务周期。该内核可以根据需要删除所有任务以创建另一个音序器。 内核提供了一个 TickGet 函数来根据需要管理所有计时器。 您只需创建一个中断函数并替换函数 Timer() 即可为您自己的应用程序获取微型内核。 恢复这个内核是基于循环链表,在任务上切换任务。它很乐意以一种通用的方式编写,以帮助人们为自己的应用程序进行定制。任务之间没有优先级,就像循环任务调度一样。我根据 MISRA 指南(汽车规范)编写了这个源代码 可以下载here

      我希望帮助人们在微控制器上管理任务。

      【讨论】:

        【解决方案4】:

        在 8051 上,我使用简单的堆栈切换器完成了双重任务。如果每个任务只使用 16 层堆栈,我希望在 PIC 上也可以这样做。代码将是这样的(假设 _altSP 在公共银行中)

        _InitTask2: movff _STKPTR,_altSP movlw 16 movwf _STKPTR,c 转到_Task2Start _TaskSwitch: movf _altSP,w,c movff _STKPTR,_altSP movwf _STKPTR,c 返回

        主任务应该调用 _InitTask2 来启动第二个任务。第二个任务将一直运行,直到它调用_TaskSwitch,然后主任务将按照调用_InitTask2 的指令继续执行。从那时起,每次一个任务调用_TaskSwitch,另一个任务将从它上次调用_TaskSwitch的地方恢复执行。

        如果您使用这种方法,您的编译器将必须被告知所有寄存器都可能因调用 _InitTask2 或 _TaskSwitch 而被丢弃。还必须告知 _Task2Start 及其调用的函数必须与主任务分配不同的变量空间。

        我不确定你需要告诉编译器什么让它开心,但我会说合作的双任务可以让一些事情很好地工作。

        【讨论】:

        • This 应用说明指出,如果内核不是 PIC18,则无法访问堆栈指针。我不知道组装并试图了解简单的(s)大头钉切换器。这是否意味着我希望用 PIC12 和 PIC16 创建一个简单的任务切换器是无稽之谈?
        • @abdullahkahraman:在 PIC12 或 PIC16 上执行多任务代码的唯一方法是要求只有一个任务可以在嵌套子例程中执行任务切换。顺便说一句,我曾经在一个基于 PIC165x 的芯片上做了一个很好的任务切换应用程序,除了 I/O 分配之外,这两个任务几乎相同。每个任务使用一组存储寄存器。效果非常好。
        【解决方案5】:

        我同意 ndim 的观点——您可以将每个中断处理程序视为类似“线程”的东西。 有时你需要做的所有任务都可以由外部和内部事件触发的中断处理程序来处理——“主循环”是一个不做任何事情的空闲循环。

        我不知道有些评论者从哪里得到 PIC18 没有“操作系统”的想法。 PIC18 有很多特定于 PIC 的多线程库和“多任务操作系统内核”,其中许多是免费和开源的。见PICList: "PIC Microcontroller specific Multitasking Methods"

        【讨论】:

          【解决方案6】:

          这就是一个任务循环,以及提供任务的优先级,以及我喜欢将长时间运行的函数分解为切片的简单编码。

          http://www.mculabs.com/drivers/qtask.html

          【讨论】:

            【解决方案7】:

            CCS 编译器包含一个 RTOS。我没用过,但是来自compiler manual

            CCS 实时操作系统 (RTOS) 允许 PIC 微控制器 运行定期计划的任务 无需中断。这 由一个函数完成 (RTOS_RUN()) 作为一个 调度员。计划任务时 运行,调度函数给出 处理器对该任务的控制。 当任务完成执行或 不再需要处理器, 返回处理器的控制权 到调度功能,然后 将控制处理器 计划的下一个任务 在适当的时候执行。这 过程称为合作 多任务处理。

            只是一个警告-查看他们的论坛以获取有关您正在寻找的特定功能的信息。显然 CCS 习惯于在新功能经过全面测试之前发布它们。这就是我仍在使用旧版本 (v3.249) 的原因之一。

            【讨论】:

              【解决方案8】:

              您可能想从嵌入式系统编程阅读这篇文章: Build a Super Simple Tasker

              【讨论】:

                【解决方案9】:

                请注意,在微控制器上,某些“线程”也可以仅由某些特定的中断处理程序处理,因此无论如何都与您的主事件循环“并行”运行。

                例如如果您有外部事件触发 ADC 转换,您的 ADC-conversion-done 处理程序可以获取该值,进行一些计算,然后设置一些输出位以根据 ADC 值调整控制输出。所有这些都可能发生在中断处理程序中,因此与其他所有事情并行。

                根据您需要并行执行的操作,您可以选择多种技术的组合,以使工作按预期并行工作。

                【讨论】:

                  【解决方案10】:

                  如果根本没有操作系统,您(显然)必须自己重新创建必要的功能。

                  最简单的方法可能是安装一个以某个合适频率运行的定时器中断(可能取决于您的实际时钟速度,但可能在 100-1000 Hz 范围内)。在中断处理程序中,您需要检查当前线程的状态,并决定是否应该进行切换。

                  诀窍是在必要时进行切换,并从中断处理程序返回到不同的线程

                  当然,在线程本身可能使用中断的情况下让它工作并不一定容易。

                  你也可以考虑安装一些内核,也许是Contiki

                  Here 是 PIC18 的“protothreads”示例,看起来是相当数量的代码。不过,不确定语义。

                  更新:这可能需要您在汇编程序中执行一些最低级别的代码(我不确定,在 PIC 上没有用 C 语言工作,所以我不太清楚你有多少控制权)。您将需要控制程序计数器的寄存器,而这些不是 C 概念。

                  【讨论】:

                    【解决方案11】:

                    不要使用线程,使用事件循环。

                    PIC18 是一个小型处理器,基于事件循环的风格意味着您不必保留许多深堆栈。您需要根据事件循环编写代码,但这可能是合理的。

                    如果你确实有一些长时间运行的任务,使用定时器是不同的中断优先级,以允许较高优先级的事件循环抢占较低优先级的事件循环,并将适当类型的工作放入适当的事件队列中。

                    【讨论】:

                    • 同意。如果它满足您的需求,请保持简单。
                    • 请注意,这是假设异步 I/O。如果您的主程序在某些 I/O 上被阻塞,这将无济于事。使用线程和简单的基于时间的循环任务切换,您可以解耦各种任务,确保它们的时间量很小但时间不变。
                    • 这是一个PIC18芯片,需要在某个地方实现线程,并且需要存储它们的状态。几乎所有你能做的 I/O 都可以以某种方式异步完成;如果您开始进行同步 I/O,则必须禁用中断以提高可靠性,然后无论如何您都不会被抢占。您可以在芯片的异步功能之上实现线程库和调度程序,但何苦呢?您可能只有不到 4kB 的 RAM,而且时间关键的操作很可能是 I/O 驱动的。只需将 PIC18 视为一个硬件实现的、非常简单的操作系统。
                    • 我理解为什么人们说这不是你会做的事情,但是 RTOS 通过使用 RTOS 隔离线程大大提高了编程质量。在复杂的安全关键代码中,RTOS 可以为工程师团队节省数月的时间,使用经过安全关键认证的 RTOS 可以节省超过 6 位数的时间。
                    • @Kortuk 当然,在复杂且对安全至关重要的代码中,除了“我如何处理线程?”之外,还有其他因素。一个从事安全关键项目的工程师团队往往不会问“我如何做线程”,而是会问,就像你在电子产品上所做的那样,“你能告诉我你在这些方面的 RTOS 经验吗?”话虽如此,我已经使用事件循环结构在经过认证的设备上实现了安全关键代码,并对结果感到满意。但是,该决定取决于许多因素,而不仅仅是“x 好,y 坏”。
                    【解决方案12】:

                    你可以试试Cooperative multitasking

                    对于 PIC 解决的问题类型,如果您尝试使用中断或轮询而不是多线程的不同设计,您可能会更好。

                    【讨论】:

                    • 仅供参考,我刚刚发布了一些代码来说明协作式多任务处理是多么简单。我没有在PIC18上做过,但是我在8051和TI DSP平台上做过。
                    【解决方案13】:

                    你可以在那里安装一个 RTOS(有an unofficial ucOS port,或者你可以查看FreeRTOS's PIC18 port)。

                    否则,您可以尝试使用setjmplongjmp 来实现coroutines in C

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2013-08-03
                      • 1970-01-01
                      • 2021-07-21
                      • 2017-07-20
                      • 1970-01-01
                      • 1970-01-01
                      • 2023-03-12
                      • 2020-08-03
                      相关资源
                      最近更新 更多