如何从linux内核内部生成稳定的37kHz GPIO触发器?

如何从linux内核内部生成稳定的37kHz GPIO触发器?,linux,linux-kernel,interrupt,kernel-module,gpio,Linux,Linux Kernel,Interrupt,Kernel Module,Gpio,目前我有一个微控制器负责红外TX载波的生成,但我开始怀疑是否可以处理它,并在linux端完成这项工作,从而降低了嵌入式系统的成本 我在飞思卡尔I.mx233(454MHz ARM9)上运行,如果我直接通过/dev/mem访问注册表,我可以实现相当稳定的5MHz GPIO引脚触发 由于我需要37kHz,我开始寻找减慢速度的方法,但至少nanowait()对于这个目的来说太粗糙了。 我找到了一个在for循环中调用rand()的解决方案,我似乎能够很好地生成38,4kHz的信号,但是根据示波器,有时会

目前我有一个微控制器负责红外TX载波的生成,但我开始怀疑是否可以处理它,并在linux端完成这项工作,从而降低了嵌入式系统的成本

我在飞思卡尔I.mx233(454MHz ARM9)上运行,如果我直接通过
/dev/mem
访问注册表,我可以实现相当稳定的5MHz GPIO引脚触发

由于我需要37kHz,我开始寻找减慢速度的方法,但至少
nanowait()
对于这个目的来说太粗糙了。 我找到了一个在for循环中调用rand()的解决方案,我似乎能够很好地生成38,4kHz的信号,但是根据示波器,有时会出现一些不可接受的抖动。(我知道这是相当浪费资源的,但是当需要发送时,系统实际上没有其他任务)

我的问题是: Freescales内核代码(3.8分支)没有CONFIG\u PREEMPT\u RT补丁,所以这可能是我应该研究的一件事,但在此之前:

  • 我是否可以通过编写内核模块从内核内部驱动GPIO来实现更精确的性能?我确实需要从用户空间读取一些数据(要发送的数据),但除此之外,我只需要在GPIO结束时以指定频率触发led,因此驱动程序应该非常简单

  • 我可以强制驱动程序的优先级,以便其他任务不会中断此gpio触发吗?(数据发送目前大约需要400毫秒,而且很少完成)

  • 有没有更好的方法来创建一个中断,比如说每37kHz一次,这样我就不会因为SW而使系统失速


微控制器是这类任务的完美选择,但如果可能的话,最好避免这种成本开销

获得37 kHz信号的最佳方法是找到一些可以在硬件中生成信号的串行/音频/PWM输出

提高用户空间进程的优先级是可能的,但这无助于防止中断或高优先级内核任务。 RT内核允许您获得比更多内核任务更高的优先级,但不能帮助您抵御所有中断。 我不知道您是否能够获得低于37 kHz(27µs)的最大延迟;我认为不太可能

在内核中这样做会有所帮助,因为您可以禁用中断处理。 然而,禁用中断长达400毫秒是不可取的。

在“多芯片连接模式”下的i.MX23 PWM正是针对这一要求而设计的

例如,假设您使用的是24Mhz时钟,则在“多芯片连接模式”下使用其中一个PWM

  • MATT=1(启用多芯片连接模式)
  • MATT_SEL=1(用户24Mhz时钟)
  • CDIV=0x2(或DIV_4,即除以4)
  • 非活动状态=0x2或0x3
  • 活动状态=0x3或0x2
  • 周期=175(即176-1)
  • 如果使用32Mhz时钟,则需要其他CDIV和周期参数才能达到34Khz

    有关示例代码,请参阅“i.MX23应用程序处理器参考手册”。如果我没有弄错的话,驱动程序代码位于
    arch/arm/plat mxc/pwm.c
    中,但它似乎不支持MATT模式。您可能需要自己扩展代码

    关于实施——

    以上答案仅与CPU有关。在实践中,实现这一想法的能力取决于电路板的设计。该板需要一个连接到GPIO引脚的头(外部连接引脚),GPIO引脚可以通过pinmux连接到一个PWM。我假设大多数参考设计至少有一个PWM可配置GPIO通过报头公开。问题是,如果只有一个,并且您已经将其用于其他控制目的

    确定存在具有空闲PWM可配置GPIO的收割台后,需要配置引脚mux并激活PWM。上述处理器参考手册中有相关说明。大多数系统在引导加载程序board_init()(假设U-boot)中进行此配置,但在Linux引导后,也可以在用户空间中使用一些
    mmap
    技巧进行此配置

    最后,您需要根据
    platform-mxc_PWM.c
    中的PWM模块接口编写驱动程序

    如果您使用的是i.MX23 EVK 10.05,您可能能够修改LED PWM驱动程序,因为它已经在引导加载程序和内核级别进行了配置,并将您的设备连接到LED输出,而不是LED。(您需要一名硬件技术人员来帮助您完成这项工作。)请确保使用config_LEDS_mx配置内核

    由于我不知道EVK,上面关于实现的评论有些推测。也许知道这一点的人可以改进这一点


    2013年9月21日更新
    使用i.MX23或具有类似ARM CPU内核的任何SoC生成37kHz信号的另一种方法是使用未使用的片上定时器以所需频率生成FIQ中断,并写入FIQ中断处理程序以切换GPIO引脚。今年4月30日,Maxime Ripard在他的自由电子博客上发表了一篇关于使用i.MX28 SoC的这种方法的文章。要使用此方法,您需要一个未使用的计时器,并且不要将FIQ中断用于其他目的,例如使用ARM FIQ的SPI、摄像头或限电检测驱动程序之一。您还需要在ARM汇编程序中编写ISR。

    Jonathan,这看起来确实很有趣。但是,我真的很困惑如何使用这个。。关于如何开始测试,你有什么建议吗?在Freescales 3.8内核源代码中,似乎存在
    /arch/arm/mach-imx/devices/platform-mxc_-pwm.c
    ——但我真的不知道该如何开始。。似乎可以在dtb中定义pwm设备?这是我应该做的吗?