SPI版本更新0.0.1

This commit is contained in:
MacRsh
2023-03-19 00:45:38 +08:00
parent eb1731b9d5
commit 85bc5ea1ec
2 changed files with 421 additions and 0 deletions

326
device/spi/spi.c Normal file
View File

@@ -0,0 +1,326 @@
/*
* Copyright (c), mr-library Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-03-18 MacRsh first version
*/
#include "spi.h"
#if (MR_DEVICE_SPI == MR_CONF_ENABLE)
static mr_err_t mr_take_spi_bus(mr_spi_device_t spi_device)
{
mr_err_t ret = MR_ERR_OK;
MR_ASSERT(spi_device->bus != MR_NULL);
/* Take the mutex lock of the spi-bus */
ret = mr_mutex_take(&spi_device->bus->lock, &spi_device->device.object);
if (ret != MR_ERR_OK)
return ret;
/* Check if the current spi-device is the owner of the spi-bus */
if (spi_device->bus->owner != spi_device)
{
/* Stop the chip-select of the last spi-bus owner */
if (spi_device->bus->owner != MR_NULL)
spi_device->bus->ops->cs_set(spi_device->bus, spi_device->bus->owner->device.data, MR_DISABLE);
/* If the configuration is different, the spi-bus is reconfigured */
if (spi_device->config.baud_rate != spi_device->bus->config.baud_rate
|| spi_device->config.data_bits != spi_device->bus->config.data_bits
|| spi_device->config.master_slave != spi_device->bus->config.master_slave
|| spi_device->config.mode != spi_device->bus->config.mode
|| spi_device->config.bit_order != spi_device->bus->config.bit_order)
{
ret = spi_device->bus->ops->configure(spi_device->bus, &spi_device->config);
if (ret != MR_ERR_OK)
return ret;
}
/* Sets the spi-bus owner to the current spi-device */
spi_device->bus->config = spi_device->config;
spi_device->bus->owner = spi_device;
/* Start the chip-select of the spi-device */
spi_device->bus->ops->cs_set(spi_device->bus, spi_device->bus->owner->device.data, MR_ENABLE);
}
return MR_ERR_OK;
}
static mr_err_t mr_release_spi_bus(mr_spi_device_t spi_device)
{
MR_ASSERT(spi_device->bus != MR_NULL);
return mr_mutex_release(&spi_device->bus->lock, &spi_device->device.object);
}
static mr_err_t mr_spi_bus_open(mr_device_t device)
{
mr_spi_bus_t spi_bus = (mr_spi_bus_t)device;
struct mr_spi_config default_config = MR_SPI_CONFIG_DEFAULT;
/* Setting spi-bus to default-config */
if (spi_bus->config.baud_rate == 0)
spi_bus->config = default_config;
return spi_bus->ops->configure(spi_bus, &spi_bus->config);
}
static mr_err_t mr_spi_bus_close(mr_device_t device)
{
mr_spi_bus_t spi_bus = (mr_spi_bus_t)device;
/* Setting spi-bus to close-config */
spi_bus->config.baud_rate = 0;
return spi_bus->ops->configure(spi_bus, &spi_bus->config);
}
static mr_err_t mr_spi_device_open(mr_device_t device)
{
mr_spi_device_t spi_device = (mr_spi_device_t)device;
struct mr_spi_config default_config = MR_SPI_CONFIG_DEFAULT;
/* Setting spi-device to default-config */
if (spi_device->config.baud_rate == 0)
spi_device->config = default_config;
return MR_ERR_OK;
}
static mr_err_t mr_spi_device_close(mr_device_t device)
{
mr_spi_device_t spi_device = (mr_spi_device_t)device;
/* Setting spi-device to close-config */
spi_device->config.baud_rate = 0;
/* Disconnect from the spi-bus */
spi_device->bus = MR_NULL;
return MR_ERR_OK;
}
static mr_err_t mr_spi_device_ioctl(mr_device_t device, int cmd, void *args)
{
mr_err_t ret = MR_ERR_OK;
mr_spi_device_t spi_device = (mr_spi_device_t)device;
switch (cmd & _MR_CMD_MASK)
{
case MR_CMD_CONFIG:
{
if (args)
spi_device->config = *(struct mr_spi_config *)args;
break;
}
case MR_CMD_ATTACH:
{
if (args)
{
/* Find in the kernel spi-bus */
mr_device_t spi_bus = mr_device_find((char *)args);
if (spi_bus == MR_NULL || spi_bus->type != MR_DEVICE_TYPE_SPI_BUS)
{
ret = - MR_ERR_NOT_FOUND;
break;
}
/* Open spi-bus */
mr_device_open(spi_bus, MR_OPEN_RDWR);
spi_device->bus = (mr_spi_bus_t)spi_bus;
}
break;
}
default: ret = - MR_ERR_UNSUPPORTED;
}
return ret;
}
static mr_size_t mr_spi_device_read(mr_device_t device, mr_off_t pos, void *buffer, mr_size_t count)
{
mr_err_t ret = MR_ERR_OK;
mr_spi_device_t spi_device = (mr_spi_device_t)device;
mr_size_t recv_count = count;
/* Take spi-bus */
ret = mr_take_spi_bus(spi_device);
if (ret != MR_ERR_OK)
return 0;
switch (spi_device->config.data_bits)
{
case MR_SPI_DATA_BITS_8:
{
mr_uint8_t *recv_buffer = (mr_uint8_t *)buffer;
while (recv_count --)
{
*recv_buffer = spi_device->bus->ops->transmit(spi_device->bus, 0u);
recv_buffer ++;
}
break;
}
case MR_SPI_DATA_BITS_16:
{
mr_uint16_t *recv_buffer = (mr_uint16_t *)buffer;
while (recv_count --)
{
*recv_buffer = spi_device->bus->ops->transmit(spi_device->bus, 0u);
recv_buffer ++;
}
break;
}
case MR_SPI_DATA_BITS_32:
{
mr_uint32_t *recv_buffer = (mr_uint32_t *)buffer;
while (recv_count --)
{
*recv_buffer = spi_device->bus->ops->transmit(spi_device->bus, 0u);
recv_buffer ++;
}
break;
}
default:return 0;
}
/* Release spi-bus */
mr_release_spi_bus(spi_device);
return count;
}
static mr_size_t mr_spi_device_write(mr_device_t device, mr_off_t pos, const void *buffer, mr_size_t count)
{
mr_err_t ret = MR_ERR_OK;
mr_spi_device_t spi_device = (mr_spi_device_t)device;
mr_size_t send_count = count;
/* Take spi-bus */
ret = mr_take_spi_bus(spi_device);
if (ret != MR_ERR_OK)
return 0;
switch (spi_device->config.data_bits)
{
case MR_SPI_DATA_BITS_8:
{
mr_uint8_t *send_buffer = (mr_uint8_t *)buffer;
while (send_count --)
{
spi_device->bus->ops->transmit(spi_device->bus, *send_buffer);
send_buffer ++;
}
break;
}
case MR_SPI_DATA_BITS_16:
{
mr_uint16_t *send_buffer = (mr_uint16_t *)buffer;
while (send_count --)
{
spi_device->bus->ops->transmit(spi_device->bus, *send_buffer);
send_buffer ++;
}
break;
}
case MR_SPI_DATA_BITS_32:
{
mr_uint32_t *send_buffer = (mr_uint32_t *)buffer;
while (send_count --)
{
spi_device->bus->ops->transmit(spi_device->bus, *send_buffer);
send_buffer ++;
}
break;
}
default:return 0;
}
/* Release spi-bus */
mr_release_spi_bus(spi_device);
return count;
}
mr_err_t mr_hw_spi_bus_add_to_container(mr_spi_bus_t spi_bus, const char *name, struct mr_spi_bus_ops *ops, void *data)
{
mr_err_t ret = MR_ERR_OK;
const static struct mr_device_ops device_ops =
{
.open = mr_spi_bus_open,
.close = mr_spi_bus_close,
.ioctl = MR_NULL,
.read = MR_NULL,
.write = MR_NULL,
};
MR_ASSERT(spi_bus != MR_NULL);
MR_ASSERT(ops != MR_NULL);
/* Add the spi-bus to the container */
ret = mr_device_add_to_container(&spi_bus->device, name, MR_DEVICE_TYPE_SPI_BUS, MR_OPEN_RDWR, &device_ops, data);
if (ret != MR_ERR_OK)
return ret;
/* Initialize the spi-bus fields */
spi_bus->config.baud_rate = 0;
spi_bus->owner = MR_NULL;
mr_mutex_init(&spi_bus->lock);
/* Set spi-bus operations as protect functions if ops is null */
spi_bus->ops = ops;
return MR_ERR_OK;
}
mr_err_t mr_hw_spi_device_add_to_container(mr_spi_device_t spi_device,
const char *name,
mr_uint16_t support_flag,
void *cs_data)
{
mr_err_t ret = MR_ERR_OK;
const static struct mr_device_ops device_ops =
{
.open = mr_spi_device_open,
.close = mr_spi_device_close,
.ioctl = mr_spi_device_ioctl,
.read = mr_spi_device_read,
.write = mr_spi_device_write,
};
MR_ASSERT(spi_device != MR_NULL);
MR_ASSERT(support_flag != MR_NULL);
/* Add the spi-device to the container */
ret = mr_device_add_to_container(&spi_device->device, name, MR_DEVICE_TYPE_SPI, support_flag, &device_ops, cs_data);
if (ret != MR_ERR_OK)
return ret;
/* Initialize the spi-device fields */
spi_device->config.baud_rate = 0;
spi_device->bus = MR_NULL;
return MR_ERR_OK;
}
#endif

95
device/spi/spi.h Normal file
View File

@@ -0,0 +1,95 @@
/*
* Copyright (c), mr-library Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-03-18 MacRsh first version
*/
#ifndef _SPI_H_
#define _SPI_H_
#include <mrlib.h>
#if (MR_DEVICE_SPI == MR_CONF_ENABLE)
#define MR_SPI_DATA_BITS_8 0
#define MR_SPI_DATA_BITS_16 1
#define MR_SPI_DATA_BITS_32 2
#define MR_SPI_MASTER 0
#define MR_SPI_SLAVE 1
#define MR_SPI_MODE_0 0
#define MR_SPI_MODE_1 1
#define MR_SPI_MODE_2 2
#define MR_SPI_MODE_3 3
#define MR_SPI_BIT_ORDER_MSB 0
#define MR_SPI_BIT_ORDER_LSB 1
#define MR_SPI_CS_ACTIVE_LOW 0
#define MR_SPI_CS_ACTIVE_HIGH 1
/* Default config for mr_spi_config structure */
#define MR_SPI_CONFIG_DEFAULT \
{ \
.baud_rate = 3000000, \
.data_bits = MR_SPI_DATA_BITS_8, \
.master_slave = MR_SPI_MASTER, \
.mode = MR_SPI_MODE_0, \
.bit_order = MR_SPI_BIT_ORDER_MSB, \
.cs_active = MR_SPI_CS_ACTIVE_LOW, \
}
struct mr_spi_config
{
mr_uint32_t baud_rate;
mr_uint8_t data_bits: 2;
mr_uint8_t master_slave: 1;
mr_uint8_t mode: 2;
mr_uint8_t bit_order: 1;
mr_uint8_t cs_active: 1;
};
typedef struct mr_spi_bus *mr_spi_bus_t;
struct mr_spi_device
{
struct mr_device device;
struct mr_spi_config config;
struct mr_spi_bus *bus;
};
typedef struct mr_spi_device *mr_spi_device_t;
struct mr_spi_bus_ops
{
mr_err_t (*configure)(mr_spi_bus_t spi_bus, struct mr_spi_config *config);
void (*cs_set)(mr_spi_bus_t spi_bus, void *cs_data, mr_state_t state);
mr_uint32_t (*transmit)(mr_spi_bus_t spi_bus, mr_uint32_t send_data);
};
struct mr_spi_bus
{
struct mr_device device;
struct mr_spi_config config;
struct mr_spi_device *owner;
struct mr_mutex lock;
const struct mr_spi_bus_ops *ops;
};
mr_err_t mr_hw_spi_bus_add_to_container(mr_spi_bus_t spi_bus, const char *name, struct mr_spi_bus_ops *ops, void *data);
mr_err_t mr_hw_spi_device_add_to_container(mr_spi_device_t spi_device,
const char *name,
mr_uint16_t support_flag,
void *cs_data);
#endif
#endif