1 /*
2 * Copyright (c) 2006-2024 RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2024-10-08 wumingzi first implementation
9 * 2024-10-08 wumingzi add custom configuration and support muti spi obj
10 */
11
12 #include <rtthread.h>
13 #include <rtdevice.h>
14 #include <time.h>
15
16 #include "rtdef.h"
17 #include "rttypes.h"
18 #include "sdkconfig.h"
19
20 #include "hal/spi_hal.h" /*bsp/ESP32_C3/packages/ESP-IDF-latest/components/hal/include/hal/spi_types.h*/
21 #include "driver/gpio.h" /*bsp/ESP32_C3/packages/ESP-IDF-latest/components/driver/include/driver/gpio.h*/
22 #include "driver/spi_master.h"
23
24 #include "drv_spi.h"
25 #include "drivers/dev_spi.h"
26
27 #ifdef RT_USING_SPI
28 #ifdef BSP_USING_SPI2
29 #define LOG_TAG "drv.spi"
30 #include <rtdbg.h>
31
32 static struct rt_spi_bus spi_bus2;
33
34 static spi_device_handle_t spi;
35 static spi_bus_config_t buscfg;
36
37 static struct esp32_spi spi_bus_obj[] = {
38 #ifdef BSP_USING_SPI2
39 {
40 .bus_name = "spi2",
41 .spi_bus = &spi_bus2,
42 .esp32_spi_bus_cfg = &buscfg,
43 },
44 #endif /* BSP_USING_SPI2 */
45 };
46
47 /* private rt-thread spi ops function */
48 static rt_err_t spi_configure(struct rt_spi_device* device, struct rt_spi_configuration* configuration);
49 static rt_ssize_t spixfer(struct rt_spi_device* device, struct rt_spi_message* message);
50
51 static struct rt_spi_ops esp32_spi_ops =
52 {
53 .configure = spi_configure,
54 .xfer = spixfer,
55 };
56
57 /**
58 * @brief SPI Initialization
59 * @param esp32_spi: SPI BUS
60 * @retval None
61 */
esp32_spi_init(struct esp32_spi * esp32_spi)62 static void esp32_spi_init(struct esp32_spi *esp32_spi)
63 {
64 spi_configure(NULL,NULL);
65 }
66
spi_configure(struct rt_spi_device * device,struct rt_spi_configuration * configuration)67 static rt_err_t spi_configure(struct rt_spi_device* device,
68 struct rt_spi_configuration* configuration)
69 {
70 static spi_bus_config_t buscfg =
71 {
72 .miso_io_num=SPI2_IOMUX_PIN_NUM_MISO, /*MISO*/
73 .mosi_io_num=SPI2_IOMUX_PIN_NUM_MOSI, /*MOSI*/
74 .sclk_io_num=SPI2_IOMUX_PIN_NUM_CLK, /*CLK*/
75 .quadwp_io_num=-1, /*不使用*/
76 .quadhd_io_num=-1, /*不使用*/
77 .max_transfer_sz=4092 /*最大传送数据长度*/
78 };
79
80 esp_err_t err = spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO);
81 ESP_ERROR_CHECK(err);
82
83 static spi_device_interface_config_t devcfg;
84 if(configuration->data_width == 8)
85 {
86 size_t length; /*/< Total data length, in bits*/
87 size_t rxlength; /*/< Total data length received, should be not greater than ``length`` in full-duplex mode (0 defaults this to the value of ``length``)*/
88 }
89
90 LOG_W("configuration->max_hz = %d \n",configuration->max_hz);
91 if(configuration->max_hz >= SPI_MASTER_FREQ_80M)
92 {
93 devcfg.clock_speed_hz = SPI_MASTER_FREQ_80M; /*/< 80MHz*/
94 }
95 else if(configuration->max_hz >= SPI_MASTER_FREQ_40M)
96 {
97 devcfg.clock_speed_hz = SPI_MASTER_FREQ_40M; /*/< 40MHz*/
98 }
99 else if(configuration->max_hz >= SPI_MASTER_FREQ_26M)
100 {
101 devcfg.clock_speed_hz = SPI_MASTER_FREQ_26M; /*/< 26.67MHz*/
102 }
103 else if(configuration->max_hz >= SPI_MASTER_FREQ_20M)
104 {
105 devcfg.clock_speed_hz = SPI_MASTER_FREQ_20M; /*/< 20MHz*/
106 }
107 else if(configuration->max_hz >= SPI_MASTER_FREQ_16M)
108 {
109 devcfg.clock_speed_hz = SPI_MASTER_FREQ_16M; /*/< 16MHz*/
110 }
111 else if(configuration->max_hz >= SPI_MASTER_FREQ_13M)
112 {
113 devcfg.clock_speed_hz = SPI_MASTER_FREQ_13M; /*/< 13.33MHz*/
114 }
115 else if(configuration->max_hz >= SPI_MASTER_FREQ_11M)
116 {
117 devcfg.clock_speed_hz = SPI_MASTER_FREQ_11M; /*/< 11.43MHz*/
118 }
119 else if(configuration->max_hz >= SPI_MASTER_FREQ_10M)
120 {
121 devcfg.clock_speed_hz = SPI_MASTER_FREQ_10M; /*/< 10MHz*/
122 }
123 else if(configuration->max_hz >= SPI_MASTER_FREQ_9M)
124 {
125 devcfg.clock_speed_hz = SPI_MASTER_FREQ_9M ; /*/< 8.89MHz*/
126 }
127 else
128 {
129 devcfg.clock_speed_hz = SPI_MASTER_FREQ_8M ;
130 }
131
132 switch (configuration->mode)
133 {
134 case RT_SPI_MODE_0: /*!< CPOL = 0, CPHA = 0 */
135 devcfg.mode = 0;
136 case RT_SPI_MODE_1: /*!< CPOL = 0, CPHA = 1 */
137 devcfg.mode = 1;
138 case RT_SPI_MODE_2: /*!< CPOL = 1, CPHA = 0 */
139 devcfg.mode = 2;
140 case RT_SPI_MODE_3: /*!< CPOL = 1, CPHA = 1 */
141 devcfg.mode = 3;
142 default:
143 devcfg.mode = 0;
144 }
145
146 /* todo: support changing cs_pin,queue_size or specifing spi_device_interface_config_t and
147 * spi_transaction_t by resever data.Meanwhile finish the initialization of interrupt
148 * callback function and dma.
149 */
150
151 devcfg.spics_io_num = RT_BSP_SPI_CS_PIN;
152 devcfg.queue_size = 7;
153
154 err = spi_bus_add_device(SPI2_HOST, &devcfg, &spi);
155 ESP_ERROR_CHECK(err);
156
157 /* Although there is only one spi bus object, it will be a template for other bsps of ESP32 series */
158 for(int i = 0; i < sizeof(spi_bus_obj)/sizeof(spi_bus_obj[0]); i++)
159 {
160 spi_bus_obj[i].bus_name = "spi2";
161 spi_bus_obj[i].spi_bus = &spi_bus2;
162 spi_bus_obj[i].esp32_spi_bus_cfg = &buscfg;
163 }
164
165 return RT_EOK;
166 };
167
spixfer(struct rt_spi_device * device,struct rt_spi_message * message)168 static rt_ssize_t spixfer(struct rt_spi_device* device, struct rt_spi_message* message)
169 {
170
171 RT_ASSERT(device != NULL);
172 RT_ASSERT(message != NULL);
173
174 static spi_transaction_t trans;
175
176 trans.tx_buffer = message->send_buf;
177 trans.rx_buffer = message->recv_buf;
178 trans.length = (message->length)*8;
179 trans.rxlength = (message->length)*8;
180
181 spi_device_acquire_bus(spi, portMAX_DELAY);
182 esp_err_t err = spi_device_polling_transmit(spi, &trans);
183
184 spi_device_release_bus(spi);
185
186 ESP_ERROR_CHECK(err);
187 return RT_EOK;
188 };
189
190 /**
191 * Attach the spi device to SPI bus, this function must be used after initialization.
192 */
rt_hw_spi_device_attach(const char * bus_name,const char * device_name,rt_base_t cs_pin)193 rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_base_t cs_pin)
194 {
195 RT_ASSERT(bus_name != RT_NULL);
196 RT_ASSERT(device_name != RT_NULL);
197
198 rt_err_t result;rt_device_t busp = RT_NULL;
199 struct rt_spi_device *spi_device;
200
201 /* attach the device to spi bus*/
202 spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
203 RT_ASSERT(spi_device != RT_NULL);
204
205 result = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin);
206
207 if (result != RT_EOK)
208 {
209 LOG_E("%s attach to %s faild, %d\n", device_name, bus_name, result);
210 }
211
212 RT_ASSERT(result == RT_EOK);
213
214 LOG_D("%s attach to %s done", device_name, bus_name);
215
216 return result;
217 }
218
rt_hw_spi_init(void)219 int rt_hw_spi_init(void)
220 {
221 int result = 0;
222
223 for(int i = 0; i < sizeof(spi_bus_obj)/sizeof(spi_bus_obj[0]); i++)
224 {
225 spi_bus_obj[i].spi_bus->parent.user_data = (void *)&spi_bus_obj[i];
226 result = rt_spi_bus_register(spi_bus_obj[i].spi_bus, spi_bus_obj[i].bus_name, &esp32_spi_ops);
227
228 RT_ASSERT(result == RT_EOK);
229
230 LOG_D("%s bus init done", spi_bus_obj[i].bus_name);
231 }
232
233 return result;
234 }
235
236 INIT_BOARD_EXPORT(rt_hw_spi_init);
237
238 #endif /* BSP_USING_SPI0 || BSP_USING_SPI1 || BSP_USING_SPI2 || BSP_USING_SPI3 || BSP_USING_SPI4*/
239 #endif /* RT_USING_SPI */