drv_spi.c 11.1 KB
Newer Older
1 2
/*
 * Copyright (c) 2006-2022, RT-Thread Development Team
N
NationsHuanghanbin 已提交
3
 *
4
 * SPDX-License-Identifier: Apache-2.0
N
NationsHuanghanbin 已提交
5
 *
6 7 8
 * Change Logs:
 * Date           Author       Notes
 * 2022-10-19     Nations      first version
N
NationsHuanghanbin 已提交
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
 */

#include "drv_spi.h"

#if defined(RT_USING_SPI) && defined(RT_USING_PIN)
#include <rtdevice.h>

#if defined(BSP_USING_SPI1) || defined(BSP_USING_SPI2) || \
    defined(BSP_USING_SPI3)

/* #define DEBUG */
#ifdef DEBUG
#define DEBUG_PRINTF(...)   rt_kprintf(__VA_ARGS__)
#else
#define DEBUG_PRINTF(...)
#endif

/* private rt-thread spi ops function */

static rt_err_t configure(struct rt_spi_device* device, struct rt_spi_configuration* configuration)
{
    SPI_InitType SPI_InitStructure;
    RCC_ClocksType RCC_ClockFreq;
    SPI_Module* spi_periph;

    RT_ASSERT(device != RT_NULL);
    RT_ASSERT(configuration != RT_NULL);
mysterywolf's avatar
mysterywolf 已提交
36

N
NationsHuanghanbin 已提交
37
    RCC_GetClocksFreqValue(&RCC_ClockFreq);
mysterywolf's avatar
mysterywolf 已提交
38

N
NationsHuanghanbin 已提交
39
    spi_periph = (SPI_Module*)device->bus->parent.user_data;
mysterywolf's avatar
mysterywolf 已提交
40

41 42
#if defined(SOC_N32G45X) || defined(SOC_N32WB452)
    if (spi_periph != SPI1 && spi_periph != SPI2 && spi_periph != SPI3)
N
NationsHuanghanbin 已提交
43 44 45
    {
        return RT_EIO;
    }
46 47 48 49 50 51 52 53
#elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X)
    if (spi_periph != SPI1 && spi_periph != SPI2)
    {
        return RT_EIO;
    }
#endif

    if (configuration->data_width <= 8)
N
NationsHuanghanbin 已提交
54 55 56
    {
        SPI_InitStructure.DataLen = SPI_DATA_SIZE_8BITS;
    }
57
    else if (configuration->data_width <= 16)
N
NationsHuanghanbin 已提交
58 59 60 61 62 63 64
    {
        SPI_InitStructure.DataLen = SPI_DATA_SIZE_16BITS;
    }
    else
    {
        return RT_EIO;
    }
mysterywolf's avatar
mysterywolf 已提交
65

N
NationsHuanghanbin 已提交
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
    {
        rt_uint32_t spi_apb_clock;
        rt_uint32_t max_hz;

        max_hz = configuration->max_hz;

        DEBUG_PRINTF("sys   freq: %d\n", RCC_ClockFreq.SysclkFreq);
        DEBUG_PRINTF("CK_APB2 freq: %d\n", RCC_ClockFreq.Pclk2Freq);
        DEBUG_PRINTF("max   freq: %d\n", max_hz);

        if (spi_periph == SPI1)
        {
            spi_apb_clock = RCC_ClockFreq.Pclk2Freq;
        }
        else
        {
            spi_apb_clock = RCC_ClockFreq.Pclk1Freq;
        }

85
        if (max_hz >= spi_apb_clock/2)
N
NationsHuanghanbin 已提交
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
        {
            SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_2;
        }
        else if (max_hz >= spi_apb_clock/4)
        {
            SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_4;
        }
        else if (max_hz >= spi_apb_clock/8)
        {
            SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_8;
        }
        else if (max_hz >= spi_apb_clock/16)
        {
            SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_16;
        }
        else if (max_hz >= spi_apb_clock/32)
        {
            SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_32;
        }
        else if (max_hz >= spi_apb_clock/64)
        {
            SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_64;
        }
        else if (max_hz >= spi_apb_clock/128)
        {
            SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_128;
        }
        else
        {
            /*  min prescaler 256 */
            SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_256;
        }
    } /* baudrate */
mysterywolf's avatar
mysterywolf 已提交
119

120
    switch (configuration->mode & RT_SPI_MODE_3)
N
NationsHuanghanbin 已提交
121 122 123
    {
        case RT_SPI_MODE_0:
            SPI_InitStructure.CLKPOL        = SPI_CLKPOL_LOW;
mysterywolf's avatar
mysterywolf 已提交
124
            SPI_InitStructure.CLKPHA        = SPI_CLKPHA_FIRST_EDGE;
N
NationsHuanghanbin 已提交
125 126 127 128 129 130 131 132 133 134 135 136 137 138
            break;
        case RT_SPI_MODE_1:
            SPI_InitStructure.CLKPOL        = SPI_CLKPOL_LOW;
            SPI_InitStructure.CLKPHA        = SPI_CLKPHA_SECOND_EDGE;
            break;
        case RT_SPI_MODE_2:
            SPI_InitStructure.CLKPOL        = SPI_CLKPOL_HIGH;
            SPI_InitStructure.CLKPHA        = SPI_CLKPHA_FIRST_EDGE;
            break;
        case RT_SPI_MODE_3:
            SPI_InitStructure.CLKPOL        = SPI_CLKPOL_HIGH;
            SPI_InitStructure.CLKPHA        = SPI_CLKPHA_SECOND_EDGE;
            break;
    }
mysterywolf's avatar
mysterywolf 已提交
139

N
NationsHuanghanbin 已提交
140
    /* MSB or LSB */
141
    if (configuration->mode & RT_SPI_MSB)
N
NationsHuanghanbin 已提交
142 143 144 145 146 147 148
    {
        SPI_InitStructure.FirstBit = SPI_FB_MSB;
    }
    else
    {
        SPI_InitStructure.FirstBit = SPI_FB_LSB;
    }
149
    /* SPI configuration */
N
NationsHuanghanbin 已提交
150 151 152
    SPI_InitStructure.DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX;
    SPI_InitStructure.SpiMode       = SPI_MODE_MASTER;
    SPI_InitStructure.NSS           = SPI_NSS_SOFT;
mysterywolf's avatar
mysterywolf 已提交
153 154
    SPI_InitStructure.CRCPoly       = 7;

N
NationsHuanghanbin 已提交
155 156
    SPI_Init(spi_periph, &SPI_InitStructure);

157
    /* Enable the sFLASH_SPI  */
N
NationsHuanghanbin 已提交
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
    SPI_Enable(spi_periph, ENABLE);

    return RT_EOK;
}

static rt_uint32_t xfer(struct rt_spi_device* device, struct rt_spi_message* message)
{
    struct n32_spi_cs *cs_pin = device->parent.user_data;
    SPI_Module* spi_periph = (SPI_Module*)device->bus->parent.user_data;
    struct rt_spi_configuration * config = &device->config;

    RT_ASSERT(device != NULL);
    RT_ASSERT(message != NULL);

    /* take CS */
173
    if (message->cs_take)
N
NationsHuanghanbin 已提交
174 175 176 177 178
    {
        rt_pin_write(cs_pin->GPIO_Pin, PIN_LOW);
        DEBUG_PRINTF("spi take cs\n");
    }

179
        if (config->data_width <= 8)
N
NationsHuanghanbin 已提交
180 181 182 183
        {
            const rt_uint8_t * send_ptr = message->send_buf;
            rt_uint8_t * recv_ptr = message->recv_buf;
            rt_uint32_t size = message->length;
mysterywolf's avatar
mysterywolf 已提交
184

N
NationsHuanghanbin 已提交
185 186
            DEBUG_PRINTF("spi poll transfer start: %d\n", size);

187
            while (size--)
N
NationsHuanghanbin 已提交
188 189 190
            {
                rt_uint8_t data = 0xA5;

191
                if (send_ptr != RT_NULL)
N
NationsHuanghanbin 已提交
192 193 194
                {
                    data = *send_ptr++;
                }
mysterywolf's avatar
mysterywolf 已提交
195

196
                /* Loop while DAT register in not emplty */
N
NationsHuanghanbin 已提交
197
                while (SPI_I2S_GetStatus(spi_periph, SPI_I2S_TE_FLAG) == RESET);
mysterywolf's avatar
mysterywolf 已提交
198

199
                /* Send the byte */
N
NationsHuanghanbin 已提交
200 201
                SPI_I2S_TransmitData(spi_periph, data);

202 203
                /* Wait until a data is received */
                while (SPI_I2S_GetStatus(spi_periph, SPI_I2S_RNE_FLAG) == RESET);
mysterywolf's avatar
mysterywolf 已提交
204

205
                /* Get the received data */
N
NationsHuanghanbin 已提交
206
                data = SPI_I2S_ReceiveData(spi_periph);
mysterywolf's avatar
mysterywolf 已提交
207

208
                if (recv_ptr != RT_NULL)
N
NationsHuanghanbin 已提交
209
                {
210
                        *recv_ptr++ = data;
N
NationsHuanghanbin 已提交
211 212 213 214
                }
            }
            DEBUG_PRINTF("spi poll transfer finsh\n");
        }
215
        else if (config->data_width <= 16)
N
NationsHuanghanbin 已提交
216 217 218 219 220
        {
            const rt_uint16_t * send_ptr = message->send_buf;
            rt_uint16_t * recv_ptr = message->recv_buf;
            rt_uint32_t size = message->length;

221
            while (size--)
N
NationsHuanghanbin 已提交
222 223 224
            {
                rt_uint16_t data = 0xFF;

225
                if (send_ptr != RT_NULL)
N
NationsHuanghanbin 已提交
226 227 228
                {
                    data = *send_ptr++;
                }
mysterywolf's avatar
mysterywolf 已提交
229

230
                /* Loop while DAT register in not emplty */
N
NationsHuanghanbin 已提交
231
                while (SPI_I2S_GetStatus(spi_periph, SPI_I2S_TE_FLAG) == RESET);
mysterywolf's avatar
mysterywolf 已提交
232

233
                /* Send the byte */
N
NationsHuanghanbin 已提交
234 235
                SPI_I2S_TransmitData(spi_periph, data);

236 237
                /* Wait until a data is received */
                while (RESET == SPI_I2S_GetStatus(spi_periph, SPI_I2S_RNE_FLAG));
mysterywolf's avatar
mysterywolf 已提交
238

239
                /* Get the received data */
N
NationsHuanghanbin 已提交
240 241
                data = SPI_I2S_ReceiveData(spi_periph);

242
                if (recv_ptr != RT_NULL)
N
NationsHuanghanbin 已提交
243
                {
244
                        *recv_ptr++ = data;
N
NationsHuanghanbin 已提交
245 246 247 248 249
                }
            }
        }

    /* release CS */
250
    if (message->cs_release)
N
NationsHuanghanbin 已提交
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
    {
        rt_pin_write(cs_pin->GPIO_Pin, PIN_HIGH);
        DEBUG_PRINTF("spi release cs\n");
    }

    return message->length;
}

static struct rt_spi_ops spi_ops =
{
    configure,
    xfer
};

int rt_hw_spi_init(void)
{
    int result = 0;
268
    GPIO_InitType GPIO_InitStructure;
mysterywolf's avatar
mysterywolf 已提交
269

N
NationsHuanghanbin 已提交
270 271 272 273 274
#ifdef BSP_USING_SPI1
    static struct rt_spi_bus spi_bus1;
    spi_bus1.parent.user_data = (void *)SPI1;

    result = rt_spi_bus_register(&spi_bus1, "spi1", &spi_ops);
mysterywolf's avatar
mysterywolf 已提交
275

276 277 278 279 280 281 282 283 284 285
#if defined(SOC_N32G45X) || defined(SOC_N32WB452)
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA | RCC_APB2_PERIPH_SPI1, ENABLE);

    GPIO_InitStruct(&GPIO_InitStructure);

    /* Confige SPI1_SCLK(PA5) and SPI1_MOSI(PA7) */
    GPIO_InitStructure.Pin        = GPIO_PIN_5 | GPIO_PIN_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
mysterywolf's avatar
mysterywolf 已提交
286

287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
    /* Confige SPI1_MISO(PA6) */
    GPIO_InitStructure.Pin        = GPIO_PIN_6;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
#elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X)
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_SPI1 | RCC_APB2_PERIPH_AFIO, ENABLE);

    GPIO_InitStruct(&GPIO_InitStructure);
    /* Confige SPI1_SCLK(PA5) and SPI1_MISO(PA6) and SPI1_MOSI(PA7) */
    GPIO_InitStructure.Pin            = GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
    GPIO_InitStructure.GPIO_Mode      = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Alternate = GPIO_AF0_SPI1;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
#endif
N
NationsHuanghanbin 已提交
302
#endif
303

N
NationsHuanghanbin 已提交
304 305 306 307
#ifdef BSP_USING_SPI2
    static struct rt_spi_bus spi_bus2;
    spi_bus2.parent.user_data = (void *)SPI2;

mysterywolf's avatar
mysterywolf 已提交
308
    result = rt_spi_bus_register(&spi_bus2, "spi2", &spi_ops);
N
NationsHuanghanbin 已提交
309

310 311
#if defined(SOC_N32G45X) || defined(SOC_N32WB452)
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);
mysterywolf's avatar
mysterywolf 已提交
312 313
    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_SPI2, ENABLE);

314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
    GPIO_InitStruct(&GPIO_InitStructure);

    /* Confige SPI2_SCLK(PB13) and SPI2_MOSI(PB15) */
    GPIO_InitStructure.Pin        = GPIO_PIN_13 | GPIO_PIN_15;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);

    /* Confige SPI2_MISO(PB14) */
    GPIO_InitStructure.Pin        = GPIO_PIN_14;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
    GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
#elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X)
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_SPI2 | RCC_APB2_PERIPH_AFIO, ENABLE);

    GPIO_InitStruct(&GPIO_InitStructure);
    /* Confige SPI2_SCLK(PB13) and SPI2_MISO(PB14) and SPI2_MOSI(PB15) */
    GPIO_InitStructure.Pin            = GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
    GPIO_InitStructure.GPIO_Mode      = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Alternate = GPIO_AF0_SPI2;
    GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
N
NationsHuanghanbin 已提交
336
#endif
337 338
#endif

N
NationsHuanghanbin 已提交
339 340 341 342 343
#ifdef BSP_USING_SPI3
    static struct rt_spi_bus spi_bus3;
    spi_bus3.parent.user_data = (void *)SPI3;

    result = rt_spi_bus_register(&spi_bus3, "spi3", &spi_ops);
mysterywolf's avatar
mysterywolf 已提交
344

345 346
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB | RCC_APB2_PERIPH_AFIO, ENABLE);
    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_SPI3, ENABLE);
mysterywolf's avatar
mysterywolf 已提交
347

N
NationsHuanghanbin 已提交
348
    GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_SW_ENABLE, ENABLE);
mysterywolf's avatar
mysterywolf 已提交
349

350 351 352 353 354 355 356
    GPIO_InitStruct(&GPIO_InitStructure);

    /* Confige SPI3_SCLK(PB3) and SPI3_MOSI(PB5) */
    GPIO_InitStructure.Pin        = GPIO_PIN_3 | GPIO_PIN_5;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
mysterywolf's avatar
mysterywolf 已提交
357

358 359 360 361
    /* Confige SPI3_MISO(PB4) */
    GPIO_InitStructure.Pin        = GPIO_PIN_4;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
    GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
N
NationsHuanghanbin 已提交
362 363 364 365 366 367 368
#endif
    return result;
}
INIT_BOARD_EXPORT(rt_hw_spi_init);

#endif /* defined(BSP_USING_SPI1) || defined(BSP_USING_SPI2) || defined(BSP_USING_SPI3) */
#endif