<<RT_Thread gd450 学习 >> 三. drv_spi

1.SPI简介

        一般说的SPI(Serial Peripheral Interface)是由Motorola公司定义的接口协议标准,还有一种是SSI(Synchronous Serial Interface)由TI公司定义的接口协议标准。两者的不同主要在NSS信号。

GD的硬件spi默认使用的是摩托罗拉定义的SPI协议。使用SSI时需要打开TI模式。

/* SPI TI mode enable */
void spi_ti_mode_enable(uint32_t spi_periph);
/* SPI TI mode disable */
void spi_ti_mode_disable(uint32_t spi_periph);

2.工程自带drv_spi

        工程里带的spi驱动是真的坑,极不友好。

static struct rt_spi_bus spi_bus[];

static const struct gd32f4_spi spis[] = {
#ifdef RT_USING_SPI0
    {SPI0, RCU_SPI0, &spi_bus[0]},
#endif
    
#ifdef RT_USING_SPI1
    {SPI1, RCU_SPI1, &spi_bus[1]},
#endif

#ifdef RT_USING_SPI2
    {SPI2, RCU_SPI2, &spi_bus[2]},
#endif

#ifdef RT_USING_SPI3
    {SPI3, RCU_SPI3, &spi_bus[3]},
#endif
    
#ifdef RT_USING_SPI4
    {SPI4, RCU_SPI4, &spi_bus[4]},
#endif
    
#ifdef RT_USING_SPI5
    {SPI5, RCU_SPI5, &spi_bus[5]},
#endif
};

static struct rt_spi_bus spi_bus[ARR_LEN(spis)];

     最后一行  static struct rt_spi_bus spi_bus[ARR_LEN(spis)] ;  数组spi_bus 的长度被定义为 数组spis 的长度,当只使用  RT_USING_SPI5 时 数组spi_bus的长度是1,代码中是 引用了spi_bus[5]。 指针越界,当代码运行起来就会发生一些奇妙的事情,让你百思不得其解。

        比较简单粗暴的解决办法是把spi_bus长度定义为 6;

static struct rt_spi_bus spi_bus[6];

static const struct gd32f4_spi spis[] = {
   /****** 省略 *****/
};

3.移植RT_Thread BSP中GD的spi驱动

        3.1 复制粘贴

RT_Thread BSP GD32 driversicon-default.png?t=M666https://gitee.com/rtthread/rt-thread/tree/gitee_master/bsp/gd32/arm/libraries/gd32_drivers       

        复制gd32_drivers 中 drv_spi.c 和drv_spi.h内容粘贴至工程中。

        SPI外设定义的名字和原工程中的有一些不同,需要把文件内所有的BSP_USING_SPI替换成RT_USING_SPI。

#ifdef RT_USING_SPI

#if defined(BSP_USING_SPI0) || defined(BSP_USING_SPI1) || defined(BSP_USING_SPI2)

         bsp中的工程文件把SPI硬件的初始化设置为定义了相应的SPI后便会自动初始化,个人习惯在外部初始化这里简单做了修改。

 3.2 drv_spi.h

/* gd32 spi dirver class */
struct gd32_spi
{
    uint32_t spi_periph;
    char *bus_name;
    rcu_periph_enum spi_clk;
    struct rt_spi_bus *spi_bus;
//    rcu_periph_enum gpio_clk;
//    uint32_t spi_port;
//    uint16_t sck_pin;
//    uint16_t miso_pin;
//    uint16_t mosi_pin;
};

 3.3drv_spi.c 

       3.3.1 更改 spi_bus_obj 

#ifdef RT_USING_SPI0
    {
        .spi_periph = SPI0,
        .bus_name = "spi0",
        .spi_clk = RCU_SPI0,
        .spi_bus = &spi_bus0,

    }
#endif /* RT_USING_SPI0 */

#ifdef RT_USING_SPI1
    {
        .spi_periph = SPI1,
        .bus_name = "spi1",
        .spi_clk = RCU_SPI1,
        .spi_bus = &spi_bus1,
    }
#endif /* RT_USING_SPI1 */

#ifdef RT_USING_SPI2
    {
        .spi_periph = SPI2,
        .bus_name = "spi2",
        .spi_clk = RCU_SPI2,
        .spi_bus = &spi_bus2,
    }
#endif /* RT_USING_SPI2 */

       3.3.2 删除 gd32_spi_init 以及引用

static rt_err_t spi_configure(struct rt_spi_device* device,
                          struct rt_spi_configuration* configuration)
{
    /**** 省略 ****/
    //Init SPI
    //gd32_spi_init(spi_device);
    /**** 省略 ****/
}
//static void gd32_spi_init(struct gd32_spi *gd32_spi)
//{
//  /**** 省略 ****/
//}

       3.3.3 参考SPI0 1 2增加SPI3 SPI4 SPI5功能。

#if defined(RT_USING_SPI0) || defined(RT_USING_SPI1) || defined(RT_USING_SPI2) ||\
    defined(RT_USING_SPI3) || defined(RT_USING_SPI4) || defined(RT_USING_SPI5)
#ifdef RT_USING_SPI3
static struct rt_spi_bus spi_bus3;
#endif
#ifdef RT_USING_SPI4
static struct rt_spi_bus spi_bus4;
#endif
#ifdef RT_USING_SPI5
static struct rt_spi_bus spi_bus5;
#ifdef RT_USING_SPI3
    {
        .spi_periph = SPI3,
        .bus_name =  "spi3",
        .spi_clk = RCU_SPI3,
        .spi_bus = &spi_bus3,

    }
#endif /* RT_USING_SPI3 */

#ifdef RT_USING_SPI4
    {
        .spi_periph = SPI4,
        .bus_name = "spi4",
        .spi_clk = RCU_SPI4,
        .spi_bus = &spi_bus4,
    }
#endif /* RT_USING_SPI4 */

#ifdef RT_USING_SPI5
    {
        .spi_periph = SPI5,
        .bus_name = "spi5",
        .spi_clk = RCU_SPI5,
        .spi_bus =  &spi_bus5,
    }
#endif /* RT_USING_SPI5 */

         3.3.4 修改 gd32_spi_bus_register 函数

/* name  spi0 spi1 spi2 spi3  spi4 spi5 */
static struct rt_spi_bus * rt_spi_bus_find(const char *name)
{
    RT_ASSERT(name);

    int cmp = 0;
    for (int i = 0; i < sizeof(spi_bus_obj) / sizeof(spi_bus_obj[0]); i++)
    {
        cmp =  rt_strcmp(spi_bus_obj[i].bus_name , name);
        if( !cmp )
              return   spi_bus_obj[i].spi_bus;
    }
    return RT_NULL;
}



rt_err_t gd32_spi_bus_register( const char * spi_bus_name )
{
    RT_ASSERT(spi_bus_name);
    struct rt_spi_bus *spi_bus = RT_NULL;
    spi_bus = rt_spi_bus_find(spi_bus_name);
    rt_spi_bus_register(spi_bus, spi_bus_name, &gd32_spi_ops);
}

搞完收工,spi dma传输后面会继续加上去。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值