drv_spi.c 7.3 KB
Newer Older
W
wangyq2018 已提交
1 2 3 4 5 6 7 8
/*
 * Copyright (C) 2018 Shanghai Eastsoft Microelectronics Co., Ltd.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author        Notes
 * 2019-01-24     wangyq        the first version
9
 * 2019-11-01     wangyq        update libraries
W
wangyq2018 已提交
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
 */

#include <rtthread.h>
#include <rtdevice.h>
#include <string.h>
#include <rthw.h>
#include "board.h"
#include "drv_spi.h"
#include <ald_spi.h>
#include <ald_gpio.h>
#include <ald_cmu.h>

#ifdef RT_USING_SPI

#define SPITIMEOUT 0x0FFF

rt_err_t spi_configure(struct rt_spi_device *device,
                       struct rt_spi_configuration *cfg)
{
    spi_handle_t *hspi;
    hspi = (spi_handle_t *)device->bus->parent.user_data;

32
    /* config spi mode */
W
wangyq2018 已提交
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
    if (cfg->mode & RT_SPI_SLAVE)
    {
        hspi->init.mode = SPI_MODE_SLAVER;
    }
    else
    {
        hspi->init.mode = SPI_MODE_MASTER;
    }
    if (cfg->mode & RT_SPI_3WIRE)
    {
        hspi->init.dir = SPI_DIRECTION_1LINE;
    }
    else
    {
        hspi->init.dir = SPI_DIRECTION_2LINES;
    }
    if (cfg->data_width == 8)
    {
        hspi->init.data_size = SPI_DATA_SIZE_8;
    }
    else if (cfg->data_width == 16)
    {
        hspi->init.data_size = SPI_DATA_SIZE_16;
    }

    if (cfg->mode & RT_SPI_CPHA)
    {
        hspi->init.phase = SPI_CPHA_SECOND;
    }
    else
    {
        hspi->init.phase = SPI_CPHA_FIRST;
    }
    if (cfg->mode & RT_SPI_CPOL)
    {
        hspi->init.polarity = SPI_CPOL_HIGH;
    }
    else
    {
        hspi->init.polarity = SPI_CPOL_LOW;
    }
    if (cfg->mode & RT_SPI_NO_CS)
    {
        hspi->init.ss_en = DISABLE;
    }
    else
    {
        hspi->init.ss_en = ENABLE;
    }
82 83

    /* config spi clock */
84
    if (cfg->max_hz >= ald_cmu_get_pclk1_clock() / 2)
W
wangyq2018 已提交
85
    {
86
        /* pclk1 max speed 48MHz, spi master max speed 10MHz */
87
        if (ald_cmu_get_pclk1_clock() / 2 <= 10000000)
88 89 90
        {
            hspi->init.baud = SPI_BAUD_2;
        }
91
        else if (ald_cmu_get_pclk1_clock() / 4 <= 10000000)
92 93 94 95 96 97 98
        {
            hspi->init.baud = SPI_BAUD_4;
        }
        else
        {
            hspi->init.baud = SPI_BAUD_8;
        }
W
wangyq2018 已提交
99
    }
100
    else if (cfg->max_hz >= ald_cmu_get_pclk1_clock() / 4)
W
wangyq2018 已提交
101
    {
102
        /* pclk1 max speed 48MHz, spi master max speed 10MHz */
103
        if (ald_cmu_get_pclk1_clock() / 4 <= 10000000)
104 105 106 107 108 109 110
        {
            hspi->init.baud = SPI_BAUD_4;
        }
        else
        {
            hspi->init.baud = SPI_BAUD_8;
        }
W
wangyq2018 已提交
111
    }
112
    else if (cfg->max_hz >= ald_cmu_get_pclk1_clock() / 8)
W
wangyq2018 已提交
113 114 115
    {
        hspi->init.baud = SPI_BAUD_8;
    }
116
    else if (cfg->max_hz >= ald_cmu_get_pclk1_clock() / 16)
W
wangyq2018 已提交
117 118 119
    {
        hspi->init.baud = SPI_BAUD_16;
    }
120
    else if (cfg->max_hz >= ald_cmu_get_pclk1_clock() / 32)
W
wangyq2018 已提交
121 122 123
    {
        hspi->init.baud = SPI_BAUD_32;
    }
124
    else if (cfg->max_hz >= ald_cmu_get_pclk1_clock() / 64)
W
wangyq2018 已提交
125 126 127
    {
        hspi->init.baud = SPI_BAUD_64;
    }
128
    else if (cfg->max_hz >= ald_cmu_get_pclk1_clock() / 128)
W
wangyq2018 已提交
129 130 131 132 133 134 135
    {
        hspi->init.baud = SPI_BAUD_128;
    }
    else
    {
        hspi->init.baud = SPI_BAUD_256;
    }
136
    ald_spi_init(hspi);
W
wangyq2018 已提交
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
    return RT_EOK;
}

static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message)
{
    rt_err_t res;
    spi_handle_t *hspi;
    struct es32f0_hw_spi_cs *cs;

    RT_ASSERT(device != RT_NULL);
    RT_ASSERT(device->bus != RT_NULL);
    RT_ASSERT(device->bus->parent.user_data != RT_NULL);
    RT_ASSERT(message->send_buf != RT_NULL || message->recv_buf != RT_NULL);

    hspi = (spi_handle_t *)device->bus->parent.user_data;
    cs = device->parent.user_data;

154
    /* only send data */
W
wangyq2018 已提交
155 156 157 158 159 160
    if (message->recv_buf == RT_NULL)
    {
        if (message->cs_take)
        {
            rt_pin_write(cs->pin, 0);
        }
161
        res = ald_spi_send(hspi, (rt_uint8_t *)message->send_buf, (rt_int32_t)message->length, SPITIMEOUT);
W
wangyq2018 已提交
162 163 164 165 166 167 168 169
        if (message->cs_release)
        {
            rt_pin_write(cs->pin, 1);
        }
        if (res != RT_EOK)
            return RT_ERROR;
    }

170
    /* only receive data */
W
wangyq2018 已提交
171 172 173 174 175 176
    if (message->send_buf == RT_NULL)
    {
        if (message->cs_take)
        {
            rt_pin_write(cs->pin, 0);
        }
177
        res = ald_spi_recv(hspi, (rt_uint8_t *)message->recv_buf, (rt_int32_t)message->length, SPITIMEOUT);
W
wangyq2018 已提交
178 179 180 181 182 183 184 185
        if (message->cs_release)
        {
            rt_pin_write(cs->pin, 1);
        }
        if (res != RT_EOK)
            return RT_ERROR;
    }

186
    /* send & receive */
W
wangyq2018 已提交
187 188 189 190 191 192
    else
    {
        if (message->cs_take)
        {
            rt_pin_write(cs->pin, 0);
        }
193 194
        res = ald_spi_send_recv(hspi, (rt_uint8_t *)message->send_buf, (rt_uint8_t *)message->recv_buf,
                                (rt_int32_t)message->length, SPITIMEOUT);
W
wangyq2018 已提交
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
        if (message->cs_release)
        {
            rt_pin_write(cs->pin, 1);
        }
        if (res != RT_EOK)
            return RT_ERROR;
    }

    return message->length;
}

const struct rt_spi_ops es32f0_spi_ops =
{
    spi_configure,
    spixfer,
};

212 213
static struct rt_spi_bus _spi_bus0, _spi_bus1;
static spi_handle_t _spi0, _spi1;
W
wangyq2018 已提交
214 215 216 217 218 219 220 221 222 223 224 225
int es32f0_spi_register_bus(SPI_TypeDef *SPIx, const char *name)
{
    struct rt_spi_bus *spi_bus;
    spi_handle_t *spi;
    gpio_init_t gpio_instruct;

    if (SPIx == SPI0)
    {
        _spi0.perh = SPI0;
        spi_bus = &_spi_bus0;
        spi = &_spi0;

226
        /* SPI0 gpio init */
W
wangyq2018 已提交
227 228 229 230 231 232
        gpio_instruct.mode = GPIO_MODE_OUTPUT;
        gpio_instruct.odos = GPIO_PUSH_PULL;
        gpio_instruct.func = GPIO_FUNC_4;
        gpio_instruct.type = GPIO_TYPE_CMOS;
        gpio_instruct.flt  = GPIO_FILTER_DISABLE;

233
        /* PB3->SPI0_SCK, PB5->SPI0_MOSI */
234
        ald_gpio_init(GPIOB, GPIO_PIN_3 | GPIO_PIN_5, &gpio_instruct);
W
wangyq2018 已提交
235

236
        /* PB4->SPI0_MISO */
W
wangyq2018 已提交
237
        gpio_instruct.mode = GPIO_MODE_INPUT;
238
        ald_gpio_init(GPIOB, GPIO_PIN_4, &gpio_instruct);
W
wangyq2018 已提交
239 240 241
    }
    else if (SPIx == SPI1)
    {
242
        _spi1.perh = SPI1;
W
wangyq2018 已提交
243 244 245
        spi_bus = &_spi_bus1;
        spi = &_spi1;

246
        /* SPI1 gpio init */
W
wangyq2018 已提交
247 248 249 250 251 252
        gpio_instruct.mode = GPIO_MODE_OUTPUT;
        gpio_instruct.odos = GPIO_PUSH_PULL;
        gpio_instruct.func = GPIO_FUNC_4;
        gpio_instruct.type = GPIO_TYPE_CMOS;
        gpio_instruct.flt  = GPIO_FILTER_DISABLE;

253
        /* PB13->SPI1_SCK, PB15->SPI1_MOSI */
254
        ald_gpio_init(GPIOB, GPIO_PIN_13 | GPIO_PIN_15, &gpio_instruct);
W
wangyq2018 已提交
255

256
        /* PB14->SPI1_MISO */
W
wangyq2018 已提交
257
        gpio_instruct.mode = GPIO_MODE_INPUT;
258
        ald_gpio_init(GPIOB, GPIO_PIN_14, &gpio_instruct);
W
wangyq2018 已提交
259 260 261 262 263 264 265 266 267 268 269 270
    }
    else
    {
        return -1;
    }
    spi_bus->parent.user_data = spi;

    return rt_spi_bus_register(spi_bus, name, &es32f0_spi_ops);
}

rt_err_t es32f0_spi_device_attach(rt_uint32_t pin, const char *bus_name, const char *device_name)
{
271
    /* define spi Instance */
W
wangyq2018 已提交
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
    struct rt_spi_device *spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
    RT_ASSERT(spi_device != RT_NULL);
    struct es32f0_hw_spi_cs *cs_pin = (struct es32f0_hw_spi_cs *)rt_malloc(sizeof(struct es32f0_hw_spi_cs));
    RT_ASSERT(cs_pin != RT_NULL);
    cs_pin->pin = pin;
    rt_pin_mode(pin, PIN_MODE_OUTPUT);
    rt_pin_write(pin, 1);
    return rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin);
}

int rt_hw_spi_init(void)
{
    int result = 0;

#ifdef BSP_USING_SPI0
    result = es32f0_spi_register_bus(SPI0, "spi0");
#endif

#ifdef BSP_USING_SPI1
    result = es32f0_spi_register_bus(SPI1, "spi1");
#endif

    return result;
}
INIT_BOARD_EXPORT(rt_hw_spi_init);
297 298

#endif