0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

【S32K146 RT-thread】之 SPI驱动适配

RT-Thread官方账号 2024-11-01 08:11 次阅读

概述

RT-Thread 对SPI总线的驱动,抽象出了spi bus 的设备驱动,我们基于S32K146 的硬件学习spi bus 设备驱动。

SPI总线驱动适配

驱动涉及的主要结构体为如下:

rt_spi_device:app 通过该结构体和bus 绑定通过bus 控制spi总线

rt_spi_bus spi bus总线设备抽象

rt_spi_ops bus设备依赖的底层操作函数

结构体关系如下:

c7eba39e-97e5-11ef-8084-92fbcf53809c.jpg

对于总线设备的驱动对接我们需要实现对应的ops函数。

使用S32 Design Studio 工具配置spi1

本次实验使用的是lpspi1 ,首先使用S32 Design Studio 工具生成pinmux 和 clk 初始化配置代码。

配置SPI1 master 参数

c7f25e8c-97e5-11ef-8084-92fbcf53809c.jpg

配置pimmux

c80a97cc-97e5-11ef-8084-92fbcf53809c.jpg

配置clk

c8329c68-97e5-11ef-8084-92fbcf53809c.jpg

适配SPI1 ops 函数至RT-Thread

根据上面的梳理,依赖芯片层实现ops函数并开启spi设备驱动

c8394306-97e5-11ef-8084-92fbcf53809c.png

config ops函数

tatic rt_err_t spi_configure(struct rt_spi_device* device,
struct rt_spi_configuration* configuration)
{
struct rt_spi_bus * spi_bus = (struct rt_spi_bus *)device->bus;
struct s32k_spi *spi_device = (struct s32k_spi *)spi_bus->parent.user_data;
status_t ret;


RT_ASSERT(device != RT_NULL);
RT_ASSERT(configuration != RT_NULL);


/* config spi init spi bus */
//LPSPI_DRV_MasterDeinit(spi_device->instance);


switch(configuration->mode & RT_SPI_MODE_3)
{
case RT_SPI_MODE_0:
spi_device->masterconfig->clkPhase = LPSPI_CLOCK_PHASE_2ND_EDGE;
spi_device->masterconfig->clkPolarity = LPSPI_SCK_ACTIVE_LOW;
break;
case RT_SPI_MODE_1:
spi_device->masterconfig->clkPhase = LPSPI_CLOCK_PHASE_1ST_EDGE;
spi_device->masterconfig->clkPolarity = LPSPI_SCK_ACTIVE_LOW;
break;
case RT_SPI_MODE_2:
spi_device->masterconfig->clkPhase = LPSPI_CLOCK_PHASE_2ND_EDGE;
spi_device->masterconfig->clkPolarity = LPSPI_SCK_ACTIVE_HIGH;
break;
case RT_SPI_MODE_3:
spi_device->masterconfig->clkPhase = LPSPI_CLOCK_PHASE_1ST_EDGE;
spi_device->masterconfig->clkPolarity = LPSPI_SCK_ACTIVE_HIGH;
break;
}


/* MSB or LSB */
if(configuration->mode & RT_SPI_MSB)
{
spi_device->masterconfig->lsbFirst = false;
}
else
{
spi_device->masterconfig->lsbFirst = true;
}


if(configuration->max_hz < 10000000)
spi_device->masterconfig->bitsPerSec = configuration->max_hz;


spi_device->masterconfig->bitcount = configuration->data_width;


ret = LPSPI_DRV_MasterInit(spi_device->instance,spi_device->status,spi_device->masterconfig);
RT_ASSERT(ret == STATUS_SUCCESS);


ret = LPSPI_DRV_MasterSetDelay(spi_device->instance, 1, 1, 1);
RT_ASSERT(ret == STATUS_SUCCESS);


return ret == STATUS_SUCCESS ? RT_EOK:RT_ERROR;

xfer ops 函数

truct s32k_spi
{
struct rt_spi_bus spi_bus; /* spi bus device */
lpspi_master_config_t * masterconfig; /* lpspi master config */
lpspi_state_t * status; /* lpspi driver status */
uint32_t instance; /* spi instance id */
char * bus_name;
}s32k_spi_t;


static rt_ssize_t spixfer(struct rt_spi_device* device, struct rt_spi_message* message){
struct rt_spi_bus * spi_bus = (struct rt_spi_bus *)device->bus;
struct s32k_spi *spi_device = (struct s32k_spi *)spi_bus->parent.user_data;
status_t ret;


RT_ASSERT(device != NULL);
RT_ASSERT(message != NULL);




ret = LPSPI_DRV_MasterTransferBlocking(spi_device->instance,message->send_buf,message->recv_buf,message->length,1000);
RT_ASSERT(ret == STATUS_SUCCESS);


return ret == STATUS_SUCCESS ? message->length:0;

添加如下初始化代码像系统注册spibus设备

xtern void LPSPI_DRV_IRQHandler(uint32_t instance);


void S32K14X_LPspi1_Master_Slave_IRQHandler(void){
/* enter interrupt */
rt_interrupt_enter();


LPSPI_DRV_IRQHandler(1);


/* leave interrupt */
rt_interrupt_leave();
}


/* private rt-thread spi ops function */
static struct rt_spi_ops s32k_spi_ops =
{
.configure = spi_configure,
.xfer = spixfer,
};


static struct s32k_spi spi1;




int rt_hw_spi_init(void){
int result = 0;


/* config spi strruct */
spi1.instance = INST_LPSPI_1;
spi1.masterconfig = &lpspi_1_MasterConfig0;
spi1.status = &lpspi_1State;
spi1.spi_bus.parent.user_data = (void *)&spi1;
spi1.bus_name = "spi1";


result = rt_spi_bus_register(&spi1.spi_bus, spi1.bus_name, &s32k_spi_ops);


RT_ASSERT(result == RT_EOK);


LOG_D("%s bus init done", spi1.bus_name);


if(result == RT_EOK)
{
INT_SYS_InstallHandler(LPSPI1_IRQn,S32K14X_LPspi1_Master_Slave_IRQHandler,NULL);
}




return result;
}


INIT_APP_EXPORT(rt_hw_spi_init);

验证

添加如下测试代码输入 spi10 open/config/readid 命令打开并挂载到spi1总线,并读取板子上的spi flash 的id信息

include
#include
#include
#include
#include


#define SPF_R_JEDEC_CMD (0x9Fu)
#define SPF_R_JEDEC_LEN (4u)


struct rt_spi_device spi1_device;


static void spi10(int argc,char *argv[]){
rt_err_t ret;
struct rt_spi_configuration cfg;
uint8_t sendbuff[4] = {SPF_R_JEDEC_CMD,0x00,0x00,0x00};
uint8_t recvbuff[4] = {0x00,0x00,0x00,0x00};


if(!strcmp(argv[1], "readid"))
{
rt_spi_transfer(&spi1_device,sendbuff,recvbuff,4);
rt_kprintf("read did [%x][%x][%x]\n",recvbuff[1],recvbuff[2],recvbuff[3]);
}
else if(!strcmp(argv[1], "open"))
{
ret = rt_spi_bus_attach_device(&spi1_device,"spi10","spi1",NULL);
if(ret != RT_EOK)
rt_kprintf("attach spi1 faied %d\n",ret);
}
else if(!strcmp(argv[1], "config"))
{
cfg.data_width = 8;
cfg.max_hz = 8000000;
cfg.mode = RT_SPI_MODE_3 | RT_SPI_MSB;
rt_spi_configure(&spi1_device,&cfg);
}
else if(!strcmp(argv[1], "read"))
{


}
}
MSH_CMD_EXPORT(spi10,spi10flashtest)

输入命令验证已经读取到flash 的Id 信息说明SPI 总线和spi flash 通信ok ,而且系统内也已经多了spi1 bus设备和spi10 的spi 设备节点。

c84fc220-97e5-11ef-8084-92fbcf53809c.jpg

试验读取的did和芯片手册的也是一致的。

c8564b7c-97e5-11ef-8084-92fbcf53809c.jpg

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • SPI总线
    +关注

    关注

    4

    文章

    103

    浏览量

    27569
  • 设备驱动
    +关注

    关注

    0

    文章

    68

    浏览量

    10875
  • RT-Thread
    +关注

    关注

    31

    文章

    1271

    浏览量

    39902
收藏 人收藏

    评论

    相关推荐

    RT-Thread NUC97x 移植 LVGL

    不涉及 rt-thread 驱动,但是它是 LVGL 和 rt-thread 的接口。LVGL 在 rt-thread 上运行的基石。
    发表于 07-08 09:37 1466次阅读

    基于RT-ThreadSPI通讯

         sdk 目前还不支持 spi,没有 spi 就失去了很多乐趣,如 easyflash、spi 的屏幕,蓝讯的这次活动我接到了模拟 spi 的任务,下面介绍如何写
    的头像 发表于 08-22 09:28 1652次阅读

    RT-Thread ssd1306驱动

    RT-Thread 驱动ssd1306
    的头像 发表于 04-21 10:08 26.4w次阅读
    <b class='flag-5'>RT-Thread</b> ssd1306<b class='flag-5'>驱动</b>

    S32K146的hard fault问题解决方案

    最近有个客户使用S32K146的产品在量产之后出现了三个售后件,ABBA测试之后的结果表明失效现象跟着S32K146走;同时客户反馈说试着将其中一个售后件重新烧录程序,S32K146又正常工作了。结合这两种情况,
    的头像 发表于 11-22 11:35 2215次阅读
    <b class='flag-5'>S32K146</b>的hard fault问题解决方案

    基于MM32F5270开发板RT-Thread SPI驱动适配指南

    1、第一次给RT-Thread添加芯片SPI驱动  为MM32F5370开发板添加SPI驱动支持的过程。
    发表于 09-02 14:59

    如何使用RT-Thread SPI设备驱动

    RT-Thread中引入了SPI设备驱动框架。本文说明了如何使用RT-Thread SPI设备驱动
    发表于 10-25 14:20

    RT-Thread编程指南

    RT-Thread编程指南——RT-Thread开发组(2015-03-31)。RT-Thread做为国内有较大影响力的开源实时操作系统,本文是RT-Thread实时操作系统的编程指南
    发表于 11-26 16:06 0次下载

    RT-ThreadSPI的细节内容

    作为通信协议的两大基础,IIC和SPI两者的应用都非常广泛,上一篇文章讲过了RTT上IIC的移植与实践。 《一步到位!教你RT-Thread上设备IIC驱动移植》 讲完IIC,自然少不了SPI
    的头像 发表于 09-30 15:35 3838次阅读
    <b class='flag-5'>RT-Thread</b>上<b class='flag-5'>SPI</b>的细节内容

    RT-Thread (2) RTT SPI设备驱动流程 || LWIP + ENC28J60

    系列文章目录RT-Thread (1) 添加外部内存到内存管理RT-Thread (2) RTT SPI设备驱动流程 || LWIP + ENC28J60目录0 概述0.0 参考资料0
    发表于 11-19 14:21 15次下载
    <b class='flag-5'>RT-Thread</b> (2) RTT <b class='flag-5'>SPI</b>设备<b class='flag-5'>驱动</b>流程 || LWIP + ENC28J60

    RT-Thread Studio驱动SD卡

    RT-Thread Studio驱动SD卡前言一、创建基本工程1、创建Bootloader2、创建项目工程二、配置RT-Thread Settings三、代码分析1.引入库2.读入数据四、效果验证
    发表于 12-27 19:13 20次下载
    <b class='flag-5'>RT-Thread</b> Studio<b class='flag-5'>驱动</b>SD卡

    RT-Thread低功耗的适配和应用

    近期 RT-Thread 工程师完成了基于瑞萨 CPK-RA2L1 开发板的BSP适配,支持了GPIO、UART、I2C、SPI、ADC、DAC、PWM、CAN、on-chip Flash
    的头像 发表于 08-03 10:29 2430次阅读

    RT-Thread文档_RT-Thread 简介

    RT-Thread文档_RT-Thread 简介
    发表于 02-22 18:22 5次下载
    <b class='flag-5'>RT-Thread</b>文档_<b class='flag-5'>RT-Thread</b> 简介

    RT-Thread文档_RT-Thread SMP 介绍与移植

    RT-Thread文档_RT-Thread SMP 介绍与移植
    发表于 02-22 18:31 9次下载
    <b class='flag-5'>RT-Thread</b>文档_<b class='flag-5'>RT-Thread</b> SMP 介绍与移植

    RT-Thread文档_SPI 设备

    RT-Thread文档_SPI 设备
    发表于 02-22 18:36 2次下载
    <b class='flag-5'>RT-Thread</b>文档_<b class='flag-5'>SPI</b> 设备

    S32K146 RT-Thread 使用SFUD组件驱动spi flash

    S32K146 RT-Thread 使用SFUD组件驱动spi flash
    的头像 发表于 11-21 01:05 42次阅读
    【<b class='flag-5'>S32K146</b> <b class='flag-5'>RT-Thread</b>】<b class='flag-5'>之</b> 使用SFUD组件<b class='flag-5'>驱动</b><b class='flag-5'>spi</b> flash