为RTEMS Raspberrypi4 BSP添加SPI支持

为RTEMS Raspberrypi4 BSP添加SPI支持

主要参考了dev/bsps/shared/dev/spi/cadence-spi.c

RTEMS 使用了基于linux的SPI框架,SPI总线驱动已经在内核中实现。在这个项目中我需要实习的是 RPI4的SPI主机控制器驱动

SPI在RTEMS中的实现如图:
在这里插入图片描述
首先需要将SPI主机控制器设备在总线上注册,注册函数如下:

rtems_status_code raspberrypi_spi_init(raspberrypi_spi_device device)
{raspberrypi_spi_bus *bus;int eno;volatile raspberrypi_spi *regs;const char *bus_path;bus = (raspberrypi_spi_bus *) spi_bus_alloc_and_init(sizeof(*bus));if (bus == NULL) {return RTEMS_UNSATISFIED;}switch (device) {case raspberrypi_SPI0:regs = (volatile raspberrypi_spi *) BCM2711_SPI0_BASE;bus_path = "/dev/spidev0";break;case raspberrypi_SPI3:regs = (volatile raspberrypi_spi *) BCM2711_SPI3_BASE;bus_path = "/dev/spidev3";break;case raspberrypi_SPI4:regs = (volatile raspberrypi_spi *) BCM2711_SPI4_BASE;bus_path = "/dev/spidev4";break;case raspberrypi_SPI5:regs = (volatile raspberrypi_spi *) BCM2711_SPI5_BASE;bus_path = "/dev/spidev5";break;case raspberrypi_SPI6:regs = (volatile raspberrypi_spi *) BCM2711_SPI6_BASE;bus_path = "/dev/spidev6";break;default:spi_bus_destroy_and_free(&bus->base);return RTEMS_INVALID_NUMBER;break;}eno = spi_bus_register(&bus->base, bus_path);if (eno != 0) {spi_bus_destroy_and_free(&bus->base);return RTEMS_UNSATISFIED;}eno = raspberrypi_spi_init_gpio(device);if (eno != 0) {spi_bus_destroy_and_free(&bus->base);return RTEMS_INVALID_NUMBER;}bus->regs = regs;bus->num_cs = 2;bus->base.transfer = raspberrypi_spi_transfer;bus->base.destroy = raspberrypi_spi_destroy;bus->base.setup = raspberrypi_spi_setup;bus->base.bits_per_word = 8;bus->base.max_speed_hz = 250000000;bus->base.cs = 0;
#ifdef BSP_SPI_USE_INTERRUPTSbus->irq = BCM2711_IRQ_SPI;eno = rtems_interrupt_handler_install(bus->irq,"SPI",RTEMS_INTERRUPT_SHARED,raspberrypi_spi_interrupt,bus);if (eno != RTEMS_SUCCESSFUL) {return EAGAIN;}
#endifreturn RTEMS_SUCCESSFUL;
}

调用 spi_bus_alloc_and_init ,此为SPI总线驱动实现的函数,位于RTEMS内核 dev/cpukit/dev/spi/spi-bus.c

Allocates a bus control from the heap and initializes it. After a sucessful allocation and initialization the bus control must be destroyed via spi_bus_destroy_and_free(). A registered bus control will be automatically destroyed in case the device file is unlinked. Make sure to call spi_bus_destroy_and_free() in a custom destruction handler.参数:
size – The size of the bus control. This enables the addition of bus controller specific data to the base bus control. The bus control is zero initialized.返回值:
non-NULL The new bus control.
NULL An error occurred. The errno is set to indicate the error.

switch结构中根据枚举变量raspberrypi_spi_device 的值分别选择 SPI寄存器地址dev目录下的路径名称。寄存器地址定义在 raspberrypi.h 文件中。

设置bus的各种参数和接口函数。
使用宏定义BSP_SPI_USE_INTERRUPTS选择驱动使用中断模式或轮询模式。

中端句柄的安装,考虑到同时启用多个SPI的情况,使用RTEMS_INTERRUPT_SHARED

  eno = rtems_interrupt_handler_install(bus->irq,"SPI",RTEMS_INTERRUPT_SHARED,raspberrypi_spi_interrupt,bus);

调用spi_bus_register,将设备注册进总线。此函数为SPI总线驱动中实现的函数。

调用raspberrypi_spi_init_gpio,初始化gpio,将gpio设置为正确的功能。将此函数后置的原因:总线注册失败时,避免对gpio进行复原。

接下来介绍transfer函数,用于处理SPI读写。

static int raspberrypi_spi_transfer(spi_bus *base,const spi_ioc_transfer *msgs,uint32_t msg_count
)
{int rv = 0;raspberrypi_spi_bus *bus;bus = (raspberrypi_spi_bus *) base;rv = raspberrypi_spi_check_msg(bus, msgs, msg_count);if (rv == 0) {bus->msg_todo = msg_count;bus->msg = msgs;
#ifdef BSP_SPI_USE_INTERRUPTSbus->task_id = rtems_task_self();raspberrypi_spi_start(bus);rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
#elseraspberrypi_spi_transfer_msg(bus);
#endif}return rv;
}

调用raspberrypi_spi_check_msg函数,对msg进行检查,主要检查是否使用了驱动不支持的模式,cs是否超过cs的总数。
这里需要传入msg_count,因为msgs是地址连续的一个队列,可能包含多个msg。

检查通过则将数据的信息结构体的部分变量赋值给bus结构体中的相应变量。

如果使用中断模式则进入raspberrypi_spi_start,轮询模式则进入raspberrypi_spi_transfer_msg

本文主要介绍中断模式。

raspberrypi_spi_start只需要将传输启动,对于RPI4的SPI控制器,将TA=1,就会立即触发第一个中断,我认为这是与其他BSP不同的点。

static void raspberrypi_spi_start(raspberrypi_spi_bus *bus)
{volatile raspberrypi_spi *regs;regs = bus->regs;regs->spics = regs->spics | RPI_SPICS_INTR | RPI_SPICS_INTD;/* * Set TA = 1. This will immediately trigger a first interrupt with * DONE = 1. */regs->spics = regs->spics | RPI_SPICS_TA;
}

中断处理函数如下:

static void raspberrypi_spi_interrupt(void *arg)
{raspberrypi_spi_bus *bus;volatile raspberrypi_spi *regs;uint32_t val;bus = arg;regs = bus->regs;if (raspberrypi_spi_irq(regs)) {if (bus->todo > 0) {raspberrypi_spi_push(bus, regs);} else {--bus->msg_todo;++bus->msg;raspberrypi_spi_next_msg(bus);}while (regs->spics & RPI_SPICS_RXD && bus->in_transfer > 0) {/*  RX FIFO contains at least 1 byte. */val = regs->spififo;if (bus->rx_buf != NULL) {*bus->rx_buf = (uint8_t)val;++bus->rx_buf;}--bus->in_transfer;}}
}

函数 raspberrypi_spi_irq 用于判断中断是否是由当前SPI设备产生。这使得多个SPI设备可以同时使用。

函数raspberrypi_spi_next_msg用于切换到下一个msg,并将msg结构体中的剩余变量赋值给bus结构体。

rtems_event_transient_receive 和 rtems_event_transient_send 至关重要
传输开始时调用rtems_event_transient_receive

	bus->task_id = rtems_task_self();rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);

传输结束时调用rtems_event_transient_send

	rtems_event_transient_send(bus->task_id);

保证一条传输命令在传输结束前阻塞。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/51137.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

day06 项目实践:router,axios

vue组件的生命周期钩子 今天几乎没有讲什么新内容,就是一起做项目,只有一个小小的知识点,就是关于vue组件的生命周期钩子,其中最重要的四个函数—— beforeCreate():组件创建之间执行 created():组件创建…

[Meachines] [Easy] Admirer Adminer远程Mysql反向+Python三方库函数劫持权限提升

信息收集 IP AddressOpening Ports10.10.10.187TCP:21,22,80 $ nmap -p- 10.10.10.187 --min-rate 1000 -sC -sV PORT STATE SERVICE VERSION 21/tcp open ftp vsftpd 3.0.3 22/tcp open ssh OpenSSH 7.4p1 Debian 10deb9u7 (protocol 2.0) | ssh-hostkey: | …

前端三大主流框架对比

在现代前端开发中,React、Vue和Angular是三大流行的框架/库。它们各自有独特的优缺点,适用于不同的开发需求和项目规模。下面是对这三者的详细比较: 一、 React 简介: 由Facebook开发和维护,是一个用于构建用户界面…

yolov8标注细胞、识别边缘、计算面积、灰度值计算

一、数据标注 1. 使用labelme软件标注每个细胞的边界信息,标注结果为JSON格式 2. JSON格式转yolo支持的txt格式 import json import os import glob import os.path as osp此函数用来将labelme软件标注好的数据集转换为yolov5_7.0sege中使用的数据集:param jsonfi…

【vue前端项目实战案例】之Vue仿饿了么App

本文将介绍一款仿“饿了么”商家页面的App。该案例是基于 Vue2.0 Vue Router webpack ES6 等技术栈实现的一款外卖类App,适合初学者进行学习。 项目源码下载链接在文章末尾 1 项目概述 该项目是一款仿“饿了么”商家页面的外卖类App,主要有以下功能…

【深度学习】“复杂场景下基于深度学习的卷积神经网络在鸟类多类别识别中的模型设计与性能优化研究“(上)

【深度学习】“复杂场景下基于深度学习的卷积神经网络在鸟类多类别识别中的模型设计与性能优化研究”(上) 大家好 我是寸铁👊 【深度学习】“复杂场景下基于深度学习的卷积神经网络在鸟类多类别识别中的模型设计与性能优化研究”(上)✨ 喜欢的小伙伴可以点点关注 &a…

LangChain-v0.2 构建 PDF 采集和问答系统

PDF 文件通常包含其他来源无法获取的重要非结构化数据。它们可能非常长,而且与纯文本文件不同,通常无法直接输入到语言模型的提示中。 在本中,我们将创建一个可以回答有关 PDF 文件的问题的系统。更具体地说,就是使用文档加载器加…

【前端 14】Vue常见指令

Vue常见指令 Vue.js 是一个构建用户界面的渐进式框架,它通过一系列简洁的指令(Directives)来增强HTML的功能,使得开发者能够更加方便地构建出响应式的Web应用。本文将详细讲解Vue中的几个核心指令:v-bind、v-model、v…

AndroidAOSP定制之关闭某些app的通知

AndroidAOSP定制之关闭某些app的通知 前言: ​ 最近在做AOSP系统定制时发现gms定制好了后,Google应用商店用不了,提示此设备未获得Play保护机制认证,Google应用和服务无法在此设备上运行,查看官方文档和资料,说是由于…

【学习笔记】| 03 - 使用STM32CubeMX新建工程

使用STM32CubeMX新建工程是一个相对直观的过程,主要涉及到选择芯片型号、配置外设、时钟系统、GPIO引脚等,并最终生成工程代码。以下是一个详细的步骤指南: 一、打开STM32CubeMX并新建工程 启动STM32CubeMX: 打开STM32CubeMX软件…

FPGA实验6: 有时钟使能两位十进制计数器的设计

一、实验目的与要求 1.. 熟练掌握使用原理图设计较复杂电路; 2. 学习原理图设计中总线的表示以及使用方法。 二、实验原理 运用Quartus II 集成环境下的图形设计方法设计有时钟使能的两位十进制计数器。进行波形仿真和分析、引脚分配并下载到实验设备上进行功能…

[ECharts] There is a chart instance already initialized on the dom. 已存在图表,渲染重复

报错:已存在图表,渲染重复 解决: 在合适的时机执行 dispose 方法即可 // echarts 全局存入 实例 let myChart: any;// 在你的 initChart 初始化 Echarts 方法中 先执行清理方法 const initChart () > {// 执行清理方法然后初始化if(myChart){cons…

AndroidStudio 开发环境搭建

文章目录 AndroidStudio 开发环境搭建JDK 下载与安装,配置环境变量JDK1.8 下载安装配置环境变量新建JAVA_HOME编辑Path 下载AndroidStudio最新版本历史版本先安装JDK,后启动AS以管理员身份运行打开解决双击打不开的问题Error:你的主机中的软件中止了一个…

Coggle数据科学 | 大模型技术内参:39 种提示工程 在 29 种 NLP 任务精度对比

本文来源公众号“Coggle数据科学”,仅用于学术分享,侵权删,干货满满。 原文链接:大模型技术内参:39 种提示工程 在 29 种 NLP 任务精度对比 大语言模型(LLMs)在许多不同的自然语言处理&#x…

Linux网络-netstat命令

作者介绍:简历上没有一个精通的运维工程师。希望大家多多关注我,我尽量把自己会的都分享给大家,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 Linux服务器作为一个常用的网络服务器,主要的作用就是向客户端提供网络…

1143. 最长公共子序列(详细版)

目录 dp解法: 1.状态代表什么: 2. 状态转移方程 3.初始化 3. so为什么要这样? 代码实现: 给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0…

从小白到架构师:万字长文 | 社交媒体应用系统设计

移动互联网时代,社交媒体应用彻底改变了我们联系和共享信息的方式。这些平台在幕后处理庞大的用户群、数据存储和实时交互。 在本文中,我们将深入探讨如何设计一个可扩展且高性能的社交媒体应用系统。我们将探讨关键组件、流程图、功能需求以及容量规划…

科普文:分布式数据一致性协议Paxos

1 什么是Paxos Paxos协议其实说的就是Paxos算法, Paxos算法是基于消息传递且具有高度容错特性的一致性算 法,是目前公认的解决分布式一致性问题最有效的算法之一。 Paxos由 莱斯利兰伯特(Leslie Lamport)于1998年在《The Part-Time Parliament》论文中首次公 开&…

Gitops-Argo-Cli安装与使用

一、安装Argo-Cli工具 Release v2.9.21 argoproj/argo-cd GitHub **选择合适的符合你操作系统以及CPU架构的二进制文件 #依v2.9.21-X86-64-Linux操作系统为例 wget https://github.com/argoproj/argo-cd/releases/download/v2.9.21/argocd-linux-amd64 #添加执行权限并且移…

论文中的流程图参考图片

写论文的时候,在绘制流程图时,一直纠结n是大写还是小写,用不用斜体,号两边要不要空格。今天找到了一张标准的流程图来参考。图片来自 Zhi-Chang Ba et al, Combination of DCE-MRI and NME-DWI via Deep Neural Network for Predi…