SPI_Master驱动程序框架

文章详细介绍了SPI传输的基本原理,包括数据组织方式,如spi_transfer和spi_message的使用,以及SPI控制器的数据结构。同时,讨论了SPI传输的两种方法,老方法和新方法,提供了一种理解Linux内核SPI驱动执行流程的视角。

SPI_Master驱动程序框架



  • 参考内核源码: drivers\spi\spi.c

一、SPI传输概述

1.1 数据组织方式

使用SPI传输时,最小的传输单位是"spi_transfer",

对于一个设备,可以发起多个spi_transfer,

这些spi_transfer,会放入一个spi_message里。

  • spi_transfer:指定tx_buf、rx_buf、len
    在这里插入图片描述
  • 同一个SPI设备的spi_transfer,使用spi_message来管理:
    在这里插入图片描述
  • 同一个SPI Master下的spi_message,放在一个队列里:
    在这里插入图片描述

所以,反过来,SPI传输的流程是这样的:

  • 从spi_master的队列里取出每一个spi_message
    • 从spi_message的队列里取出一个spi_transfer
      • 处理spi_transfer

1.2 SPI控制器数据结构

参考内核文件:

#include <stdio.h> #include <stdint.h> #include <string.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/spi_master.h" #include "esp_log.h" #include "driver/gpio.h" void spi_test_task(void *arg) { spi_device_handle_t spi; spi_bus_config_t buscfg = { .miso_io_num = 11, .mosi_io_num = 14, .sclk_io_num = 13, .quadwp_io_num = -1, .quadhd_io_num = -1, }; spi_device_interface_config_t devcfg = { .mode = 3, .clock_speed_hz = 100 * 1000, .spics_io_num = -1, // 手动 CS .queue_size = 1, }; spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_DISABLED); spi_bus_add_device(SPI2_HOST, &devcfg, &spi); uint8_t tx_data = 0xAA; uint8_t rx_data = 0; spi_transaction_t t = { .length = 8, .tx_buffer = &tx_data, .rx_buffer = &rx_data, }; while (1) { gpio_set_level(12, 0); // 拉低 CS spi_device_polling_transmit(spi, &t); gpio_set_level(12, 1); // 拉高 CS ESP_LOGI("SPI_TEST", "Sent 0xAA"); vTaskDelay(1000 / portTICK_PERIOD_MS); } } void app_main() { gpio_set_direction(12, GPIO_MODE_OUTPUT); gpio_set_level(12, 1); xTaskCreate(spi_test_task, "spi_test", 2048, NULL, 10, NULL); } 在运行这个代码时不断崩溃 #include <stdio.h> #include <stdint.h> #include <string.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/spi_master.h" #include "esp_log.h" #include "driver/gpio.h" void spi_test_task(void *arg) { spi_device_handle_t spi; spi_bus_config_t buscfg = { .miso_io_num = 11, .mosi_io_num = 14, .sclk_io_num = 13, .quadwp_io_num = -1, .quadhd_io_num = -1, }; spi_device_interface_config_t devcfg = { .mode = 3, .clock_speed_hz = 100 * 1000, .spics_io_num = -1, // 手动 CS .queue_size = 1, }; spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_DISABLED); spi_bus_add_device(SPI2_HOST, &devcfg, &spi); uint8_t tx_data = 0xAA; uint8_t rx_data = 0; spi_transaction_t t = { .length = 8, .tx_buffer = &tx_data, .rx_buffer = &rx_data, }; while (1) { gpio_set_level(12, 0); // 拉低 CS spi_device_polling_transmit(spi, &t); gpio_set_level(12, 1); // 拉高 CS ESP_LOGI("SPI_TEST", "Sent 0xAA"); vTaskDelay(1000 / portTICK_PERIOD_MS); } } void app_main() { gpio_set_direction(12, GPIO_MODE_OUTPUT); gpio_set_level(12, 1); xTaskCreate(spi_test_task, "spi_test", 4096, NULL, 10, NULL); } 在运行这个代码时不再崩溃,原因是什么
最新发布
09-24
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值