建立基础版本

This commit is contained in:
MacRsh
2023-03-09 16:49:41 +08:00
parent be28e5a0ef
commit de89af97c1
10 changed files with 1445 additions and 0 deletions

View File

@@ -1,5 +1,7 @@
`mr-library`
# 简介
**mr-library** 创建于2023年1月是一款开源驱动库。mr-library主要采用C语言编写可快速移植到各种平台主要以嵌入式mcu为主
**mr-library** 区分驱动内核、驱动抽象层、设备层,都支持模块化裁剪。驱动抽象层和设备层支持独立使用。
@@ -7,14 +9,18 @@
----------
# **mr-library** 特点
* 资源占用低。
- 简单易用,结构清晰。
- 通用性强,不同平台仅需适配少量接口即可使用。
* 松解耦,模块化。
----------
# 代码目录
mr-library源代码目录结构如下图所示
|名称|描述|
|:---|:---|
@@ -25,7 +31,9 @@ mr-library源代码目录结构如下图所示
|src|内核源文件|
----------
# 贡献代码
如果您对 mr-library 感兴趣,并希望参与到开发成为代码贡献者,可以联系我(email)macrsh@outlook.com
## 感谢各位对本仓库的贡献!

11
bsp/board.h Normal file
View File

@@ -0,0 +1,11 @@
//
// Created by 10632 on 2023/3/8.
//
#ifndef _BOARD_H_
#define _BOARD_H_
#include "stdio.h"
#include "stdlib.h"
#endif

272
device/serial.c Normal file
View File

@@ -0,0 +1,272 @@
/*
* Copyright (c), mr-library Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-03-09 MacRsh first version
*/
#include "serial.h"
mr_err_t mr_serial_init(mr_serial_t serial, struct mr_serial_config *config)
{
mr_err_t error_code = MR_ERR_OK;
struct mr_serial_fifo *fifo = MR_NULL;
/* Check that the fifo has been allocated */
if (serial->rx_fifo != MR_NULL || serial->tx_fifo != MR_NULL)
return -MR_ERR_GENERIC;
if (config->fifo_size != 0)
{
if (config->fifo_size < MR_SERIAL_FIFO_MIN_SIZE)
config->fifo_size = MR_SERIAL_FIFO_MIN_SIZE;
/* Allocation the rx-fifo memory */
fifo = (struct mr_serial_fifo *) mr_malloc(sizeof(struct mr_serial_fifo *) + config->fifo_size);
if (fifo == MR_NULL)
return -MR_ERR_NO_MEMORY;
mr_ringbuffer_init(&fifo->ringbuffer, fifo->pool, config->fifo_size);
serial->rx_fifo = fifo;
fifo = MR_NULL;
/* Allocation the tx-fifo memory */
fifo = (struct mr_serial_fifo *) mr_malloc(sizeof(struct mr_serial_fifo *) + config->fifo_size);
if (fifo == MR_NULL)
return -MR_ERR_NO_MEMORY;
mr_ringbuffer_init(&fifo->ringbuffer, fifo->pool, config->fifo_size);
serial->tx_fifo = fifo;
fifo = MR_NULL;
}
/* Initialize the underlying hardware */
if (serial->ops->configure != MR_NULL)
{
error_code = serial->ops->configure(serial, config);
if (error_code != MR_ERR_OK)
return error_code;
serial->config = *config;
return MR_ERR_OK;
} else
return -MR_ERR_IO;
}
mr_err_t mr_serial_uninit(mr_serial_t serial)
{
struct mr_serial_fifo *fifo = MR_NULL;
if (serial->config.fifo_size != 0)
{
/* Check that the fifo has been allocated */
if (serial->rx_fifo == MR_NULL || serial->tx_fifo == MR_NULL)
return -MR_ERR_GENERIC;
/* Release the rx-fifo memory */
fifo = (struct mr_serial_fifo *) serial->rx_fifo;
mr_free(fifo);
serial->rx_fifo = MR_NULL;
/* Release the tx-fifo memory */
fifo = (struct mr_serial_fifo *) serial->tx_fifo;
mr_free(fifo);
serial->tx_fifo = MR_NULL;
}
/* Uninitialize the underlying hardware */
if (serial->ops->configure != MR_NULL)
{
serial->config.baud_rate = 0;
return serial->ops->configure(serial, &serial->config);
} else
return -MR_ERR_IO;
}
mr_size_t mr_serial_write(mr_serial_t serial, const mr_uint8_t *buffer, mr_size_t count)
{
mr_size_t send_count = count;
if (serial->ops->write_byte != MR_NULL)
{
while (send_count--)
{
serial->ops->write_byte(serial, *buffer);
buffer++;
}
return count;
} else
{
// MR_LOG_E();
return 0;
}
}
mr_size_t mr_serial_write_byte(mr_serial_t serial, mr_uint8_t data)
{
if (serial->ops->write_byte != MR_NULL)
{
serial->ops->write_byte(serial, data);
return 1;
} else
{
// MR_LOG_E();
return 0;
}
}
mr_size_t mr_serial_read(mr_serial_t serial, mr_uint8_t *buffer, mr_size_t count)
{
struct mr_serial_fifo *fifo = MR_NULL;
mr_size_t recv_count;
if (serial->config.fifo_size != 0)
{
fifo = (struct mr_serial_fifo *) serial->rx_fifo;
do
{
recv_count = mr_ringbuffer_get_data_length(&fifo->ringbuffer);
} while (recv_count < count);
return mr_ringbuffer_read(&fifo->ringbuffer, buffer, count);
} else
return 0;
}
mr_size_t mr_serial_read_byte(mr_serial_t serial, mr_uint8_t *data)
{
struct mr_serial_fifo *fifo = MR_NULL;
mr_size_t recv_count;
if (serial->config.fifo_size != 0)
{
fifo = (struct mr_serial_fifo *) serial->rx_fifo;
do
{
recv_count = mr_ringbuffer_get_data_length(&fifo->ringbuffer);
} while (recv_count < 1);
return mr_ringbuffer_read_byte(&fifo->ringbuffer, data);
} else
return 0;
}
static mr_err_t mr_device_serial_open(mr_device_t device)
{
mr_serial_t serial = (mr_serial_t) device;
return mr_serial_init(serial, &serial->config);
}
static mr_err_t mr_device_serial_close(mr_device_t device)
{
mr_serial_t serial = (mr_serial_t) device;
return mr_serial_uninit(serial);
}
static mr_err_t mr_device_serial_ioctl(mr_device_t device, int cmd, void *args)
{
mr_serial_t serial = (mr_serial_t) device;
struct mr_serial_config config = serial->config;
switch (cmd & _MR_CMD_MASK)
{
case MR_CMD_CONFIG:
{
config = *(struct mr_serial_config *) args;
/* The fifo size cannot be changed once the device is opened */
if ((config.fifo_size != serial->config.fifo_size) && (device->ref_count > 0))
return -MR_ERR_BUSY;
else
return mr_serial_init(serial, &config);
}
case MR_CMD_SET_RX_CALLBACK:
{
device->rx_callback = (mr_err_t (*)(mr_device_t device, void *args)) args;
return MR_ERR_OK;
}
default:return -MR_ERR_UNSUPPORTED;
}
}
static mr_size_t mr_device_serial_read(mr_device_t device, mr_off_t pos, void *buffer, mr_size_t count)
{
mr_serial_t serial = (mr_serial_t) device;
if (count == 0) return 0;
return mr_serial_read(serial, buffer, count);
}
static mr_size_t mr_device_serial_write(mr_device_t device, mr_off_t pos, const void *buffer, mr_size_t count)
{
mr_serial_t serial = (mr_serial_t) device;
if (count == 0) return 0;
return mr_serial_write(serial, buffer, count);
}
mr_err_t mr_serial_add_to_container(mr_serial_t serial, const char *name, struct mr_serial_ops *ops, void *data)
{
mr_err_t error_code = MR_ERR_OK;
struct mr_serial_config default_config = MR_SERIAL_CONFIG_DEFAULT;
const static struct mr_serial_ops null_ops = {MR_NULL};
const static struct mr_device_ops device_ops =
{
.open = mr_device_serial_open,
.close = mr_device_serial_close,
.ioctl = mr_device_serial_ioctl,
.read = mr_device_serial_read,
.write = mr_device_serial_write,
};
/* Initialize the device and add the device to the container */
mr_device_init(&serial->device, name);
error_code = mr_device_add_to_container(&serial->device, MR_DEVICE_TYPE_SERIAL, MR_OPEN_RDWR, &device_ops, data);
if (error_code != MR_ERR_OK)
return error_code;
/* Initialize the serial fields */
serial->config = default_config;
serial->tx_fifo = MR_NULL;
serial->rx_fifo = MR_NULL;
/* Set serial's operations as null_ops if ops is null */
serial->ops = (ops == MR_NULL) ? &null_ops : ops;
return MR_ERR_OK;
}
void mr_hw_serial_isr(mr_serial_t serial, mr_uint16_t event)
{
switch (event & _MR_SERIAL_EVENT_MASK)
{
case MR_SERIAL_EVENT_RX_INT:
{
struct mr_serial_fifo *fifo = (struct mr_serial_fifo *) serial->rx_fifo;
mr_uint8_t data = 0;
/* Read data into the ring buffer */
data = serial->ops->read_byte(serial);
mr_ringbuffer_write_byte_force(&fifo->ringbuffer, data);
/* Invoke the rx-callback function */
if (serial->device.rx_callback != MR_NULL)
{
mr_size_t rx_length = 0;
rx_length = mr_ringbuffer_get_data_length(&fifo->ringbuffer);
serial->device.rx_callback(&serial->device, &rx_length);
}
break;
}
default:break;
}
}

98
device/serial.h Normal file
View File

@@ -0,0 +1,98 @@
/*
* Copyright (c), mr-library Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-03-09 MacRsh first version
*/
#ifndef _SERIAL_H_
#define _SERIAL_H_
#include <mrlib.h>
#define MR_SERIAL_DATA_BITS_8 8
#define MR_SERIAL_DATA_BITS_9 9
#define MR_SERIAL_STOP_BITS_1 1
#define MR_SERIAL_STOP_BITS_1_5 2
#define MR_SERIAL_STOP_BITS_2 3
#define MR_SERIAL_PARITY_NONE 0
#define MR_SERIAL_PARITY_EVEN 1
#define MR_SERIAL_PARITY_ODD 2
#define MR_SERIAL_BIT_ORDER_LSB 0
#define MR_SERIAL_BIT_ORDER_MSB 1
#define MR_SERIAL_NRZ_NORMAL 0
#define MR_SERIAL_NRZ_INVERTED 1
#define MR_SERIAL_FIFO_MIN_SIZE MR_SERIAL_FIFO_MIN
#define MR_SERIAL_EVENT_RX_INT 0x1000
#define _MR_SERIAL_EVENT_MASK 0xf000
/* Default config for serial_configure structure */
#define MR_SERIAL_CONFIG_DEFAULT \
{ \
115200, \
MR_SERIAL_DATA_BITS_8, \
MR_SERIAL_STOP_BITS_1, \
MR_SERIAL_PARITY_NONE, \
MR_SERIAL_BIT_ORDER_LSB, \
MR_SERIAL_NRZ_NORMAL, \
MR_SERIAL_FIFO_MIN_SIZE \
}
struct mr_serial_config
{
mr_uint32_t baud_rate;
mr_uint32_t data_bits: 4;
mr_uint32_t stop_bits: 2;
mr_uint32_t parity: 2;
mr_uint32_t bit_order: 1;
mr_uint32_t invert: 1;
mr_uint32_t fifo_size: 16;
mr_uint32_t reserved: 6;
};
struct mr_serial_fifo
{
struct mr_ringbuffer ringbuffer;
mr_uint8_t pool[];
};
typedef struct mr_serial *mr_serial_t;
struct mr_serial_ops
{
mr_err_t (*configure)(mr_serial_t serial, struct mr_serial_config *config);
void (*write_byte)(mr_serial_t serial, mr_uint8_t data);
mr_uint8_t (*read_byte)(mr_serial_t serial);
};
struct mr_serial
{
struct mr_device device;
struct mr_serial_config config;
void *rx_fifo;
void *tx_fifo;
const struct mr_serial_ops *ops;
};
mr_err_t mr_serial_init(mr_serial_t serial, struct mr_serial_config *config);
mr_err_t mr_serial_uninit(mr_serial_t serial);
mr_size_t mr_serial_write_byte(mr_serial_t serial, mr_uint8_t data);
mr_size_t mr_serial_write(mr_serial_t serial, const mr_uint8_t *buffer, mr_size_t count);
mr_size_t mr_serial_read(mr_serial_t serial, mr_uint8_t *buffer, mr_size_t count);
mr_size_t mr_serial_read_byte(mr_serial_t serial, mr_uint8_t *data);
mr_err_t mr_serial_add_to_container(mr_serial_t serial, const char *name, struct mr_serial_ops *ops, void *data);
void mr_hw_serial_isr(mr_serial_t serial, mr_uint16_t event);
#endif

252
include/mrdef.h Normal file
View File

@@ -0,0 +1,252 @@
/*
* Copyright (c), mr-library Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-03-08 MacRsh first version
*/
#ifndef _MR_DEF_H_
#define _MR_DEF_H_
#include <mrconfig.h>
#include "malloc.h"
#define mr_malloc malloc
#define mr_free free
#include "string.h"
#define mr_strncmp strncmp
#define mr_strncpy strncpy
#define mr_memset memset
#define mr_memcpy memcpy
/* mr-library version information */
#define MR_LIBRARY_VERSION "0.0.1"
/* mr-library basic data_p type definitions */
typedef signed char mr_int8_t; /**< 8bit integer type */
typedef signed short mr_int16_t; /**< 16bit integer type */
typedef signed int mr_int32_t; /**< 32bit integer type */
typedef unsigned char mr_uint8_t; /**< 8bit unsigned integer type */
typedef unsigned short mr_uint16_t; /**< 16bit unsigned integer type */
typedef unsigned int mr_uint32_t; /**< 32bit unsigned integer type */
typedef float mr_float;
typedef double mr_double;
typedef signed long long mr_int64_t; /**< 64bit integer type */
typedef unsigned long long mr_uint64_t; /**< 64bit unsigned integer type */
typedef unsigned int mr_size_t; /**< Type for size number */
typedef signed int mr_base_t; /**< Nbit CPU related date type */
typedef unsigned int mr_ubase_t; /**< Nbit unsigned CPU related cs_data type */
typedef mr_base_t mr_err_t; /**< Type for error number */
typedef mr_base_t mr_off_t; /**< Type for offset */
#define MR_NULL 0
/* mr-library error code definitions */
#define MR_ERR_OK 0 /**< There is no error */
#define MR_ERR_GENERIC 1 /**< A generic error happens */
#define MR_ERR_OVERFLOW 2 /**< Overflow */
#define MR_ERR_NO_MEMORY 3 /**< No memory */
#define MR_ERR_IO 4 /**< IO error */
#define MR_ERR_INVALID 5 /**< Invalid argument */
#define MR_ERR_TIMEOUT 6 /**< Timed out */
#define MR_ERR_BUSY 7 /**< Busy */
#define MR_ERR_NOT_FOUND 8 /**< Not found */
#define MR_ERR_UNSUPPORTED 9 /**< Unsupported feature */
/* mr-library basic open flag definitions */
#define MR_OPEN_CLOSED 0x0000 /**< Closed */
#define MR_OPEN_RDONLY 0x1000 /**< Read only */
#define MR_OPEN_WRONLY 0x2000 /**< Write only */
#define MR_OPEN_RDWR 0x3000 /**< Read and Write */
#define MR_OPEN_NONBLOCKING_RD 0x4000 /**< Non-blocking Read */
#define MR_OPEN_NONBLOCKING_WR 0x8000 /**< Non-blocking Write */
#define MR_OPEN_ACTIVE 0x0100 /**< Active */
#define _MR_OPEN_FLAG_MASK 0xf000
/* mr-library basic command definitions */
#define MR_CMD_NULL 0x0000 /**< Null command */
#define MR_CMD_CONFIG 0x1000 /**< Configure command */
#define MR_CMD_SET_RX_CALLBACK 0x2000 /**< Set rx callback command */
#define MR_CMD_SET_TX_CALLBACK 0x3000 /**< Set tx callback command */
#define MR_CMD_ATTACH 0x4000 /**< Attach command */
#define MR_CMD_DETACH 0x5000
#define MR_CMD_TRANSFER 0x6000 /**< Transfer command */
#define _MR_CMD_MASK 0xf000 /**< Mask for getting command */
/* Compiler Related Definitions */
#if defined(__ARMCC_VERSION)
#define MR_SECTION(x) __attribute__((section(x)))
#define MR_USED __attribute__((used))
#define MR_ALIGN(n) __attribute__((aligned(n)))
#define MR_WEAK __attribute__((weak))
#define MR_INLINE static __inline
#elif defined (__IAR_SYSTEMS_ICC__)
#define MR_SECTION(x) @ x
#define MR_USED __root
#define PRAGMA(x) _Pragma(#x)
#define MR_ALIGN(n) PRAGMA(data_alignment=n)
#define MR_WEAK __weak
#define MR_INLINE static inline
#elif defined (__GNUC__)
#define MR_SECTION(x) __attribute__((section(x)))
#define MR_USED __attribute__((used))
#define MR_ALIGN(n) __attribute__((aligned(n)))
#define MR_WEAK __attribute__((weak))
#define MR_INLINE static __inline
#elif defined (__ADSPBLACKFIN__)
#define MR_SECTION(x) __attribute__((section(x)))
#define MR_USED __attribute__((used))
#define MR_ALIGN(n) __attribute__((aligned(n)))
#define MR_WEAK __attribute__((weak))
#define MR_INLINE static inline
#elif defined (_MSC_VER)
#define MR_SECTION(x)
#define MR_USED
#define MR_ALIGN(n) __declspec(align(n))
#define MR_WEAK
#define MR_INLINE static __inline
#elif defined (__TASKING__)
#define MR_SECTION(x) __attribute__((section(x)))
#define MR_USED __attribute__((used, protect))
#define mrAGMA(x) _Pragma(#x)
#define MR_ALIGN(n) __attribute__((__align(n)))
#define MR_WEAK __attribute__((weak))
#define MR_INLINE static inline
#endif
typedef enum mr_bool
{
MR_FALSE = 0, MR_TRUE = 1
} mr_bool_t;
typedef enum mr_level
{
MR_LOW = 0, MR_HIGH = 1
} mr_level_t;
struct mr_list
{
struct mr_list *next; /**< point to next node. */
struct mr_list *prev; /**< point to prev node. */
};
typedef struct mr_list *mr_list_t;
enum mr_container_type
{
MR_CONTAINER_TYPE_MISC,
MR_CONTAINER_TYPE_DEVICE,
_MR_CONTAINER_TYPE_MASK,
};
struct mr_container
{
enum mr_container_type type;
struct mr_list list;
};
typedef struct mr_container *mr_container_t;
#define MR_OBJECT_TYPE_NULL 0x00
#define MR_OBJECT_TYPE_REGISTER 0x40
#define MR_OBJECT_TYPE_STATIC 0x80
struct mr_object
{
char name[MR_NAME_MAX];
mr_uint8_t type;
struct mr_list list;
};
typedef struct mr_object *mr_object_t;
struct mr_mutex
{
enum
{
MR_UNLOCK = 0,
MR_LOCK,
} lock;
mr_object_t owner;
};
typedef struct mr_mutex *mr_mutex_t;
enum mr_ringbuffer_state
{
MR_RINGBUFFER_EMPTY,
MR_RINGBUFFER_FULL,
MR_RINGBUFFER_HALF_FULL,
};
struct mr_ringbuffer
{
mr_uint8_t *buffer;
mr_uint16_t read_mirror: 1;
mr_uint16_t read_index: 15;
mr_uint16_t write_mirror: 1;
mr_uint16_t write_index: 15;
mr_uint16_t buffer_size;
};
typedef struct mr_ringbuffer *mr_ringbuffer_t;
enum mr_device_type
{
MR_DEVICE_TYPE_NULL,
MR_DEVICE_TYPE_PIN,
MR_DEVICE_TYPE_SPI_BUS,
MR_DEVICE_TYPE_SPI,
MR_DEVICE_TYPE_I2C_BUS,
MR_DEVICE_TYPE_I2C,
MR_DEVICE_TYPE_SERIAL,
MR_DEVICE_TYPE_ADC,
MR_DEVICE_TYPE_DAC,
MR_DEVICE_TYPE_PWM,
MR_DEVICE_TYPE_TIMER,
MR_DEVICE_TYPE_WDT,
MR_DEVICE_TYPE_FLASH,
MR_DEVICE_TYPE_SDRAM,
/* ... */
MR_DEVICE_TYPE_LINK,
MR_DEVICE_TYPE_LINK_SERVICE,
};
typedef struct mr_device *mr_device_t;
struct mr_device_ops
{
mr_err_t (*open)(mr_device_t device);
mr_err_t (*close)(mr_device_t device);
mr_err_t (*ioctl)(mr_device_t device, int cmd, void *args);
mr_size_t (*read)(mr_device_t device, mr_off_t pos, void *buffer, mr_size_t count);
mr_size_t (*write)(mr_device_t device, mr_off_t pos, const void *buffer, mr_size_t count);
};
struct mr_device
{
struct mr_object object;
mr_err_t (*rx_callback)(mr_device_t this, void *args);
mr_err_t (*tx_callback)(mr_device_t this, void *args);
enum mr_device_type type;
mr_uint16_t support_flag;
mr_uint16_t open_flag;
mr_uint8_t ref_count;
void *data;
const struct mr_device_ops *ops;
};
#endif

81
include/mrlib.h Normal file
View File

@@ -0,0 +1,81 @@
/*
* Copyright (c), mr-library Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-03-08 MacRsh first version
*/
#ifndef _MR_LIB_H_
#define _MR_LIB_H_
#include <mrdef.h>
#include <mrserve.h>
mr_container_t mr_container_find(enum mr_container_type type);
mr_object_t mr_object_find(const char *name, enum mr_container_type type);
void mr_object_init(mr_object_t object, const char *name);
mr_object_t mr_object_create(const char *name);
mr_err_t mr_object_add_to_container(mr_object_t object, enum mr_container_type container_type);
mr_err_t mr_object_remove_from_container(mr_object_t object);
mr_err_t mr_object_move(mr_object_t object, enum mr_container_type dest_type);
void mr_object_rename(mr_object_t object, char *name);
mr_bool_t mr_object_is_static(mr_object_t object);
void mr_mutex_init(mr_mutex_t mutex);
mr_err_t mr_mutex_take(mr_mutex_t mutex, mr_object_t owner);
mr_err_t mr_mutex_release(mr_mutex_t mutex, mr_object_t owner);
void mr_ringbuffer_init(mr_ringbuffer_t ringbuffer, mr_uint8_t *pool, mr_size_t pool_size);
mr_size_t mr_ringbuffer_get_data_length(mr_ringbuffer_t ringbuffer);
mr_size_t mr_ringbuffer_write(mr_ringbuffer_t ringbuffer, const mr_uint8_t *buffer, mr_size_t length);
mr_size_t mr_ringbuffer_write_byte(mr_ringbuffer_t ringbuffer, mr_uint8_t data);
mr_size_t mr_ringbuffer_write_byte_force(mr_ringbuffer_t ringbuffer, mr_uint8_t data);
mr_size_t mr_ringbuffer_write_force(mr_ringbuffer_t ringbuffer, const mr_uint8_t *buffer, mr_size_t length);
mr_size_t mr_ringbuffer_read(mr_ringbuffer_t ringbuffer, mr_uint8_t *buffer, mr_size_t length);
mr_size_t mr_ringbuffer_read_byte(mr_ringbuffer_t ringbuffer, mr_uint8_t *data);
mr_device_t mr_device_find(const char *name);
void mr_device_init(mr_device_t device, const char *name);
mr_err_t mr_device_add_to_container(mr_device_t device,
enum mr_device_type type,
mr_uint16_t support_flag,
const struct mr_device_ops *ops,
void *data);
mr_err_t mr_device_open(mr_device_t device, mr_uint16_t flags);
mr_err_t mr_device_close(mr_device_t device);
mr_err_t mr_device_ioctl(mr_device_t device, int cmd, void *args);
mr_size_t mr_device_read(mr_device_t device, mr_off_t pos, void *buf, mr_size_t count);
mr_size_t mr_device_write(mr_device_t device, mr_off_t pos, const void *buf, mr_size_t count);
#define MR_LOG_D(string) \
printf("[ DEBUG ] [ %s ][ %d ][ %s ] { %s }\r\n", \
__FILE__, \
__LINE__, \
__FUNCTION__, \
string \
)
#define MR_LOG_W(string) \
printf("[ WARING ] [ %s ][ %d ][ %s ] { %s }\r\n", \
__FILE__, \
__LINE__, \
__FUNCTION__, \
string \
)
#define MR_LOG_E(string, error) \
if (error != MR_ERR_OK) \
{ \
printf("[ ERROR ] [ %s ][ %d ][ %s ] { %s }{ %d }\r\n", \
__FILE__, \
__LINE__, \
__FUNCTION__, \
string, \
error); \
}
#endif

44
include/mrserve.h Normal file
View File

@@ -0,0 +1,44 @@
//
// Created by 10632 on 2023/3/8.
//
#ifndef DESIGN_MR_LIBRARY_INCLUDE_MRSERVE_H_
#define DESIGN_MR_LIBRARY_INCLUDE_MRSERVE_H_
#include <mrdef.h>
#define mr_hw_interrupt_enable() \
do{ \
}while(0)
#define mr_hw_interrupt_disable()\
do{ \
}while(0)
#define mr_container_of(ptr, type, member) \
((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
MR_INLINE void mr_list_init(mr_list_t list)
{
list->next = list;
list->prev = list;
}
MR_INLINE void mr_list_insert_after(mr_list_t list, mr_list_t node)
{
list->next->prev = node;
node->next = list->next;
list->next = node;
node->prev = list;
}
MR_INLINE void mr_list_remove(mr_list_t node)
{
node->next->prev = node->prev;
node->prev->next = node->next;
node->next = node->prev = node;
}
#endif //DESIGN_MR_LIBRARY_INCLUDE_MRSERVE_H_

21
mrconfig.h Normal file
View File

@@ -0,0 +1,21 @@
#ifndef _MR_CONFIG_H_
#define _MR_CONFIG_H_
#define MR_CONF_ENABLE 1
#define MR_CONF_DISABLE 0
#include <board.h>
#define MR_NAME_MAX 10
#define MR_LIBRARY MR_CONF_ENABLE
#define MR_DEVICE_PIN CONF_ENABLE
#define MR_DEVICE_SPI CONF_ENABLE
#define MR_DEVICE_ADC CONF_ENABLE
#define MR_DEVICE_DAC CONF_ENABLE
#define MR_DEVICE_I2C CONF_ENABLE
#define MR_DEVICE_SERIAL CONF_ENABLE
#define MR_SERIAL_FIFO_MIN 64
#endif

231
src/device.c Normal file
View File

@@ -0,0 +1,231 @@
/*
* Copyright (c), mr-library Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-03-09 MacRsh first version
*/
#include <mrlib.h>
mr_device_t mr_device_find(const char *name)
{
mr_device_t device = MR_NULL;
/* Debug log */
MR_LOG_D(name);
/* Find the device object from the device container */
device = (mr_device_t) mr_object_find(name, MR_CONTAINER_TYPE_DEVICE);
if (device == MR_NULL)
{
/* Error log */
MR_LOG_E(name, -MR_ERR_NOT_FOUND);
return MR_NULL;
}
return device;
}
void mr_device_init(mr_device_t device, const char *name)
{
/* Debug log */
MR_LOG_D(name);
/* Initialize the object */
mr_object_init(&device->object, name);
/* Initialize the private fields */
device->rx_callback = MR_NULL;
device->tx_callback = MR_NULL;
device->type = MR_DEVICE_TYPE_NULL;
device->support_flag = MR_OPEN_CLOSED;
device->open_flag = MR_OPEN_CLOSED;
device->ref_count = 0;
device->data = MR_NULL;
device->ops = MR_NULL;
}
mr_err_t mr_device_add_to_container(mr_device_t device,
enum mr_device_type type,
mr_uint16_t support_flag,
const struct mr_device_ops *ops,
void *data)
{
mr_err_t error_code = MR_ERR_OK;
static struct mr_device_ops null_ops = {MR_NULL};
/* Debug log */
MR_LOG_D(device->object.name);
/* Initialize the private fields */
device->type = type;
device->support_flag = support_flag;
device->data = data;
/* Set operations as null_ops if ops is null */
device->ops = (ops == MR_NULL) ? &null_ops : ops;
/* Register the object to the container */
error_code = mr_object_add_to_container(&device->object, MR_CONTAINER_TYPE_DEVICE);
MR_LOG_E(device->object.name, error_code);
return error_code;
}
mr_err_t mr_device_open(mr_device_t device, mr_uint16_t flags)
{
mr_err_t error_code = MR_ERR_OK;
/* Debug log */
MR_LOG_D(device->object.name);
/* Check if the specified open flags are supported by the device */
if (flags != (flags & device->support_flag))
{
/* Error log */
MR_LOG_E(device->object.name, -MR_ERR_UNSUPPORTED);
return -MR_ERR_UNSUPPORTED;
}
/* Check if the device is already closed */
if (!(device->open_flag & MR_OPEN_ACTIVE))
{
device->open_flag = (flags & _MR_OPEN_FLAG_MASK);
/* Call the device open function, if provided */
if (device->ops->open != MR_NULL)
{
error_code = device->ops->open(device);
/* Error log */
MR_LOG_E(device->object.name, error_code);
if (error_code != MR_ERR_OK)
return error_code;
}
/* Update the device type as active */
device->open_flag |= MR_OPEN_ACTIVE;
device->ref_count++;
}
return MR_ERR_OK;
}
mr_err_t mr_device_close(mr_device_t device)
{
mr_err_t error_code = MR_ERR_OK;
/* Debug log */
MR_LOG_D(device->object.name);
/* If the reference count is zero, the device has already been closed */
if (device->ref_count == 0)
{
device->open_flag = MR_OPEN_CLOSED;
return MR_ERR_OK;
}
/* Decrement the reference count */
device->ref_count--;
/* If the reference count is still non-zero, return without closing the device */
if (device->ref_count != 0)
return MR_ERR_OK;
/* Call the device close function, if provided */
if (device->ops->close != MR_NULL)
{
error_code = device->ops->close(device);
/* Error log */
MR_LOG_E(device->object.name, error_code);
if (error_code != MR_ERR_OK)
return error_code;
}
return MR_ERR_OK;
}
mr_err_t mr_device_ioctl(mr_device_t device, int cmd, void *args)
{
mr_err_t error_code = MR_ERR_OK;
/* Debug log */
MR_LOG_D(device->object.name);
/* Check if the device is closed */
if (device->ref_count == 0)
{
/* Error log */
MR_LOG_E(device->object.name, -MR_ERR_UNSUPPORTED);
return -MR_ERR_UNSUPPORTED;
}
/* Call the device ioctl function, if provided */
if (device->ops->ioctl != MR_NULL)
{
error_code = device->ops->ioctl(device, cmd, args);
/* Error log */
MR_LOG_E(device->object.name, error_code);
return error_code;
} else
{
/* Error log */
MR_LOG_E(device->object.name, -MR_ERR_IO);
return -MR_ERR_UNSUPPORTED;
}
}
mr_size_t mr_device_read(mr_device_t device, mr_off_t pos, void *buf, mr_size_t count)
{
/* Debug log */
MR_LOG_D(device->object.name);
/* Check if the device is closed or unsupported */
if ((device->ref_count == 0) || !(device->open_flag & MR_OPEN_RDONLY))
{
/* Error log */
MR_LOG_E(device->object.name, -MR_ERR_UNSUPPORTED);
return 0;
}
/* Call the device read function, if provided */
if (device->ops->read != MR_NULL)
{
return device->ops->read(device, pos, buf, count);
} else
{
/* Error log */
MR_LOG_E(device->object.name, -MR_ERR_IO);
return 0;
}
}
mr_size_t mr_device_write(mr_device_t device, mr_off_t pos, const void *buf, mr_size_t count)
{
/* Debug log */
MR_LOG_D(device->object.name);
/* Check if the device is closed or unsupported */
if ((device->ref_count == 0) || !(device->open_flag & MR_OPEN_WRONLY))
{
/* Error log */
MR_LOG_E(device->object.name, -MR_ERR_UNSUPPORTED);
return 0;
}
/* Call the device write function, if provided */
if (device->ops->write != MR_NULL)
{
return device->ops->write(device, pos, buf, count);
} else
{
/* Error log */
MR_LOG_E(device->object.name, -MR_ERR_IO);
return 0;
}
}

427
src/kernel.c Normal file
View File

@@ -0,0 +1,427 @@
/*
* Copyright (c), mr-library Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-03-08 MacRsh first version
*/
#include <mrlib.h>
static struct mr_container mr_kernel_container[_MR_CONTAINER_TYPE_MASK] =
{
{.type = MR_CONTAINER_TYPE_MISC,
.list = {&mr_kernel_container[MR_CONTAINER_TYPE_MISC].list,
&mr_kernel_container[MR_CONTAINER_TYPE_MISC].list}},
{.type = MR_CONTAINER_TYPE_DEVICE,
.list = {&mr_kernel_container[MR_CONTAINER_TYPE_DEVICE].list,
&mr_kernel_container[MR_CONTAINER_TYPE_DEVICE].list}},
};
mr_container_t mr_container_find(enum mr_container_type type)
{
/* Check if the kernel has this container type */
if (type >= _MR_CONTAINER_TYPE_MASK)
return MR_NULL;
return &mr_kernel_container[type];
}
mr_object_t mr_object_find(const char *name, enum mr_container_type type)
{
mr_list_t list = MR_NULL;
mr_container_t container = MR_NULL;
/* Get corresponding container */
container = mr_container_find(type);
if (container == MR_NULL)
return MR_NULL;
/* Walk through the container looking for objects */
for (list = (container->list).next; list != &(container->list); list = list->next)
{
mr_object_t object;
object = mr_container_of(list, struct mr_object, list);
if (object == MR_NULL)
continue;
if (mr_strncmp(object->name, name, MR_NAME_MAX) == 0)
return object;
}
return MR_NULL;
}
void mr_object_init(mr_object_t object, const char *name)
{
/* Set the object list to its initial state */
mr_list_init(&(object->list));
/* Copy the specified name to the object name */
mr_strncpy(object->name, name, MR_NAME_MAX);
/* Set the object type to initialized */
object->type = MR_OBJECT_TYPE_NULL;
object->type |= MR_OBJECT_TYPE_STATIC;
}
mr_object_t mr_object_create(const char *name)
{
mr_object_t object = MR_NULL;
/* Allocate memory for the object */
object = (mr_object_t) mr_malloc(sizeof(struct mr_object));
if (object == MR_NULL)
return MR_NULL;
/* Initialize the memory */
mr_memset(object, 0x0, sizeof(struct mr_object));
/* Set the object list to its initial state */
mr_list_init(&(object->list));
/* Copy the specified name to the object name */
mr_strncpy(object->name, name, MR_NAME_MAX);
return object;
}
mr_err_t mr_object_add_to_container(mr_object_t object, enum mr_container_type container_type)
{
mr_container_t container = MR_NULL;
/* Check if the object is already registered */
if (object->type & MR_OBJECT_TYPE_REGISTER)
return -MR_ERR_BUSY;
/* Find the container for the specified type */
container = mr_container_find(container_type);
if (container == MR_NULL)
return -MR_ERR_NOT_FOUND;
/* Check if the object already exists in the container */
if (mr_object_find(object->name, container_type) != MR_NULL)
return -MR_ERR_GENERIC;
/* Insert the object into the container's list */
mr_list_insert_after(&(container->list), &(object->list));
object->type |= MR_OBJECT_TYPE_REGISTER;
return MR_ERR_OK;
}
mr_err_t mr_object_remove_from_container(mr_object_t object)
{
mr_err_t error_code = MR_ERR_OK;
/* Check if the object is registered */
if ((object->type & MR_OBJECT_TYPE_REGISTER) == 0)
return -MR_ERR_GENERIC;
/* Remove the object from the container's list */
mr_list_remove(&(object->list));
object->type &= ~MR_OBJECT_TYPE_REGISTER;
return error_code;
}
mr_err_t mr_object_move(mr_object_t object, enum mr_container_type dest_type)
{
mr_err_t error_code = MR_ERR_OK;
/* Remove the object from its current container */
error_code = mr_object_remove_from_container(object);
if (error_code != MR_ERR_OK)
return error_code;
/* Add the object to the new container */
error_code = mr_object_add_to_container(object, dest_type);
return error_code;
}
void mr_object_rename(mr_object_t object, char *name)
{
mr_strncpy(object->name, name, MR_NAME_MAX);
}
mr_bool_t mr_object_is_static(mr_object_t object)
{
if (object->type & MR_OBJECT_TYPE_STATIC)
return MR_TRUE;
else
return MR_FALSE;
}
void mr_mutex_init(mr_mutex_t mutex)
{
mutex->owner = MR_NULL;
mutex->lock = MR_UNLOCK;
}
mr_err_t mr_mutex_take(mr_mutex_t mutex, mr_object_t owner)
{
mr_hw_interrupt_disable();
if (mutex->owner != owner)
{
if (mutex->lock == MR_LOCK)
{
mr_hw_interrupt_enable();
return -MR_ERR_BUSY;
}
mutex->owner = owner;
}
mutex->lock = MR_LOCK;
mr_hw_interrupt_enable();
return MR_ERR_OK;
}
mr_err_t mr_mutex_release(mr_mutex_t mutex, mr_object_t owner)
{
mr_hw_interrupt_disable();
if (mutex->owner == owner)
{
mutex->lock = MR_UNLOCK;
mr_hw_interrupt_enable();
return MR_ERR_OK;
}
mr_hw_interrupt_enable();
return -MR_ERR_GENERIC;
}
void mr_ringbuffer_init(mr_ringbuffer_t ringbuffer, mr_uint8_t *pool, mr_size_t pool_size)
{
ringbuffer->read_mirror = ringbuffer->read_index = 0;
ringbuffer->write_mirror = ringbuffer->write_index = 0;
ringbuffer->buffer = pool;
ringbuffer->buffer_size = pool_size;
}
MR_INLINE enum mr_ringbuffer_state mr_ringbuffer_get_state(mr_ringbuffer_t ringbuffer)
{
if (ringbuffer->read_index == ringbuffer->write_index)
{
if (ringbuffer->read_mirror == ringbuffer->write_mirror)
return MR_RINGBUFFER_EMPTY;
else
return MR_RINGBUFFER_FULL;
}
return MR_RINGBUFFER_HALF_FULL;
}
mr_size_t mr_ringbuffer_get_data_length(mr_ringbuffer_t ringbuffer)
{
mr_size_t wi, ri;
switch (mr_ringbuffer_get_state(ringbuffer))
{
case MR_RINGBUFFER_EMPTY:return 0;
case MR_RINGBUFFER_FULL:return ringbuffer->buffer_size;
default:
{
wi = ringbuffer->write_index;
ri = ringbuffer->read_index;
if (wi > ri)
return wi - ri;
else
return (ringbuffer->buffer_size - (ri - wi));
}
}
}
MR_INLINE mr_size_t mr_ringbuffer_space_length(mr_ringbuffer_t ringbuffer)
{
return (ringbuffer->buffer_size - mr_ringbuffer_get_data_length(ringbuffer));
}
mr_size_t mr_ringbuffer_write(mr_ringbuffer_t ringbuffer, const mr_uint8_t *buffer, mr_size_t length)
{
mr_size_t space_length;
space_length = mr_ringbuffer_space_length(ringbuffer);
if (space_length == 0)
return 0;
if (space_length < length)
length = space_length;
if ((ringbuffer->buffer_size - ringbuffer->write_index) > length)
{
mr_memcpy(&ringbuffer->buffer[ringbuffer->write_index], buffer, length);
ringbuffer->write_index += length;
return length;
} else
{
mr_memcpy(&ringbuffer->buffer[ringbuffer->write_index],
&buffer[0],
(ringbuffer->buffer_size - ringbuffer->write_index));
mr_memcpy(&ringbuffer->buffer[0],
&buffer[ringbuffer->buffer_size - ringbuffer->write_index],
(length - (ringbuffer->buffer_size - ringbuffer->write_index)));
ringbuffer->write_mirror = ~ringbuffer->write_mirror;
ringbuffer->write_index = (length - (ringbuffer->buffer_size - ringbuffer->write_index));
return length;
}
}
mr_size_t mr_ringbuffer_write_force(mr_ringbuffer_t ringbuffer, const mr_uint8_t *buffer, mr_size_t length)
{
mr_size_t space_length;
space_length = mr_ringbuffer_space_length(ringbuffer);
if (space_length == 0)
return 0;
if (ringbuffer->buffer_size < length)
{
buffer = &buffer[length - ringbuffer->buffer_size];
length = ringbuffer->buffer_size;
}
if ((ringbuffer->buffer_size - ringbuffer->write_index) > length)
{
mr_memcpy(&ringbuffer->buffer[ringbuffer->write_index], buffer, length);
ringbuffer->write_index += length;
if (length > space_length)
ringbuffer->read_index = ringbuffer->write_index;
return length;
} else
{
mr_memcpy(&ringbuffer->buffer[ringbuffer->write_index],
&buffer[0],
(ringbuffer->buffer_size - ringbuffer->write_index));
mr_memcpy(&ringbuffer->buffer[0],
&buffer[ringbuffer->buffer_size - ringbuffer->write_index],
(length - (ringbuffer->buffer_size - ringbuffer->write_index)));
ringbuffer->write_mirror = ~ringbuffer->write_mirror;
ringbuffer->write_index = (length - (ringbuffer->buffer_size - ringbuffer->write_index));
if (length > space_length)
{
if (ringbuffer->write_index <= ringbuffer->read_index)
ringbuffer->read_mirror = ~ringbuffer->read_mirror;
ringbuffer->read_index = ringbuffer->write_index;
}
return length;
}
}
mr_size_t mr_ringbuffer_read(mr_ringbuffer_t ringbuffer, mr_uint8_t *buffer, mr_size_t length)
{
mr_size_t count;
count = mr_ringbuffer_get_data_length(ringbuffer);
if (count == 0)
return 0;
if (count < length)
length = count;
if ((ringbuffer->buffer_size - ringbuffer->read_index) > length)
{
mr_memcpy(&buffer[0], &ringbuffer->buffer[ringbuffer->read_index], length);
ringbuffer->read_index += length;
return length;
}
/* read index cross mirror */
mr_memcpy(buffer,
&ringbuffer->buffer[ringbuffer->read_index],
ringbuffer->buffer_size - ringbuffer->read_index);
mr_memcpy(&buffer[ringbuffer->buffer_size - ringbuffer->read_index],
ringbuffer->buffer,
length - (ringbuffer->buffer_size - ringbuffer->read_index));
ringbuffer->read_mirror = ~ringbuffer->read_mirror;
ringbuffer->read_index = length - (ringbuffer->buffer_size - ringbuffer->read_index);
return length;
}
mr_size_t mr_ringbuffer_write_byte(mr_ringbuffer_t ringbuffer, mr_uint8_t data)
{
/* Whether there is enough space */
if (!mr_ringbuffer_space_length(ringbuffer))
return 0;
ringbuffer->buffer[ringbuffer->write_index] = data;
/* flip mirror */
if (ringbuffer->write_index == ringbuffer->buffer_size - 1)
{
ringbuffer->write_mirror = ~ringbuffer->write_mirror;
ringbuffer->write_index = 0;
} else
{
ringbuffer->write_index++;
}
return 1;
}
mr_size_t mr_ringbuffer_write_byte_force(mr_ringbuffer_t ringbuffer, mr_uint8_t data)
{
enum mr_ringbuffer_state old_state;
old_state = mr_ringbuffer_get_state(ringbuffer);
ringbuffer->buffer[ringbuffer->write_index] = data;
/* flip mirror */
if (ringbuffer->write_index == ringbuffer->buffer_size - 1)
{
ringbuffer->write_mirror = ~ringbuffer->write_mirror;
ringbuffer->write_index = 0;
if (old_state == MR_RINGBUFFER_FULL)
{
ringbuffer->read_mirror = ~ringbuffer->read_mirror;
ringbuffer->read_index = ringbuffer->write_index;
}
} else
{
ringbuffer->write_index++;
if (old_state == MR_RINGBUFFER_FULL)
ringbuffer->read_index = ringbuffer->write_index;
}
return 1;
}
mr_size_t mr_ringbuffer_read_byte(mr_ringbuffer_t ringbuffer, mr_uint8_t *data)
{
/* ringbuffer is empty */
if (!mr_ringbuffer_get_data_length(ringbuffer))
return 0;
/* put byte */
*data = ringbuffer->buffer[ringbuffer->read_index];
if (ringbuffer->read_index == ringbuffer->buffer_size - 1)
{
ringbuffer->read_mirror = ~ringbuffer->read_mirror;
ringbuffer->read_index = 0;
} else
{
ringbuffer->read_index++;
}
return 1;
}