建立基础版本
This commit is contained in:
@@ -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
11
bsp/board.h
Normal 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
272
device/serial.c
Normal 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
98
device/serial.h
Normal 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
252
include/mrdef.h
Normal 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
81
include/mrlib.h
Normal 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
44
include/mrserve.h
Normal 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
21
mrconfig.h
Normal 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
231
src/device.c
Normal 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
427
src/kernel.c
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user