123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- /*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2021-10-11 kyle first implementation.
- */
- #include "drv_soft_spi.h"
- #include <board.h>
- #include <rtthread.h>
- #if defined(RT_USING_SPI) && defined(RT_USING_SPI_BITOPS) && defined(RT_USING_PIN)
- #include <rtdevice.h>
- #include "spi-bit-ops.h"
- #define DBG_TAG "drv.SPI"
- #ifdef RT_SPI_DEBUG
- #define DBG_LVL DBG_LOG
- #else
- #define DBG_LVL DBG_WARNING
- #endif
- #include <rtdbg.h>
- #ifndef ITEM_NUM
- #define ITEM_NUM(items) sizeof(items) / sizeof(items[0])
- #endif
- struct gd32_spi_bit_data
- {
- struct
- {
- rcu_periph_enum clk;
- rt_uint32_t port;
- rt_uint32_t pin;
- } sclk, mosi, miso;
- };
- rt_inline FlagStatus GPIO_OUTPUT_BIT_GET(uint32_t gpio_periph, uint32_t pin)
- {
- if((uint32_t)RESET !=(GPIO_OCTL(gpio_periph)&(pin))){
- return SET;
- }else{
- return RESET;
- }
- }
- rt_inline void GPIO_BIT_RESET(uint32_t gpio_periph, uint32_t pin)
- {
- GPIO_BC(gpio_periph) = (uint32_t)pin;
- }
- rt_inline void GPIO_BIT_SET(uint32_t gpio_periph, uint32_t pin)
- {
- GPIO_BOP(gpio_periph) = (uint32_t)pin;
- }
- rt_inline FlagStatus GPIO_INPUT_BIT_GET(uint32_t gpio_periph,uint32_t pin)
- {
- if((uint32_t)RESET != (GPIO_ISTAT(gpio_periph)&(pin))){
- return SET;
- }else{
- return RESET;
- }
- }
- rt_inline void GPIO_INIT(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin)
- {
- uint16_t i;
- uint32_t temp_mode = 0U;
- uint32_t reg = 0U;
- /* GPIO mode configuration */
- temp_mode = (uint32_t)(mode & ((uint32_t)0x0FU));
- /* GPIO speed configuration */
- if(((uint32_t)0x00U) != ((uint32_t)mode & ((uint32_t)0x10U))){
- /* output mode max speed:10MHz,2MHz,50MHz */
- temp_mode |= (uint32_t)speed;
- }
- /* configure the eight low port pins with GPIO_CTL0 */
- for(i = 0U;i < 8U;i++){
- if((1U << i) & pin){
- reg = GPIO_CTL0(gpio_periph);
- /* clear the specified pin mode bits */
- reg &= ~GPIO_MODE_MASK(i);
- /* set the specified pin mode bits */
- reg |= GPIO_MODE_SET(i, temp_mode);
- /* set IPD or IPU */
- if(GPIO_MODE_IPD == mode){
- /* reset the corresponding OCTL bit */
- GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin);
- }else{
- /* set the corresponding OCTL bit */
- if(GPIO_MODE_IPU == mode){
- GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin);
- }
- }
- /* set GPIO_CTL0 register */
- GPIO_CTL0(gpio_periph) = reg;
- }
- }
- /* configure the eight high port pins with GPIO_CTL1 */
- for(i = 8U;i < 16U;i++){
- if((1U << i) & pin){
- reg = GPIO_CTL1(gpio_periph);
- /* clear the specified pin mode bits */
- reg &= ~GPIO_MODE_MASK(i - 8U);
- /* set the specified pin mode bits */
- reg |= GPIO_MODE_SET(i - 8U, temp_mode);
- /* set IPD or IPU */
- if(GPIO_MODE_IPD == mode){
- /* reset the corresponding OCTL bit */
- GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin);
- }else{
- /* set the corresponding OCTL bit */
- if(GPIO_MODE_IPU == mode){
- GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin);
- }
- }
- /* set GPIO_CTL1 register */
- GPIO_CTL1(gpio_periph) = reg;
- }
- }
- }
- #define GPIO_SET_OUTPUT(port, pin) GPIO_INIT(port, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, pin)
- #define GPIO_SET_INPUT(port, pin) GPIO_INIT(port, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, pin)
- static void gpio_tog_sclk(void *data)
- {
- struct gd32_spi_bit_data *bd = data;
- if (GPIO_OUTPUT_BIT_GET(bd->sclk.port, bd->sclk.pin) == SET)
- {
- GPIO_BIT_RESET(bd->sclk.port, bd->sclk.pin);
- }
- else
- {
- GPIO_BIT_SET(bd->sclk.port, bd->sclk.pin);
- }
- }
- static void gpio_set_sclk(void *data, rt_int32_t state)
- {
- struct gd32_spi_bit_data *bd = data;
- if (state)
- {
- GPIO_BIT_SET(bd->sclk.port, bd->sclk.pin);
- }
- else
- {
- GPIO_BIT_RESET(bd->sclk.port, bd->sclk.pin);
- }
- }
- static void gpio_set_mosi(void *data, rt_int32_t state)
- {
- struct gd32_spi_bit_data *bd = data;
- if (state)
- {
- GPIO_BIT_SET(bd->mosi.port, bd->mosi.pin);
- }
- else
- {
- GPIO_BIT_RESET(bd->mosi.port, bd->mosi.pin);
- }
- }
- static void gpio_set_miso(void *data, rt_int32_t state)
- {
- struct gd32_spi_bit_data *bd = data;
- if (state)
- {
- GPIO_BIT_SET(bd->miso.port, bd->miso.pin);
- }
- else
- {
- GPIO_BIT_RESET(bd->miso.port, bd->miso.pin);
- }
- }
- static rt_int32_t gpio_get_sclk(void *data)
- {
- struct gd32_spi_bit_data *bd = data;
- return GPIO_INPUT_BIT_GET(bd->sclk.port, bd->sclk.pin);
- }
- static rt_int32_t gpio_get_mosi(void *data)
- {
- struct gd32_spi_bit_data *bd = data;
- return GPIO_INPUT_BIT_GET(bd->mosi.port, bd->mosi.pin);
- }
- static rt_int32_t gpio_get_miso(void *data)
- {
- struct gd32_spi_bit_data *bd = data;
- return GPIO_INPUT_BIT_GET(bd->miso.port, bd->miso.pin);
- }
- static void gpio_dir_mosi(void *data, rt_int32_t state)
- {
- struct gd32_spi_bit_data *bd = data;
- if (state)
- {
- GPIO_SET_INPUT(bd->mosi.port, bd->mosi.pin);
- }
- else
- {
- GPIO_SET_OUTPUT(bd->mosi.port, bd->mosi.pin);
- }
- }
- static void gpio_dir_miso(void *data, rt_int32_t state)
- {
- struct gd32_spi_bit_data *bd = data;
- if (state)
- {
- GPIO_SET_INPUT(bd->miso.port, bd->miso.pin);
- }
- else
- {
- GPIO_SET_OUTPUT(bd->miso.port, bd->miso.pin);
- }
- }
- static void gpio_udelay(rt_uint32_t us)
- {
- int i = ((rcu_clock_freq_get(CK_SYS) / 4000000) * us);
- while (i)
- {
- i--;
- }
- }
- static void soft_spi_gpio_init(const struct gd32_spi_bit_data *bd)
- {
- rcu_periph_clock_enable(bd->sclk.clk);
- rcu_periph_clock_enable(bd->mosi.clk);
- rcu_periph_clock_enable(bd->miso.clk);
- gpio_init(bd->sclk.port, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, bd->sclk.pin);
- gpio_init(bd->mosi.port, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, bd->mosi.pin);
- gpio_init(bd->miso.port, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, bd->miso.pin);
- GPIO_BIT_SET(bd->sclk.port, bd->sclk.pin);
- GPIO_BIT_SET(bd->mosi.port, bd->mosi.pin);
- GPIO_BIT_SET(bd->miso.port, bd->miso.pin);
- }
- int rt_soft_spi_init(void)
- {
- int result = 0;
- {
- static const struct gd32_spi_bit_data spi1_bdata =
- {
- .sclk = { RCU_GPIOB, GPIOB, GPIO_PIN_13},
- .mosi = { RCU_GPIOB, GPIOB, GPIO_PIN_15},
- .miso = { RCU_GPIOB, GPIOB, GPIO_PIN_14},
- };
- static struct rt_spi_bit_ops spi1_bops =
- {
- .data = (void *)&spi1_bdata,
- .tog_sclk = gpio_tog_sclk,
- .set_sclk = gpio_set_sclk,
- .set_mosi = gpio_set_mosi,
- .set_miso = gpio_set_miso,
- .get_sclk = gpio_get_sclk,
- .get_mosi = gpio_get_mosi,
- .get_miso = gpio_get_miso,
- .dir_mosi = gpio_dir_mosi,
- .dir_miso = gpio_dir_miso,
- .udelay = gpio_udelay,
- };
- struct rt_spi_bit_obj spi1_obj;
- soft_spi_gpio_init(&spi1_bdata);
- rt_spi_bit_add_bus(&spi1_obj, "spi3", &spi1_bops);
- }
- return result;
- }
- INIT_BOARD_EXPORT(rt_soft_spi_init);
- #endif
|