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

目前我有一个微控制器负责处理红外TX载波的产生,但是我开始想知道是否可以处理它,并在Linux端做这个工作 – 这样就降低了embedded式系统的成本。

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

由于我需要37kHz,我开始寻找放慢速度的方法,但是至less对于这个目的, nanowait()似乎太粗糙了。 我find了一个在rand循环中调用rand()的解决scheme,我似乎可以很好地生成38.4kHz的信号,但是根据示波器,有时会出现一些不可接受的抖动。 (据我所知,这样做对于资源来说是相当浪费的,但是当TX需要完成的时候,系统并没有真正的其他任务)

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

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

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

  • 有没有更好的方法来创build每37kHz的中断,这样我就不会通过软件停止系统?

微控制器是完成这种任务,但如果可能的话,这将是很好的避免这种成本开销…

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

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

  1. MATT = 1(启用多芯片连接模式)
  2. MATT_SEL = 1(用户24Mhz时钟)
  3. CDIV = 0x2(或DIV_4,即除以4)
  4. INACTIVE_STATE = 0x2或0x3
  5. ACTIVE_STATE = 0x3或0x2
  6. PERIOD = 175(即176-1)

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

示例代码参见“i.MX23应用处理器参考手册”。 如果我没有弄错,驱动代码是在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销。 Maxime Ripard在今年4月30日在他的Free Electrons博客上发表了一个使用i.MX28 SoC的完整示例 。 要使用这种方法,您将需要一个未使用的定时器,并且不要将FIQ中断用于其他目的,例如使用ARM FIQ的SPI,相机或掉电检测驱动程序之一。 您还需要在ARM汇编器中编写ISR。

得到37 kHz信号的最好方法是找到一些可以用硬件产生的串行/音频/ PWM输出。

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

在内核中这样做会有帮助,因为你可以禁止中断处理。 然而,禁止400毫秒的中断是不被接受的。