123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- /*
- * Copyright (c) 2006-2020, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-05-28 hqfang first implementation.
- */
- #include "drv_spi.h"
- #ifdef RT_USING_SPI
- #if !defined(BSP_USING_SPI0) && !defined(BSP_USING_SPI1) && !defined(BSP_USING_SPI2)
- #error "Please define at least one BSP_USING_SPIx"
- /* this driver can be disabled at menuconfig -> Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable SPI */
- #endif
- static struct gd32_spi_config spi_config[] =
- {
- #ifdef BSP_USING_SPI0
- {
- "spi0",
- SPI0,
- },
- #endif
- #ifdef BSP_USING_SPI1
- {
- "spi1",
- SPI1,
- },
- #endif
- #ifdef BSP_USING_SPI2
- {
- "spi2",
- SPI2,
- },
- #endif
- };
- static struct gd32_spi spi_obj[sizeof(spi_config) / sizeof(spi_config[0])] = {0};
- static rt_err_t gd32_spi_init(rt_uint32_t spi_periph, struct rt_spi_configuration *cfg)
- {
- spi_parameter_struct spicfg;
- uint32_t apbfreq;
- uint32_t scale;
- RT_ASSERT(cfg != RT_NULL);
- spi_struct_para_init(&spicfg);
- if (cfg->data_width != 8 && cfg->data_width != 16)
- {
- return (-RT_EINVAL);
- }
- switch (spi_periph)
- {
- case SPI0:
- apbfreq = rcu_clock_freq_get(CK_APB2);
- break;
- default:
- apbfreq = rcu_clock_freq_get(CK_APB1);
- break;
- }
- scale = apbfreq / cfg->max_hz;
- if (scale <= 2)
- {
- spicfg.prescale = SPI_PSC_2;
- }
- else if (scale <= 4)
- {
- spicfg.prescale = SPI_PSC_4;
- }
- else if (scale <= 8)
- {
- spicfg.prescale = SPI_PSC_8;
- }
- else if (scale <= 16)
- {
- spicfg.prescale = SPI_PSC_16;
- }
- else if (scale <= 32)
- {
- spicfg.prescale = SPI_PSC_32;
- }
- else if (scale <= 64)
- {
- spicfg.prescale = SPI_PSC_64;
- }
- else if (scale <= 128)
- {
- spicfg.prescale = SPI_PSC_128;
- }
- else if (scale <= 256)
- {
- spicfg.prescale = SPI_PSC_256;
- }
- else
- {
- spicfg.prescale = SPI_PSC_256;
- }
- if (cfg->data_width == 8)
- {
- spicfg.frame_size = SPI_FRAMESIZE_8BIT;
- }
- else
- {
- spicfg.frame_size = SPI_FRAMESIZE_16BIT;
- }
- if (cfg->mode & RT_SPI_MSB)
- {
- spicfg.endian = SPI_ENDIAN_MSB;
- }
- else
- {
- spicfg.endian = SPI_ENDIAN_LSB;
- }
- spicfg.clock_polarity_phase = 0;
- if (cfg->mode & RT_SPI_CPHA)
- {
- spicfg.clock_polarity_phase |= SPI_CTL0_CKPH;
- }
- if (cfg->mode & RT_SPI_CPOL)
- {
- spicfg.clock_polarity_phase |= SPI_CTL0_CKPL;
- }
- if (cfg->mode & RT_SPI_SLAVE)
- {
- spicfg.device_mode = SPI_SLAVE;
- }
- else
- {
- spicfg.device_mode = SPI_MASTER;
- }
- spicfg.nss = SPI_NSS_SOFT;
- spicfg.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
- spi_init(spi_periph, &spicfg);
- /* set crc polynomial */
- spi_crc_polynomial_set(spi_periph, 7);
- return RT_EOK;
- }
- static rt_err_t gd32_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg)
- {
- rt_err_t ret = RT_EOK;
- RT_ASSERT(device != RT_NULL);
- struct gd32_spi *spi_obj = (struct gd32_spi *)(device->bus->parent.user_data);
- struct gd32_spi_config *spi_cfg = (struct gd32_spi_config *)(spi_obj->config);
- ret = gd32_spi_init(spi_cfg->spi_periph, cfg);
- /* enable SPI */
- spi_enable(spi_cfg->spi_periph);
- return ret;
- }
- /**
- * Attach the spi device to SPI bus, this function must be used after initialization.
- */
- rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t pin)
- {
- rt_err_t ret = RT_EOK;
- struct rt_spi_device *spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
- RT_ASSERT(spi_device != RT_NULL);
- struct gd32_spi_cs *cs_pin = (struct gd32_spi_cs *)rt_malloc(sizeof(struct gd32_spi_cs));
- RT_ASSERT(cs_pin != RT_NULL);
- cs_pin->pin = pin;
- rt_pin_mode(pin, PIN_MODE_OUTPUT);
- rt_pin_write(pin, PIN_HIGH);
- ret = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin);
- return ret;
- }
- rt_size_t gd32_spi_transmit(rt_uint32_t spi_periph, const void *send_buf, void *recv_buf, rt_size_t length)
- {
- uint8_t *send_buf_8b = (uint8_t *)send_buf;
- uint8_t *recv_buf_8b = (uint8_t *)recv_buf;
- uint8_t sndbyte = 0xFF, rcvbyte;
- rt_size_t idx = 0;
- while (idx < length)
- {
- while (RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TBE));
- if (send_buf_8b)
- {
- sndbyte = send_buf_8b[idx];
- }
- spi_i2s_data_transmit(spi_periph, sndbyte);
- while (RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE));
- rcvbyte = spi_i2s_data_receive(spi_periph);
- if (recv_buf_8b)
- {
- recv_buf_8b[idx] = rcvbyte;
- }
- idx ++;
- }
- return length;
- }
- static rt_uint32_t gd32_spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
- {
- rt_uint32_t total_length = 0;
- rt_err_t ret = RT_EOK;
- RT_ASSERT(device != RT_NULL);
- struct gd32_spi *spi_obj = (struct gd32_spi *)(device->bus->parent.user_data);
- struct gd32_spi_config *spi_cfg = (struct gd32_spi_config *)(spi_obj->config);
- RT_ASSERT(spi_cfg != RT_NULL);
- struct gd32_spi_cs *cs = (struct gd32_spi_cs *)(device->parent.user_data);
- if (message && message->cs_take)
- {
- rt_pin_write(cs->pin, PIN_LOW);
- }
- if (message && message->length)
- {
- total_length += gd32_spi_transmit(spi_cfg->spi_periph, message->send_buf, \
- message->recv_buf, message->length);
- }
- if (message && message->cs_release)
- {
- rt_pin_write(cs->pin, PIN_HIGH);
- }
- return total_length;
- }
- static const struct rt_spi_ops spi_ops =
- {
- gd32_spi_configure,
- gd32_spi_xfer
- };
- int rt_hw_spi_init(void)
- {
- rt_size_t obj_num;
- int index;
- rt_err_t result = 0;
- #ifdef BSP_USING_SPI0
- rcu_periph_clock_enable(RCU_SPI0);
- #endif
- #ifdef BSP_USING_SPI1
- rcu_periph_clock_enable(RCU_SPI1);
- #endif
- #ifdef BSP_USING_SPI2
- rcu_periph_clock_enable(RCU_SPI2);
- #endif
- obj_num = sizeof(spi_obj) / sizeof(struct gd32_spi);
- for (index = 0; index < obj_num; index++)
- {
- /* init spi object */
- spi_obj[index].config = &spi_config[index];
- spi_obj[index].bus.parent.user_data = &spi_obj[index];
- /* register spi device */
- result = rt_spi_bus_register(&spi_obj[index].bus,
- spi_obj[index].config->name,
- &spi_ops);
- RT_ASSERT(result == RT_EOK);
- }
- return 0;
- }
- INIT_DEVICE_EXPORT(rt_hw_spi_init);
- #endif
- /* end of spi driver */
|