SPI的一些基础服务函数定义。

SPI有不同位宽模式,该参数由上层平台级参数进行配置。
指定SPI设备号,获取上层指定配置的位宽。
static u8 spi_get_info_mode(spi_dev spi)//获取模式
{
u8 mode = (u8) - 1;
u8 id = spi_get_info_id(spi);
switch (id) {
#if SPI0_ENABLE
case SPI0:
mode = spi0_p_data.mode;
break;
#endif
#if SPI1_ENABLE
case SPI1:
mode = spi1_p_data.mode;
break;
#endif
#if SPI2_ENABLE
case SPI2:
mode = spi2_p_data.mode;
break;
#endif
default:
break;
}
return mode;
}
根据位宽进行SPI寄存器配置、GPIO配置。

获取上层配置的主从机选择。
static u8 spi_get_info_role(spi_dev spi)//获取主从
{
u8 role = (u8) - 1;
u8 id = spi_get_info_id(spi);
switch (id) {
#if SPI0_ENABLE
case SPI0:
role = spi0_p_data.role;
break;
#endif
#if SPI1_ENABLE
case SPI1:
role = spi1_p_data.role;
break;
#endif
#if SPI2_ENABLE
case SPI2:
role = spi2_p_data.role;
break;
#endif
default:
break;
}
return role;
}

获取上层配置的时钟:
static u32 spi_get_info_clock(spi_dev spi)//获取时钟
{
u32 clock = (u8) - 1;
u8 id = spi_get_info_id(spi);
switch (id) {
#if SPI0_ENABLE
case SPI0:
clock = spi0_p_data.clk;
break;
#endif
#if SPI1_ENABLE
case SPI1:
clock = spi1_p_data.clk;
break;
#endif
#if SPI2_ENABLE
case SPI2:
clock = spi2_p_data.clk;
break;
#endif
default:
break;
}
return clock;
}

时钟为SPI的时钟信号,用于计算波特率。
/*

  • @brief 获取波特率

  • @parm spi spi句柄

  • @return 波特率
    /
    u32 spi_get_baud(spi_dev spi)//获取波特率
    {
    u8 id = spi_get_info_id(spi);
    return spi_get_info_clock(spi);
    }
    /

  • @brief 设置波特率

  • @parm spi spi句柄

  • @parm baud 波特率

  • @return 0 成功,< 0 失败
    */
    int spi_set_baud(spi_dev spi, u32 baud)//设置波特率
    {
    //SPICK = sysclk / (SPIx_BAUD + 1)
    //=> SPIx_BAUD = sysclk / SPICK - 1
    u8 id = spi_get_info_id(spi);
    u32 sysclk;

    sysclk = clk_get(“spi”);//获取时钟源
    log_debug(“spi clock source freq %lu”, sysclk);
    if (sysclk < baud) {//时钟小于baud,则返回错误
    spi_w_reg_baud(spi_regs[id], 0);
    return -EINVAL;
    }
    spi_w_reg_baud(spi_regs[id], sysclk / baud - 1);//SPICK = system clock / (SPIBAUD + 1)
    return 0;
    }

sysclk / baud - 1:分频系数。

其他SPI收发、中断相关的基础函数:
/*

  • @brief 发送1个字节

  • @parm spi spi句柄

  • @parm byte 发送的字节

  • @return 0 成功,< 0 失败
    */
    int spi_send_byte(spi_dev spi, u8 byte)//发送1个字节
    {
    u8 id = spi_get_info_id(spi);//获取ID

    spi_dir_out(spi_regs[id]);//配置为输出
    spi_w_reg_buf(spi_regs[id], byte);//写数据
    return __spi_wait_ok(spi, 1);//等待完成
    }

/*

  • @brief 发送1个字节,不等待pnd,用于中断

  • @parm spi spi句柄

  • @parm byte 发送的字节

  • @return null
    */
    void spi_send_byte_for_isr(spi_dev spi, u8 byte)//发送1个字节,不等待pnd,用于中断
    {
    u8 id = spi_get_info_id(spi);//获取ID

    spi_dir_out(spi_regs[id]);//配置为输出
    spi_w_reg_buf(spi_regs[id], byte);//写数据
    }

/*

  • @brief 接收1个字节

  • @parm spi spi句柄

  • @parm err 返回错误信息,若err为非空指针,0 成功,< 0 失败,若为空指针,忽略

  • @return 接收的字节
    */
    u8 spi_recv_byte(spi_dev spi, int *err)//接收1字节数据
    {
    u8 id = spi_get_info_id(spi);
    int ret;

    spi_dir_in(spi_regs[id]);//配置为输入
    spi_w_reg_buf(spi_regs[id], 0xff);//buf中写入ff
    ret = __spi_wait_ok(spi, 1);//等待接收完成,返回0表示成功
    if (ret) {//接收失败
    err != NULL ? *err = ret : 0;//如果err不为NULL,*err赋值错误码
    return 0;
    }
    err != NULL ? err = 0 : 0;//接收成功,则err赋值0
    return spi_r_reg_buf(spi_regs[id]);//返回读的数值
    }

/*

  • @brief 接收1个字节,不等待pnd,用于中断

  • @parm spi spi句柄

  • @return 接收的字节
    */
    u8 spi_recv_byte_for_isr(spi_dev spi)//接收1个字节,不等待pnd,用于中断
    {
    u8 id = spi_get_info_id(spi);//获取ID

    spi_dir_in(spi_regs[id]);//配置为输入
    return spi_r_reg_buf(spi_regs[id]);//返回读到的数值
    }

/*

  • @brief 发送并接收1个字节,在8个时钟内完成,仅使用于SPI_MODE_BIDIR_1BIT

  • @parm spi spi句柄

  • @parm byte 发送的字节

  • @parm err 返回错误信息,若err为非空指针,0 成功,< 0 失败,若为空指针,忽略

  • @return 接收的字节
    */
    u8 spi_send_recv_byte(spi_dev spi, u8 byte, int *err)//发送并接收1个字节
    {
    u8 id = spi_get_info_id(spi);//获取ID
    int ret;

    spi_w_reg_buf(spi_regs[id], byte);//发送一个字节
    ret = __spi_wait_ok(spi, 1);//等待发送完成
    if (ret) {
    err != NULL ? *err = ret : 0;//错误则返回错误码
    return 0;
    }
    err != NULL ? *err = 0 : 0;//没错误则错误码为0
    return spi_r_reg_buf(spi_regs[id]);//接收一个字节
    }

SPI的等待函数:
static int __spi_wait_ok(spi_dev spi, u32 n)//等待完成
{
u8 id = spi_get_info_id(spi);
u32 baud = spi_get_info_clock(spi);
baud = clk_get(“spi”) / baud - 1;
u32 retry = baud * (clk_get(“sys”) / clk_get(“spi”)) * 8 * n * 5; //500% spi baudate

while (!spi_pnd(spi_regs[id])) {//等待标志置位__asm__ volatile("nop");//空操作if (--retry == 0) {//计数器递减,递减为0表示超时log_error("spi wait pnd timeout");return -EFAULT;//超时返回错误码}
}
spi_clr_pnd(spi_regs[id]);//清标志
return 0;

}

中断配置函数:
/*

  • @brief 中断使能
  • @parm spi spi句柄
  • @parm en 1 使能,0 失能
  • @return null
    */
    void spi_set_ie(spi_dev spi, u8 en)//配置中断使能或禁能
    {
    u8 id = spi_get_info_id(spi);
    en ? spi_ie_en(spi_regs[id]) : spi_ie_dis(spi_regs[id]);
    }

/*

  • @brief 判断中断标志
  • @parm spi spi句柄
  • @return 0 / 1
    */
    u8 spi_get_pending(spi_dev spi)//获取挂起标志
    {
    u8 id = spi_get_info_id(spi);
    return spi_pnd(spi_regs[id]) ? 1 : 0;
    }

/*

  • @brief 清除中断标志
  • @parm spi spi句柄
  • @return null
    */
    void spi_clear_pending(spi_dev spi)//清除中断标志
    {
    u8 id = spi_get_info_id(spi);
    spi_clr_pnd(spi_regs[id]);
    }

SPI接口协议的学习4相关推荐

  1. 【常见总线接口协议】学习笔记2

    https://www.cnblogs.com/zhjblogs/p/12422331.html https://www.cnblogs.com/zhjblogs/p/12464843.html ht ...

  2. 基于Verilog的SPI接口设计

    SPI接口电路的学习 1.SPI接口电路原理 SPI, Serial Perripheral Interface, 串行外围设备接口, 是Motorola 公司推出的一种同步串行接口技术. SPI 总 ...

  3. SPI接口扫盲 SPI定义/SPI时序(CPHA CPOL)

    SPI接口扫盲 douqingl@gmail.com 为何要写这篇文档? 百度上找出来的SPI接口中文描述都说的太过简略,没有一篇文档能够详尽的将SPI介绍清楚的.wikipedia英文版[注释1]中 ...

  4. nRF52832学习记录(十二、SPI接口的应用 Micro SD卡读写测试)

    目录 1.nRF52xx SPI介绍 SPI接口基础介绍 SPI 寄存器 SPI 库函数介绍 SPI初始化函数 SPI数据传输函数 2.nRF52xx SPI 使用示例 w25qxx SPI Flas ...

  5. SPI、I2C、UART三种串行总线协议的区别和SPI接口介绍(转)

    SPI.I2C.UART三种串行总线协议的区别 第一个区别当然是名字: SPI(Serial Peripheral Interface:串行外设接口); I2C(INTER IC BUS) UART( ...

  6. 单片机软件模拟SPI接口—加深理解SPI总线协议

    单片机软件模拟SPI接口-加深理解SPI总线协议   SPI(Serial Peripheral Interfacer 串行外设接口)是摩托罗拉公司推出的一种同步串行通讯接口,用于微处理器臌控制器和外 ...

  7. FPGA实现的SPI协议(二)----基于SPI接口的FLASH芯片M25P16的使用

    写在前面 SPI协议系列文章: FPGA实现的SPI协议(一)----SPI驱动 FPGA实现的SPI协议(二)----基于SPI接口的FLASH芯片M25P16的使用 在上篇文章,简要介绍了SPI协 ...

  8. LTE学习笔记三:接口协议

    上一笔记说明了LTE网络的网元组成,网元之间的联系是通过标准化的接口.接下来学习LTE终端和网络的空中接口Uu.基站之间的X2接口.基站与核心网之间的S1接口,以及LTE接口协议栈和以往无线制式相比的 ...

  9. AXI接口协议学习总结

    AXI接口协议学习总结 下面将AXI接口协议学到的相关内容整理如下 一.AXI接口协议定义 AXI是Advanced eXtensible Interface的缩写,译为高级可扩展接口协议,是ARM公 ...

最新文章

  1. 【C#实践】详解三层转七层:登录
  2. 神经网络与机器学习 笔记—复制器(恒等)映射
  3. SQL基础【十三、通配符】
  4. JavaScript对数组的处理(一)
  5. 英特尔、联发科、展讯等开始支持开源的物联网轻量化操作系统AliOS Lite
  6. libsvm数据缩放方法
  7. lm723大电流可调电源电路图_高稳定大电流直流可调稳压电路
  8. 计算机图形学E10——Bezier曲线
  9. 为什么你总感觉情绪低落心情颓废?
  10. ajax post请求发送数组后台接收
  11. librdkafka自动源码编译
  12. java gif图片分割合成,js实现GIF图片的分解和合成
  13. numpy.median
  14. 《霍乱时期的爱情》书评
  15. qt:qt5.12警告消除大法之 warning: zero as null pointer constant
  16. 冰尘社补丁php,300英雄冰尘社盒子ios
  17. python的re模块替换文件字符串_Python 正则处理_re模块
  18. 这是什么在线客服系统?
  19. 首批预计才60万套。 四轮猴
  20. mysql 介绍 怎么下载 驱动jar包 各种细节问题大详解

热门文章

  1. 小辣鸡的Android开发之路-应用冻结器-4-实现应用的禁止和解禁
  2. 在cad中出现“代理对象不允许复制 因此写块操作被拒绝”的解决办法
  3. 【blender动作练习生】从零开始的骨骼绑定学习vol.2
  4. onethink复制、移动按钮IE8不兼容
  5. 如何用一台cisco1921-K9解决目前国内常见访问全网需求和流量区分策略?
  6. 动手学数据分析Task2第一节数据清洗及特征处理
  7. pythom入门_3(学习笔记)
  8. 等保小能手_等保测评怎么做
  9. 酒精加速衰老的幕后推手——DNA甲基化
  10. chatgpt收费吗