添加rtthread相关代码
This commit is contained in:
		
							
								
								
									
										525
									
								
								riscv/rtthread/components/drivers/spi/spi-bit-ops.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										525
									
								
								riscv/rtthread/components/drivers/spi/spi-bit-ops.c
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,525 @@ | ||||
| /* | ||||
|  * Copyright (c) 2006-2023, RT-Thread Development Team | ||||
|  * | ||||
|  * SPDX-License-Identifier: Apache-2.0 | ||||
|  * | ||||
|  * Change Logs: | ||||
|  * Date           Author        Notes | ||||
|  * 2021-10-11     kyle          first version | ||||
|  */ | ||||
|  | ||||
| #include <spi-bit-ops.h> | ||||
| #include <rtdevice.h> | ||||
|  | ||||
| #define DBG_TAG               "SPI" | ||||
| #ifdef RT_SPI_BITOPS_DEBUG | ||||
| #define DBG_LVL               DBG_LOG | ||||
| #else | ||||
| #define DBG_LVL               DBG_ERROR | ||||
| #endif | ||||
| #include <rtdbg.h> | ||||
|  | ||||
| #define TOG_SCLK(ops)        ops->tog_sclk(ops->data) | ||||
| #define SET_SCLK(ops, val)   ops->set_sclk(ops->data, val) | ||||
| #define SET_MOSI(ops, val)   ops->set_mosi(ops->data, val) | ||||
| #define SET_MISO(ops, val)   ops->set_miso(ops->data, val) | ||||
| #define GET_SCLK(ops)        ops->get_sclk(ops->data) | ||||
| #define GET_MOSI(ops)        ops->get_mosi(ops->data) | ||||
| #define GET_MISO(ops)        ops->get_miso(ops->data) | ||||
| #define DIR_MOSI(ops, val)   ops->dir_mosi(ops->data, val) | ||||
| #define DIR_MISO(ops, val)   ops->dir_miso(ops->data, val) | ||||
|  | ||||
| rt_inline void spi_delay(struct rt_spi_bit_ops *ops) | ||||
| { | ||||
|     ops->udelay((ops->delay_us + 1) >> 1); | ||||
| } | ||||
|  | ||||
| rt_inline void spi_delay2(struct rt_spi_bit_ops *ops) | ||||
| { | ||||
|     ops->udelay(ops->delay_us); | ||||
| } | ||||
|  | ||||
| #define SCLK_H(ops)          SET_SCLK(ops, 1) | ||||
| #define SCLK_L(ops)          SET_SCLK(ops, 0) | ||||
| #define MOSI_H(ops)          SET_MOSI(ops, 1) | ||||
| #define MOSI_L(ops)          SET_MOSI(ops, 0) | ||||
| #define MOSI_IN(ops)         DIR_MOSI(ops, 1) | ||||
| #define MOSI_OUT(ops)        DIR_MOSI(ops, 0) | ||||
| #define MISO_IN(ops)         DIR_MISO(ops, 1) | ||||
| #define MISO_OUT(ops)        DIR_MISO(ops, 0) | ||||
|  | ||||
| rt_inline rt_ssize_t spi_xfer_4line_data8(struct rt_spi_bit_ops       *ops, | ||||
|                                          struct rt_spi_configuration *config, | ||||
|                                          const void                  *send_buf, | ||||
|                                          void                        *recv_buf, | ||||
|                                          rt_size_t                    length) | ||||
| { | ||||
|     int i = 0; | ||||
|  | ||||
|     RT_ASSERT(ops != RT_NULL); | ||||
|     RT_ASSERT(length != 0); | ||||
|  | ||||
|     { | ||||
|         const rt_uint8_t *send_ptr = send_buf; | ||||
|         rt_uint8_t *recv_ptr = recv_buf; | ||||
|         rt_uint32_t size = length; | ||||
|  | ||||
|         while (size--) | ||||
|         { | ||||
|             rt_uint8_t tx_data = 0xFF; | ||||
|             rt_uint8_t rx_data = 0xFF; | ||||
|             rt_uint8_t bit  = 0; | ||||
|  | ||||
|             if (send_buf != RT_NULL) | ||||
|             { | ||||
|                 tx_data = *send_ptr++; | ||||
|             } | ||||
|  | ||||
|             for (i = 0; i < 8; i++) | ||||
|             { | ||||
|                 if (config->mode & RT_SPI_MSB) { bit = tx_data & (0x1 << (7 - i)); } | ||||
|                 else                           { bit = tx_data & (0x1 << i); } | ||||
|  | ||||
|                 if (bit) MOSI_H(ops); | ||||
|                 else     MOSI_L(ops); | ||||
|  | ||||
|                 spi_delay2(ops); | ||||
|  | ||||
|                 TOG_SCLK(ops); | ||||
|  | ||||
|                 if (config->mode & RT_SPI_MSB) { rx_data <<= 1; bit = 0x01; } | ||||
|                 else                           { rx_data >>= 1; bit = 0x80; } | ||||
|  | ||||
|                 if (GET_MISO(ops)) { rx_data |=  bit; } | ||||
|                 else               { rx_data &= ~bit; } | ||||
|  | ||||
|                 spi_delay2(ops); | ||||
|  | ||||
|                 if (!(config->mode & RT_SPI_CPHA) || (size != 0) || (i < 7)) | ||||
|                 { | ||||
|                     TOG_SCLK(ops); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (recv_buf != RT_NULL) | ||||
|             { | ||||
|                 *recv_ptr++ = rx_data; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return length; | ||||
| } | ||||
|  | ||||
| rt_inline rt_ssize_t spi_xfer_4line_data16(struct rt_spi_bit_ops       *ops, | ||||
|                                           struct rt_spi_configuration *config, | ||||
|                                           const void                  *send_buf, | ||||
|                                           void                        *recv_buf, | ||||
|                                           rt_size_t                    length) | ||||
| { | ||||
|     int i = 0; | ||||
|  | ||||
|     RT_ASSERT(ops != RT_NULL); | ||||
|     RT_ASSERT(length != 0); | ||||
|  | ||||
|     { | ||||
|         const rt_uint16_t *send_ptr = send_buf; | ||||
|         rt_uint16_t *recv_ptr = recv_buf; | ||||
|         rt_uint32_t size = length; | ||||
|  | ||||
|         while (size--) | ||||
|         { | ||||
|             rt_uint16_t tx_data = 0xFFFF; | ||||
|             rt_uint16_t rx_data = 0xFFFF; | ||||
|             rt_uint16_t bit  = 0; | ||||
|  | ||||
|             if (send_buf != RT_NULL) | ||||
|             { | ||||
|                 tx_data = *send_ptr++; | ||||
|             } | ||||
|  | ||||
|             for (i = 0; i < 16; i++) | ||||
|             { | ||||
|                 if (config->mode & RT_SPI_MSB) { bit = tx_data & (0x1 << (15 - i)); } | ||||
|                 else                           { bit = tx_data & (0x1 << i); } | ||||
|  | ||||
|                 if (bit) MOSI_H(ops); | ||||
|                 else     MOSI_L(ops); | ||||
|  | ||||
|                 spi_delay2(ops); | ||||
|  | ||||
|                 TOG_SCLK(ops); | ||||
|  | ||||
|                 if (config->mode & RT_SPI_MSB) { rx_data <<= 1; bit = 0x0001; } | ||||
|                 else                           { rx_data >>= 1; bit = 0x8000; } | ||||
|  | ||||
|                 if (GET_MISO(ops)) { rx_data |=  bit; } | ||||
|                 else               { rx_data &= ~bit; } | ||||
|  | ||||
|                 spi_delay2(ops); | ||||
|  | ||||
|                 if (!(config->mode & RT_SPI_CPHA) || (size != 0) || (i < 15)) | ||||
|                 { | ||||
|                     TOG_SCLK(ops); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (recv_buf != RT_NULL) | ||||
|             { | ||||
|                 *recv_ptr++ = rx_data; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return length; | ||||
| } | ||||
|  | ||||
| rt_inline rt_ssize_t spi_xfer_3line_data8(struct rt_spi_bit_ops       *ops, | ||||
|                                          struct rt_spi_configuration *config, | ||||
|                                          const void                  *send_buf, | ||||
|                                          void                        *recv_buf, | ||||
|                                          rt_size_t                    length) | ||||
| { | ||||
|     int i = 0; | ||||
|  | ||||
|     RT_ASSERT(ops != RT_NULL); | ||||
|     RT_ASSERT(length != 0); | ||||
|  | ||||
|     { | ||||
|         const rt_uint8_t *send_ptr = send_buf; | ||||
|         rt_uint8_t *recv_ptr = recv_buf; | ||||
|         rt_uint32_t size = length; | ||||
|         rt_uint8_t send_flg = 0; | ||||
|  | ||||
|         if ((send_buf != RT_NULL) || (recv_buf == RT_NULL)) | ||||
|         { | ||||
|             MOSI_OUT(ops); | ||||
|             send_flg = 1; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             MOSI_IN(ops); | ||||
|         } | ||||
|  | ||||
|         while (size--) | ||||
|         { | ||||
|             rt_uint8_t tx_data = 0xFF; | ||||
|             rt_uint8_t rx_data = 0xFF; | ||||
|             rt_uint8_t bit  = 0; | ||||
|  | ||||
|             if (send_buf != RT_NULL) | ||||
|             { | ||||
|                 tx_data = *send_ptr++; | ||||
|             } | ||||
|  | ||||
|             if (send_flg) | ||||
|             { | ||||
|                 for (i = 0; i < 8; i++) | ||||
|                 { | ||||
|                     if (config->mode & RT_SPI_MSB) { bit = tx_data & (0x1 << (7 - i)); } | ||||
|                     else                           { bit = tx_data & (0x1 << i); } | ||||
|  | ||||
|                     if (bit) MOSI_H(ops); | ||||
|                     else     MOSI_L(ops); | ||||
|  | ||||
|                     spi_delay2(ops); | ||||
|  | ||||
|                     TOG_SCLK(ops); | ||||
|  | ||||
|                     spi_delay2(ops); | ||||
|  | ||||
|                     if (!(config->mode & RT_SPI_CPHA) || (size != 0) || (i < 7)) | ||||
|                     { | ||||
|                         TOG_SCLK(ops); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 rx_data = tx_data; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 for (i = 0; i < 8; i++) | ||||
|                 { | ||||
|                     spi_delay2(ops); | ||||
|  | ||||
|                     TOG_SCLK(ops); | ||||
|  | ||||
|                     if (config->mode & RT_SPI_MSB) { rx_data <<= 1; bit = 0x01; } | ||||
|                     else                           { rx_data >>= 1; bit = 0x80; } | ||||
|  | ||||
|                     if (GET_MOSI(ops)) { rx_data |=  bit; } | ||||
|                     else               { rx_data &= ~bit; } | ||||
|  | ||||
|                     spi_delay2(ops); | ||||
|  | ||||
|                     if (!(config->mode & RT_SPI_CPHA) || (size != 0) || (i < 7)) | ||||
|                     { | ||||
|                         TOG_SCLK(ops); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|  | ||||
|             if (recv_buf != RT_NULL) | ||||
|             { | ||||
|                 *recv_ptr++ = rx_data; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (!send_flg) | ||||
|         { | ||||
|             MOSI_OUT(ops); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return length; | ||||
| } | ||||
|  | ||||
| rt_inline rt_ssize_t spi_xfer_3line_data16(struct rt_spi_bit_ops       *ops, | ||||
|                                           struct rt_spi_configuration *config, | ||||
|                                           const void                  *send_buf, | ||||
|                                           void                        *recv_buf, | ||||
|                                           rt_size_t                    length) | ||||
| { | ||||
|     int i = 0; | ||||
|  | ||||
|     RT_ASSERT(ops != RT_NULL); | ||||
|     RT_ASSERT(length != 0); | ||||
|  | ||||
|     { | ||||
|         const rt_uint16_t *send_ptr = send_buf; | ||||
|         rt_uint16_t *recv_ptr = recv_buf; | ||||
|         rt_uint32_t size = length; | ||||
|         rt_uint8_t send_flg = 0; | ||||
|  | ||||
|         if ((send_buf != RT_NULL) || (recv_buf == RT_NULL)) | ||||
|         { | ||||
|             MOSI_OUT(ops); | ||||
|             send_flg = 1; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             MOSI_IN(ops); | ||||
|         } | ||||
|  | ||||
|         while (size--) | ||||
|         { | ||||
|             rt_uint16_t tx_data = 0xFFFF; | ||||
|             rt_uint16_t rx_data = 0xFFFF; | ||||
|             rt_uint16_t bit  = 0; | ||||
|  | ||||
|             if (send_buf != RT_NULL) | ||||
|             { | ||||
|                 tx_data = *send_ptr++; | ||||
|             } | ||||
|  | ||||
|             if (send_flg) | ||||
|             { | ||||
|                 for (i = 0; i < 16; i++) | ||||
|                 { | ||||
|                     if (config->mode & RT_SPI_MSB) { bit = tx_data & (0x1 << (15 - i)); } | ||||
|                     else                           { bit = tx_data & (0x1 << i); } | ||||
|  | ||||
|                     if (bit) MOSI_H(ops); | ||||
|                     else     MOSI_L(ops); | ||||
|  | ||||
|                     spi_delay2(ops); | ||||
|  | ||||
|                     TOG_SCLK(ops); | ||||
|  | ||||
|                     spi_delay2(ops); | ||||
|  | ||||
|                     if (!(config->mode & RT_SPI_CPHA) || (size != 0) || (i < 15)) | ||||
|                     { | ||||
|                         TOG_SCLK(ops); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 rx_data = tx_data; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 for (i = 0; i < 16; i++) | ||||
|                 { | ||||
|                     spi_delay2(ops); | ||||
|  | ||||
|                     TOG_SCLK(ops); | ||||
|  | ||||
|                     if (config->mode & RT_SPI_MSB) { rx_data <<= 1; bit = 0x0001; } | ||||
|                     else                           { rx_data >>= 1; bit = 0x8000; } | ||||
|  | ||||
|                     if (GET_MOSI(ops)) { rx_data |=  bit; } | ||||
|                     else               { rx_data &= ~bit; } | ||||
|  | ||||
|                     spi_delay2(ops); | ||||
|  | ||||
|                     if (!(config->mode & RT_SPI_CPHA) || (size != 0) || (i < 15)) | ||||
|                     { | ||||
|                         TOG_SCLK(ops); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|  | ||||
|             if (recv_buf != RT_NULL) | ||||
|             { | ||||
|                 *recv_ptr++ = rx_data; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (!send_flg) | ||||
|         { | ||||
|             MOSI_OUT(ops); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return length; | ||||
| } | ||||
|  | ||||
| rt_err_t spi_bit_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration) | ||||
| { | ||||
|     struct rt_spi_bit_obj *obj = rt_container_of(device->bus, struct rt_spi_bit_obj, bus); | ||||
|     struct rt_spi_bit_ops *ops = obj->ops; | ||||
|  | ||||
|     RT_ASSERT(device != RT_NULL); | ||||
|     RT_ASSERT(configuration != RT_NULL); | ||||
|  | ||||
|     if (configuration->mode & RT_SPI_SLAVE) | ||||
|     { | ||||
|         return -RT_EIO; | ||||
|     } | ||||
|  | ||||
|     if (configuration->mode & RT_SPI_CPOL) | ||||
|     { | ||||
|         SCLK_H(ops); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         SCLK_L(ops); | ||||
|     } | ||||
|  | ||||
|     if (configuration->max_hz < 200000) | ||||
|     { | ||||
|         ops->delay_us = 1; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         ops->delay_us = 0; | ||||
|     } | ||||
|  | ||||
|     rt_memcpy(&obj->config, configuration, sizeof(struct rt_spi_configuration)); | ||||
|  | ||||
|     return RT_EOK; | ||||
| } | ||||
|  | ||||
| rt_ssize_t spi_bit_xfer(struct rt_spi_device *device, struct rt_spi_message *message) | ||||
| { | ||||
|     struct rt_spi_bit_obj *obj = rt_container_of(device->bus, struct rt_spi_bit_obj, bus); | ||||
|     struct rt_spi_bit_ops *ops = obj->ops; | ||||
|     struct rt_spi_configuration *config = &obj->config; | ||||
|     rt_base_t cs_pin = device->cs_pin; | ||||
|  | ||||
|     RT_ASSERT(device != NULL); | ||||
|     RT_ASSERT(message != NULL); | ||||
|  | ||||
| #ifdef RT_SPI_BITOPS_DEBUG | ||||
|     if (!ops->tog_sclk || !ops->set_sclk || !ops->get_sclk) | ||||
|     { | ||||
|         LOG_E("SPI bus error, SCLK line not defined"); | ||||
|     } | ||||
|     if (!ops->set_mosi || !ops->get_mosi) | ||||
|     { | ||||
|         LOG_E("SPI bus error, MOSI line not defined"); | ||||
|     } | ||||
|     if (!ops->set_miso || !ops->get_miso) | ||||
|     { | ||||
|         LOG_E("SPI bus error, MISO line not defined"); | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     /* take CS */ | ||||
|     if (message->cs_take && (cs_pin != PIN_NONE)) | ||||
|     { | ||||
|         LOG_I("spi take cs\n"); | ||||
|         rt_pin_write(cs_pin, PIN_LOW); | ||||
|         spi_delay(ops); | ||||
|  | ||||
|         /* spi phase */ | ||||
|         if (config->mode & RT_SPI_CPHA) | ||||
|         { | ||||
|             spi_delay(ops); | ||||
|             TOG_SCLK(ops); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (config->mode & RT_SPI_3WIRE) | ||||
|     { | ||||
|         if (config->data_width <= 8) | ||||
|         { | ||||
|             spi_xfer_3line_data8(ops, | ||||
|                                  config, | ||||
|                                  message->send_buf, | ||||
|                                  message->recv_buf, | ||||
|                                  message->length); | ||||
|         } | ||||
|         else if (config->data_width <= 16) | ||||
|         { | ||||
|             spi_xfer_3line_data16(ops, | ||||
|                                   config, | ||||
|                                   message->send_buf, | ||||
|                                   message->recv_buf, | ||||
|                                   message->length); | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         if (config->data_width <= 8) | ||||
|         { | ||||
|             spi_xfer_4line_data8(ops, | ||||
|                                  config, | ||||
|                                  message->send_buf, | ||||
|                                  message->recv_buf, | ||||
|                                  message->length); | ||||
|         } | ||||
|         else if (config->data_width <= 16) | ||||
|         { | ||||
|             spi_xfer_4line_data16(ops, | ||||
|                                   config, | ||||
|                                   message->send_buf, | ||||
|                                   message->recv_buf, | ||||
|                                   message->length); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* release CS */ | ||||
|     if (message->cs_release && (cs_pin != PIN_NONE)) | ||||
|     { | ||||
|         spi_delay(ops); | ||||
|         rt_pin_write(cs_pin, PIN_HIGH); | ||||
|         LOG_I("spi release cs\n"); | ||||
|     } | ||||
|  | ||||
|     return message->length; | ||||
| } | ||||
|  | ||||
| static const struct rt_spi_ops spi_bit_bus_ops = | ||||
| { | ||||
|     .configure = spi_bit_configure, | ||||
|     .xfer      = spi_bit_xfer, | ||||
| }; | ||||
|  | ||||
| rt_err_t rt_spi_bit_add_bus(struct rt_spi_bit_obj *obj, | ||||
|                             const char            *bus_name, | ||||
|                             struct rt_spi_bit_ops *ops) | ||||
| { | ||||
|     obj->ops = ops; | ||||
|     obj->config.data_width = 8; | ||||
|     obj->config.max_hz     = 1 * 1000 * 1000; | ||||
|     obj->config.mode       = RT_SPI_MASTER | RT_SPI_MSB | RT_SPI_MODE_0; | ||||
|  | ||||
|     /* idle status */ | ||||
|     if (obj->config.mode & RT_SPI_CPOL) SCLK_H(ops); | ||||
|     else                                SCLK_L(ops); | ||||
|  | ||||
|     return rt_spi_bus_register(&obj->bus, bus_name, &spi_bit_bus_ops); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user