在linux之外为Cortex-A7启用SPI控制器

时间:2016-04-15 23:04:55

标签: c embedded device-driver soc

我有一个使用A20-OLinuXino-MICRO-4GB board的软件项目。我无法控制使用哪个电路板,因此有关替代电路的建议没有帮助。

拥有Allwinner A20双核Cortex-A7处理器(armv7a)。

我尝试从linux开始工作,但即使具有最高优先级PTHREAD_EXPLICIT_SCHED和SCHED_FIFO,我也无法阻止控制代码的时间关键部分的中断(需要每10微秒处理一次,但是有40微秒的间隙约40次一秒钟。

由于上述限制,从linux访问SPI和UART的建议也没有帮助。第二个线程(整个cpu核心专用于它)的时序约束意味着常规linux目前不是一个可行的选择。也许一个完整的实时Linux可以完成这项工作,但是我没有足够的资源来构建它,只是为了看它是否可能工作。

当前的开发环境:

Gentoo 4.3.3-hardened-r4
crossdev --kernel =3.18 --libc =2.21-r2 --binutils =2.24-r3 --gcc =4.8.5 

构建u-boot目前不适用于5.x版本的gcc,因此没有太多空间可以移动到那里。

因此转而编写为从u-boot启动的独立代码。没有额外的延迟,但现在我错过了配置核心的其他模块的东西。当我尝试初始化和配置SPI或UART设备(UART0,用于u-boot控制台除外)时,所有寄存器都报告为零,并在设置后保持在那里。它就像没有任何东西(没有硬件)那样。 UART0具有合理/预期的值,配置标准GPIO引脚(输入和输出)工作正常。配置SPI或UART使用的多路复用GPIO引脚似乎也可以工作,但模块固执地拒绝承认它们存在。

可以找到用于尝试与SPI模块通信的示例代码,Makefile和输出in the olimex forum。 请注意,该示例使用来自u-boot构建的包含文件 用于创建该代码的主要文档是A20 User Manual

有没有人使用A20,Cortex-A7,armv7a或类似芯片,并想出如何访问linux以外的功能?

有人知道从哪里获得有关该级别编程的更好文档吗?

我的用户手册有很多关于寄存器地址,偏移量,位掩码的信息,但没有任何代码示例。我希望一个简单的独立C(甚至汇编程序)示例,配置任何(设备)模块,并设置一个中断来处理它,将这样有助于搞清楚其余部分。 / p>

我实际上通过对I / O引脚进行位冲击来实现SPI通信。这对于UART来说不起作用,而SPI看起来更像是一个更简单的情况。

我已经在大型系统上编程了很多年,有些在非常小的(6502,8085,arduinio)系统上编程,但在这种环境中没有真正的开发经验。我不是内核程序员,也不是任何接近的程序员。

编辑: 我将SPI1时钟设置添加到示例代码中,但所有SPI寄存器在设置之前和之后仍然显示为全零。代码更改:

#include <asm/arch-sunxi/clock_sun4i.h>
struct sunxi_ccm_reg * clockRegister;
#define SPI_SCLK_GATING_CLKON   0x80000000
#define SPI_CLK_SRC_OSC24M      0x00000000
#define SPI_CLK_DIV_RATION_8    0x00030000
// ...
printf ("SPI1 clk cfg %08x\n", clockRegister->spi1_clk_cfg);
clockRegister->spi1_clk_cfg =
  SPI_SCLK_GATING_CLKON | SPI_CLK_SRC_OSC24M | SPI_CLK_DIV_RATION_8 | 15;
printf ("SPI1 clk cfg %08x\n", clockRegister->spi1_clk_cfg);

这表明时钟配置DID从0x00000000变为0x8003000f

1 个答案:

答案 0 :(得分:0)

我也发了这个问题 Microcontroller Based Projects google +社区,Nikolai Kondrashov(spbnick)发现并正确解释了文档中的一大堆信息。

要访问SPI寄存器,必须设置AHB_GATTING_REG0中SPI«n»位的门控AHB时钟和SPI«n»_CLK_REG中的SCLK_GATING位。一旦设置好,SPI«n»模块寄存器就可以访问。

可能令人困惑的注意事项:首先设置AHB门控位,然后在设置SCLK门控位之前尝试引用SPI寄存器会导致完全冻结。因为在工作应用程序中,通常会将它们设置在一起,这通常不是问题。只显示调试输出,检查SPI寄存器何时可见。

我仍然觉得文档缺乏。一些代码示例会对其进行大量改进。这一发现可能足以访问大多数SoC模块/设备。

相当简单的示例代码。这适用于原始问题显示的相同Makefile。其中包含一个额外的u-boot包含文件。

#include <common.h>

// Global memory pointers
uint32_t
    (*SPIarry1)[11],
    *SPI1_Cfg,
    *AHB_Gate0,
    *SPI1_ClkCfg;

int spi_test (void);

int spi_test (void)
{
    AHB_Gate0 = (uint32_t *)(SUNXI_CCM_BASE + 0x60);
    SPI1_ClkCfg = (uint32_t *)(SUNXI_CCM_BASE + 0xa4);
    SPIarry1 = (uint32_t (*)[11])SUNXI_SPI1_BASE;

    printf ("SPI1 Cfg Reg 0x%08x\n", (*SPIarry1)[2]);
    *SPI1_ClkCfg = 0x80000000;
    printf ("SPI1 Cfg Reg 0x%08x\n", (*SPIarry1)[2]);
    *AHB_Gate0 |= 0x00200000;
    printf ("SPI1 Cfg Reg 0x%08x\n", (*SPIarry1)[2]);
    return (0);
}

捕获的示例程序输出

## Starting application at 0x42000000 ...
SPI1 Cfg Reg 0x00000000
SPI1 Cfg Reg 0x00000000
SPI1 Cfg Reg 0x0012001c
## Application terminated, rc = 0x0