首页 文章

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

提问于
浏览
2

我现在有一个微控制器负责处理红外TX载波产生,但我开始想知道我是否可以处理它,并在linux端做这项工作 - 从而降低了嵌入式系统的成本 .

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

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

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

  • 我可以通过编写内核模块从内核中驱动GPIO来获得更准确的性能吗?我确实需要从用户空间读取一些数据(要发送的数据),但除此之外,我只需要在GPIO末尾触发指定频率的LED,因此驱动程序应该非常简单 .

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

  • 是否有更好的方法来创建一个每37kHz的中断,这样我就不会使SW停止系统?

微控制器非常适合这类任务,但如果可能的话,避免这种成本开销会很好......

2 回答

  • 0

    “多芯片连接模式”中的i.MX23 PWM完全符合此要求 .

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

    • MATT = 1(启用多芯片附加模式)

    • MATT_SEL = 1(用户24Mhz时钟)

    • CDIV = 0x2(或DIV_4,即除以4)

    • INACTIVE_STATE = 0x2或0x3

    • ACTIVE_STATE = 0x3或0x2

    • PERIOD = 175(即176-1)

    如果您使用32Mhz时钟,则需要其他CDIV和PERIOD参数才能达到34Khz .

    有关示例代码,请参阅"i.MX23 Applications Processor Reference Manual" . 如果我没有弄错,驱动程序代码在 arch/arm/plat-mxc/pwm.c 但它似乎不支持MATT模式 . 您可能需要自己扩展代码 .

    关于实施 -

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

    在确定存在具有自由PWM可配置GPIO的报头后,您需要配置引脚复用器并激活PWM . 上面提到的处理器参考手册中有相关说明 . 大多数系统在引导加载程序 board_init() (假设U-boot)中执行此配置,尽管它可能在用户空间中也可以在Linux启动后使用一些 mmap 技巧完成 .

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

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

    由于我不了解EVK,因此上述关于实施的评论有些推测 . 也许知道它的人可以改善这一点 .


    2013年9月21日更新

    使用i.MX23或具有类似ARM CPU内核的任何SoC生成37kHz信号的另一种方法是使用未使用的片上定时器以所需频率生成FIQ中断并写入FIQ中断处理程序以切换GPIO销 . 今年4月30日,Maxime Ripard在他的Free Electrons博客上使用i.MX28 SoC发布了这种方法的complete example . 要使用此方法,您将需要两者未使用的定时器,而不是将FIQ中断用于其他目的,例如使用ARM FIQ的SPI,摄像头或掉电检测驱动器之一 . 您还需要在ARM汇编程序中编写ISR .

  • 2

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

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

    在内核中执行此操作会有所帮助,因为您可以禁用中断处理 . 但是,禁用长达400毫秒的中断是不受欢迎的 .

相关问题