1 /*
2  * Copyright (c) 2006-2018, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date             Author          Notes
8  * 2021-02-14       supperthomas    first version
9  */
10 
11 #include <stdint.h>
12 #include <string.h>
13 #include "board.h"
14 #include "drv_spi.h"
15 
16 #define DBG_LEVEL   DBG_LOG
17 #include <rtdbg.h>
18 #define LOG_TAG                "drv.spi"
19 
20 #ifdef BSP_USING_SPI
21 
22 #if defined(BSP_USING_SPI0) || defined(BSP_USING_SPI1) || defined(BSP_USING_SPI2)
23 static struct mcu_drv_spi_config spi_config[] =
24 {
25 #ifdef BSP_USING_SPI0
26     MCU_SPI0_CONFIG,
27 #endif
28 #ifdef BSP_USING_SPI1
29     MCU_SPI1_CONFIG,
30 #endif
31 
32 };
33 
34 static struct mcu_drv_spi spi_bus_obj[sizeof(spi_config) / sizeof(spi_config[0])];
35 
36 
37 /**
38   * @brief  This function config spi bus
39   * @param  device
40   * @param  configuration
41   * @retval RT_EOK / -RT_ERROR
42   */
spi_configure(struct rt_spi_device * device,struct rt_spi_configuration * configuration)43 static rt_err_t spi_configure(struct rt_spi_device *device,
44                               struct rt_spi_configuration *configuration)
45 {
46     RT_ASSERT(device != RT_NULL);
47     RT_ASSERT(device->bus != RT_NULL);
48     RT_ASSERT(device->bus->parent.user_data != RT_NULL);
49     RT_ASSERT(configuration != RT_NULL);
50     struct mcu_drv_spi *tmp_spi;
51     tmp_spi = rt_container_of(device->bus, struct mcu_drv_spi, spi_bus);
52     int mode;
53 
54     ///init
55 
56     switch (configuration->mode & RT_SPI_MODE_3)
57     {
58     case RT_SPI_MODE_0/* RT_SPI_CPOL:0 , RT_SPI_CPHA:0 */:
59     case RT_SPI_MODE_1/* RT_SPI_CPOL:0 , RT_SPI_CPHA:1 */:
60     case RT_SPI_MODE_2/* RT_SPI_CPOL:1 , RT_SPI_CPHA:0 */:
61     case RT_SPI_MODE_3/* RT_SPI_CPOL:1 , RT_SPI_CPHA:1 */:
62         mode = configuration->mode & RT_SPI_MODE_3;
63         break;
64     default:
65         LOG_E("spi_configure mode error %x\n", configuration->mode);
66         return -RT_ERROR;
67     }
68 
69     tmp_spi->spixfer_req.width = SPI17Y_WIDTH_1;
70     tmp_spi->spixfer_req.bits = configuration->data_width;
71     tmp_spi->spixfer_req.ssel = 0;
72     tmp_spi->spixfer_req.deass = 1;
73     tmp_spi->spixfer_req.tx_num = 0;
74     tmp_spi->spixfer_req.rx_num = 0;
75     tmp_spi->spixfer_req.callback = NULL;
76     LOG_D("spi init mode:%d, rate:%d", mode, configuration->max_hz);
77     if (SPI_Init(tmp_spi->spi_instance, mode, configuration->max_hz) != 0)
78     {
79         LOG_E("Error configuring SPI\n");
80         while (1) {}
81     }
82     //init
83     return RT_EOK;
84 }
85 
spixfer(struct rt_spi_device * device,struct rt_spi_message * message)86 static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message)
87 {
88     RT_ASSERT(device != RT_NULL);
89     RT_ASSERT(device->bus != RT_NULL);
90     RT_ASSERT(device->bus->parent.user_data != RT_NULL);
91 
92     int ret = 0;
93     struct mcu_drv_spi *tmp_spi;
94     tmp_spi = rt_container_of(device->bus, struct mcu_drv_spi, spi_bus);
95 
96 
97     tmp_spi->spixfer_req.tx_data = message->send_buf;
98     tmp_spi->spixfer_req.rx_data = message->recv_buf;
99     tmp_spi->spixfer_req.len = message->length;
100     ret = SPI_MasterTrans(tmp_spi->spi_instance, &tmp_spi->spixfer_req);
101     if (ret == E_NO_ERROR)
102     {
103         return message->length;
104     }
105     else
106     {
107         LOG_E("spixfer faild, ret %d", ret);
108         return 0;
109     }
110 }
111 
112 /* spi bus callback function  */
113 static const struct rt_spi_ops nrfx_spi_ops =
114 {
115     .configure = spi_configure,
116     .xfer = spixfer,
117 };
118 
119 /*spi bus init*/
rt_hw_spi_bus_init(void)120 static int rt_hw_spi_bus_init(void)
121 {
122     rt_err_t result = -RT_ERROR;
123     for (int i = 0; i < sizeof(spi_config) / sizeof(spi_config[0]); i++)
124     {
125         spi_bus_obj[i].spi_instance = spi_config[i].spi_instance;
126         spi_bus_obj[i].spi_bus.parent.user_data = &spi_config[i];   //SPI INSTANCE
127         result = rt_spi_bus_register(&spi_bus_obj[i].spi_bus, spi_config[i].bus_name, &nrfx_spi_ops);
128         RT_ASSERT(result == RT_EOK);
129     }
130     return result;
131 }
132 
rt_hw_spi_init(void)133 int rt_hw_spi_init(void)
134 {
135     return rt_hw_spi_bus_init();
136 }
137 INIT_BOARD_EXPORT(rt_hw_spi_init);
138 
139 /**
140   * Attach the spi device to SPI bus, this function must be used after initialization.
141   */
rt_hw_spi_device_attach(const char * bus_name,const char * device_name,rt_uint32_t cs_pin)142 rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t cs_pin)
143 {
144     RT_ASSERT(bus_name != RT_NULL);
145     RT_ASSERT(device_name != RT_NULL);
146     RT_ASSERT(cs_pin != RT_NULL);
147 
148     rt_err_t result;
149     struct rt_spi_device *spi_device;
150     /* attach the device to spi bus*/
151     spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
152     RT_ASSERT(spi_device != RT_NULL);
153     /* initialize the cs pin */
154     result = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin);
155     if (result != RT_EOK)
156     {
157         LOG_E("%s attach to %s faild, %d", device_name, bus_name, result);
158         result = -RT_ERROR;
159     }
160     /* TODO: SET THE GPIO */
161 
162     RT_ASSERT(result == RT_EOK);
163     return result;
164 }
165 
166 #endif /* BSP_USING_SPI0 || BSP_USING_SPI1 || BSP_USING_SPI2 */
167 #endif /*BSP_USING_SPI*/
168 
169 
170