1.新增内存管理文档。

2.暂时移除module目录。
This commit is contained in:
MacRsh
2023-12-09 00:47:25 +08:00
parent e4afd85f0e
commit 1ce5395b64
7 changed files with 217 additions and 1150 deletions

217
document/mem_manager.md Normal file
View File

@@ -0,0 +1,217 @@
# 动态内存管理
## 主要功能:
- 内存块的动态分配 - 根据应用的请求,从未分配内存块中选择一个块进行分配。
- 内存块的释放回收 - 当块不再需要时,将其释放并标记为未分配状态。
- 已分配与未分配块记录 - 使用链表或数组等数据结构实时跟踪各状态块的信息。
- 内存块合并 - 在释放块后,检查相邻块状态,若均未分配则合并为一个大块减少碎片。
## 内存合并的思路
### 前合并的情况:
```
(START) -> (内存块A, size=5) -> (内存块B, size=3)
插入内存块C(size=2),发现C紧邻A且A在前,则:
(START) -> (内存块A+C, size=5+2=7) -> (内存块B, size=3)
```
### 后合并的情况:
```
(START) -> (内存块A, size=5) -> (内存块B, size=3) -> (内存块C, size=2)
插入内存块D(size=3),发现D紧邻B且B在后则:
(START) -> (内存块A, size=5) -> (内存块D+B, size=3+3=6) -> (内存块C, size=2)
```
### 不合并的情况:
```
(START) -> (内存块A, size=5) -> (内存块B, size=3) -> (内存块C, size=2)
插入内存块D(size=1),D在A和B之间且都不相连,则:
(START) -> (内存块A, size=5) -> (内存块D, size=1) -> (内存块B, size=3) -> (内存块C, size=2)
```
## 创建内存数组
创建静态数组,用来作为内存管理分配的内存。
```c
/* 定义4K空间 */
#define MR_CFG_HEAP_SIZE (4 * 1024)
static uint8_t heap_mem[MR_CFG_HEAP_SIZE] = {0};
```
## 创建内存管理结构体
定义内存块,由下一块内存块指针、内存块大小、内存分配标志位组成。
- 下一块内存块指针:用于实现链式内存块存储,表示下一个内存块的地址。
- 内存块大小:记录该内存块的大小。
- 内存分配标志位使用1比特来表示内存块当前的状态,0表示未分配,1表示已分配。
```c
#define MR_HEAP_BLOCK_FREE (0)
#define MR_HEAP_BLOCK_ALLOCATED (1)
#define MR_HEAP_BLOCK_MIN_SIZE (sizeof(struct mr_heap_block) << 1)
static struct mr_heap_block
{
struct mr_heap_block *next;
uint32_t size: 31;
uint32_t allocated: 1;
} heap_start = {MR_NULL, 0, MR_HEAP_BLOCK_FREE};
```
## 初始化内存管理
为内存初始化内存块,将整块内存作为单个内存块。
```c
int mr_heap_init(void)
{
struct mr_heap_block *first_block = (struct mr_heap_block *)&heap_mem;
/* 初始化内存块(消耗一个 sizeof(struct mr_heap_block) */
first_block->next = MR_NULL;
first_block->size = sizeof(heap_mem) - sizeof(struct mr_heap_block);
first_block->allocated = MR_HEAP_BLOCK_FREE;
/* 初始化起始内存块,启动内存管理 */
heap_start.next = first_block;
return MR_EOK;
}
```
## 分配内存
```c
void *mr_malloc(size_t size)
{
struct mr_heap_block *block_prev = &heap_start;
struct mr_heap_block *block = block_prev->next;
void *memory = MR_NULL;
size_t residual = 0;
/* 检查需要申请的内存过小、内存过大,以及内存管理器中还有无内存 */
if ((size == 0) || (size > (UINT32_MAX >> 1) || (block == MR_NULL)))
{
return MR_NULL;
}
/* 字节向上做4对齐 */
size = mr_align4_up(size);
/* 找到符合内存分配大小的内存块 */
while (block->size < size)
{
if (block->next == MR_NULL)
{
return MR_NULL;
}
/* 脱离合理的内存块 */
block_prev = block;
block = block->next;
}
/* 断开内存块链接 */
block_prev->next = block->next;
/* 生成新的内存块并返回内存 */
memory = (void *)((uint8_t *)block) + sizeof(struct mr_heap_block);
/* 剩余内存大小*/
residual = block->size - size;
/* 设置被分配的内存块 */
block->size = size;
block->next = MR_NULL;
block->allocated = MR_HEAP_BLOCK_ALLOCATED;
/* 检测是否够空间生成新的内存块 MR_HEAP_BLOCK_MIN_SIZE左移两位等于2倍需要有大于2个内存块大小才生成新的内存块 */
if (residual > MR_HEAP_BLOCK_MIN_SIZE)
{
struct mr_heap_block *new_block = (struct mr_heap_block *)(((uint8_t *)memory) + size);
/* 设置新内存块 */
new_block->size = residual - sizeof(struct mr_heap_block);
new_block->next = MR_NULL;
new_block->allocated = MR_HEAP_BLOCK_FREE;
/* 将内存块插入到内存块链表中 */
heap_insert_block(new_block);
}
return memory;
}
```
## 释放内存
```c
void mr_free(void *memory)
{
/* 判断内存是否为有效 */
if (memory != MR_NULL)
{
struct mr_heap_block *block = (struct mr_heap_block *)((uint8_t *)memory - sizeof(struct mr_heap_block));
/* 检查内存块是否可以释放 */
if (block->allocated == MR_HEAP_BLOCK_ALLOCATED && block->size != 0)
{
block->allocated = MR_HEAP_BLOCK_FREE;
/* 将内存块插入到内存块链表中 */
heap_insert_block(block);
}
}
}
```
## 插入内存块
```c
void heap_insert_block(struct mr_heap_block *block)
{
struct mr_heap_block *block_prev = &heap_start;
/* 搜索前一内存块 */
while (((block_prev->next != MR_NULL) && ((uint32_t)block_prev->next < (uint32_t)block)))
{
block_prev = block_prev->next;
}
if (block_prev->next != MR_NULL)
{
/* 如果前一内存块与需要插入的内存块相连则向前合并 */
if ((void *)(((uint8_t *)block_prev) + sizeof(struct mr_heap_block) + block_prev->size) == (void *)block)
{
block_prev->size += block->size + sizeof(struct mr_heap_block);
block = block_prev;
}
/* 如果需要插入的内存块与后一内存块于相连则向后合并 */
if ((void *)(((uint8_t *)block) + sizeof(struct mr_heap_block) + block->size) == (void *)block_prev->next)
{
block->size += block_prev->next->size + sizeof(struct mr_heap_block);
block->next = block_prev->next->next;
/* 判断当前内存块是否插入*/
if (block != block_prev)
{
block_prev->next = block;
block = block_prev;
}
}
}
/* 若内存块未插入,则插入内存块 */
if (block != block_prev)
{
block->next = block_prev->next;
block_prev->next = block;
}
}
```

View File

@@ -1,392 +0,0 @@
/*
* @copyright (c) 2023, MR Development Team
*
* @license SPDX-License-Identifier: Apache-2.0
*
* @date 2023-11-17 MacRsh First version
*/
#include "etask.h"
#ifdef MR_USING_ETASK
static struct mr_etask _etask = {0};
struct mr_event
{
struct mr_avl list;
struct mr_list tlist;
union
{
struct
{
uint32_t timer: 1;
uint32_t hard: 1;
uint32_t oneshot: 1;
};
uint32_t _sflags: 3;
} sflags;
uint32_t interval: 29;
uint32_t timeout;
int (*cb)(struct mr_etask *et, void *args);
void *args;
};
static void etask_timing(struct mr_etask *etask, struct mr_event *event, uint32_t time)
{
struct mr_list *list = MR_NULL;
if (event->sflags.timer == MR_DISABLE)
{
return;
}
if (time == 0)
{
/* Disable interrupt */
mr_interrupt_disable();
/* Insert the event into the etask list */
mr_avl_remove(&etask->list, &event->list);
if (mr_list_is_empty(&etask->tlist) == MR_TRUE)
{
mr_list_remove(&event->tlist);
}
/* Enable interrupt */
mr_interrupt_enable();
/* Free the event */
mr_free(event);
return;
}
event->interval = (event->sflags.oneshot == MR_ENABLE) ? 0 : time;
event->timeout = etask->tick + time;
/* Disable interrupt */
mr_interrupt_disable();
/* Insert the event into the etask timer-list */
for (list = etask->tlist.next; list != &etask->tlist; list = list->next)
{
struct mr_event *be_insert = (struct mr_event *)mr_container_of(list, struct mr_event, tlist);
if (event->timeout < be_insert->timeout)
{
mr_list_insert_before(&be_insert->tlist, &event->tlist);
break;
}
}
if (mr_list_is_empty(&event->tlist) == MR_TRUE)
{
mr_list_insert_before(&etask->tlist, &event->tlist);
}
/* Enable interrupt */
mr_interrupt_enable();
}
static void mr_etask_free_event(struct mr_avl *tree)
{
if (tree->left_child != MR_NULL)
{
mr_etask_free_event(tree->left_child);
tree->left_child = MR_NULL;
}
if (tree->right_child != MR_NULL)
{
mr_etask_free_event(tree->right_child);
tree->right_child = MR_NULL;
}
struct mr_event *event = (struct mr_event *)mr_container_of(tree, struct mr_event, list);
mr_free(event);
}
void etask_init(struct mr_etask *etask, void *pool, size_t size)
{
mr_assert(etask->magic != MR_MAGIC_NUMBER);
mr_assert((pool != MR_NULL) || (size == 0));
/* Initialize the fields */
etask->magic = MR_MAGIC_NUMBER;
etask->tick = 0;
mr_ringbuf_init(&etask->queue, pool, size);
etask->list = MR_NULL;
mr_list_init(&etask->tlist);
etask->state = MR_NULL;
}
void etask_uninit(struct mr_etask *etask)
{
mr_assert(etask->magic == MR_MAGIC_NUMBER);
/* Free the queue */
mr_free(etask->queue.buffer);
mr_ringbuf_init(&etask->queue, MR_NULL, 0);
mr_etask_free_event(etask->list);
etask->list = MR_NULL;
mr_list_init(&etask->tlist);
etask->state = MR_NULL;
}
void etask_tick_update(struct mr_etask *etask)
{
struct mr_list *list = MR_NULL;
etask->tick++;
for (list = etask->tlist.next; list != &etask->tlist; list = list->next)
{
struct mr_event *event = (struct mr_event *)mr_container_of(list, struct mr_event, tlist);
/* Check whether the current tick is larger than the timeout */
if ((etask->tick - event->timeout) >= UINT16_MAX)
{
break;
}
/* Remove a timeout event */
list = list->prev;
mr_list_remove(&event->tlist);
/* Call the callback */
if (event->sflags.hard == MR_ENABLE)
{
event->cb(etask, event->args);
} else
{
etask_wakeup(etask, event->list.value, MR_ETASK_WFLAG_DELAY);
}
/* Update the timing */
etask_timing(etask, event, event->interval);
}
}
void etask_handle(struct mr_etask *etask)
{
size_t count = 0;
uint32_t id = 0;
mr_assert(etask != MR_NULL);
/* Get the number of current events */
count = mr_ringbuf_get_data_size(&etask->queue);
/* Read the event id from the queue */
while (count != 0)
{
/* Read the event id */
count -= mr_ringbuf_read(&etask->queue, &id, sizeof(id));
/* Find the event */
struct mr_event *event = (struct mr_event *)mr_avl_find(etask->list, id);
if (event == MR_NULL)
{
continue;
}
/* Call the event callback */
event->cb(etask, event->args);
}
if (etask->state != MR_NULL)
{
struct mr_event *event = (struct mr_event *)etask->state;
/* Call the state callback */
event->cb(etask, event->args);
}
}
int etask_start(struct mr_etask *etask,
uint32_t id,
uint8_t sflags,
size_t time,
int (*cb)(struct mr_etask *et, void *args),
void *args)
{
struct mr_event *event = MR_NULL;
mr_assert(etask != MR_NULL);
mr_assert(((sflags & MR_ETASK_SFLAG_TIMER) != MR_ETASK_SFLAG_TIMER) || time != 0);
mr_assert(cb != MR_NULL);
/* Check if the event already exists */
if (mr_avl_find(etask->list, id) != MR_NULL)
{
return MR_EBUSY;
}
/* Allocate the event */
event = (struct mr_event *)mr_malloc(sizeof(struct mr_event));
if (event == MR_NULL)
{
return MR_ENOMEM;
}
/* Initialize the fields */
mr_avl_init(&event->list, id);
mr_list_init(&event->tlist);
event->sflags._sflags = sflags;
event->cb = cb;
event->args = args;
/* Disable interrupt */
mr_interrupt_disable();
/* Insert the event into the etask list */
mr_avl_insert(&(etask->list), &(event->list));
/* Enable interrupt */
mr_interrupt_enable();
/* Start the timer */
etask_timing(etask, event, time);
return MR_EOK;
}
int etask_stop(struct mr_etask *etask, uint32_t id)
{
struct mr_event *event = MR_NULL;
mr_assert(etask != MR_NULL);
/* Check if the event already exists */
event = (struct mr_event *)mr_avl_find(etask->list, id);
if (event == MR_NULL)
{
return MR_ENOTFOUND;
}
/* Disable interrupt */
mr_interrupt_disable();
/* Insert the event into the etask list */
mr_avl_remove(&etask->list, &event->list);
if (mr_list_is_empty(&etask->tlist) == MR_FALSE)
{
mr_list_remove(&event->tlist);
}
/* Enable interrupt */
mr_interrupt_enable();
/* Free the event */
mr_free(event);
return MR_EOK;
}
int etask_wakeup(struct mr_etask *etask, uint32_t id, uint8_t wflag)
{
mr_assert(etask != MR_NULL);
mr_assert(wflag == MR_ETASK_WFLAG_DELAY || wflag == MR_ETASK_WFLAG_NOW || wflag == MR_ETASK_WFLAG_STATE);
if (wflag == MR_ETASK_WFLAG_DELAY)
{
if (mr_ringbuf_write(&etask->queue, &id, sizeof(id)) != sizeof(id))
{
return MR_EBUSY;
}
} else
{
struct mr_event *event = (struct mr_event *)mr_avl_find(etask->list, id);
if (event == MR_NULL)
{
return MR_ENOTFOUND;
}
if (wflag == MR_ETASK_WFLAG_NOW)
{
/* Call the event callback */
event->cb(etask, event->args);
} else
{
/* Set the state machine */
etask->state = (void *)event;
}
}
return MR_EOK;
}
/**
* @brief This function initializes the etask module.
*
* @param pool The queue pool of the etask.
* @param size The size of the queue pool.
*/
void mr_etask_init(void *pool, size_t size)
{
etask_init(&_etask, pool, size);
}
/**
* @brief This function uninitializes the etask module.
*/
void mr_etask_uninit(void)
{
etask_uninit(&_etask);
}
/**
* @brief This function updates the etask module tick.
*/
void mr_etask_tick_update(void)
{
etask_tick_update(&_etask);
}
/**
* @brief This function handles events of the etask queue.
*/
void mr_etask_handle(void)
{
etask_handle(&_etask);
}
/**
* @brief This function starts an event.
*
* @param id The id of the event.
* @param sflags The start flags of the event.
* @param time The time of the event.
* @param cb The callback function of the event.
* @param args The arguments of the callback function.
*
* @return MR_ERR_OK on success, otherwise an error code.
*/
int mr_etask_start(uint32_t id, uint8_t sflags, size_t time, int (*cb)(struct mr_etask *et, void *args), void *args)
{
return etask_start(&_etask, id, sflags, time, cb, args);
}
/**
* @brief This function stops an event.
*
* @param id The id of the event.
*
* @return MR_ERR_OK on success, otherwise an error code.
*/
int mr_etask_stop(uint32_t id)
{
return etask_stop(&_etask, id);
}
/**
* @brief This function wakes up an event.
*
* @param id The id of the event.
* @param wflag The wakeup flag of the event.
*
* @return MR_ERR_OK on success, otherwise an error code.
*/
int mr_etask_wakeup(uint32_t id, uint8_t wflag)
{
return etask_wakeup(&_etask, id, wflag);
}
#endif /* MR_USING_ETASK */

View File

@@ -1,81 +0,0 @@
/*
* @copyright (c) 2023, MR Development Team
*
* @license SPDX-License-Identifier: Apache-2.0
*
* @date 2023-11-17 MacRsh First version
*/
#ifndef _ETASK_H_
#define _ETASK_H_
#include "include/mr_api.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifdef MR_USING_ETASK
/**
* @brief Etask start flag
*/
#define MR_ETASK_SFLAG_EVENT (0x00) /* Event */
#define MR_ETASK_SFLAG_TIMER (0x01) /* Timer */
#define MR_ETASK_SFLAG_HARD (0x02) /* Hard */
#define MR_ETASK_SFLAG_SOFT (0x00) /* Soft */
#define MR_ETASK_SFLAG_ONESHOT (0x04) /* One shot */
#define MR_ETASK_SFLAG_PERIODIC (0x00) /* Periodic */
/**
* @brief Etask wakeup flag
*/
#define MR_ETASK_WFLAG_NOW (0x00) /* Wakeup immediately */
#define MR_ETASK_WFLAG_DELAY (0x01) /* Wakeup after delay */
#define MR_ETASK_WFLAG_STATE (0x02) /* Wakeup by state */
/**
* @brief Etask
*/
struct mr_etask
{
uint32_t magic; /* Magic */
uint32_t tick; /* Tick */
struct mr_ringbuf queue; /* Queue */
struct mr_avl *list; /* Event list */
struct mr_list tlist; /* Timing list */
void *state; /* State */
};
/**
* @addtogroup Etask
* @{
*/
void mr_etask_init(void *pool, size_t size);
void mr_etask_uninit(void);
void mr_etask_tick_update(void);
void mr_etask_handle(void);
int mr_etask_start(uint32_t id, uint8_t sflags, size_t time, int (*cb)(struct mr_etask *et, void *args), void *args);
int mr_etask_stop(uint32_t id);
int mr_etask_wakeup(uint32_t id, uint8_t wflag);
void etask_init(struct mr_etask *etask, void *pool, size_t size);
void etask_uninit(struct mr_etask *etask);
void etask_tick_update(struct mr_etask *etask);
void etask_handle(struct mr_etask *etask);
int etask_start(struct mr_etask *etask,
uint32_t id,
uint8_t sflags,
size_t time,
int (*cb)(struct mr_etask *et, void *args),
void *args);
int etask_stop(struct mr_etask *etask, uint32_t id);
int etask_wakeup(struct mr_etask *etask, uint32_t id, uint8_t wflag);
/** @} */
#endif /* MR_USING_ETASK */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _ETASK_H_ */

View File

@@ -1,215 +0,0 @@
/*
* @copyright (c) 2023, MR Development Team
*
* @license SPDX-License-Identifier: Apache-2.0
*
* @date 2023-11-17 MacRsh First version
*/
#include "hx711.h"
#ifdef MR_USING_HX711
#if !defined(MR_USING_PIN)
#error "Please define MR_USING_PIN. Otherwise HX711 will not work."
#else
#include "include/device/pin.h"
static void hx711_set_sck(struct mr_hx711 *hx711, uint8_t value)
{
mr_dev_ioctl(hx711->desc, MR_CTL_SET_OFFSET, &hx711->sck_pin);
mr_dev_write(hx711->desc, &value, sizeof(value));
}
static uint8_t hx711_get_dout(struct mr_hx711 *hx711)
{
uint8_t value = 0;
mr_dev_ioctl(hx711->desc, MR_CTL_SET_OFFSET, &hx711->dout_pin);
mr_dev_read(hx711->desc, &value, sizeof(value));
return value;
}
static uint32_t hx711_get_value(struct mr_hx711 *hx711)
{
uint32_t value = 0;
int i = 0;
/* Start the conversion */
hx711_set_sck(hx711, 0);
mr_delay_us(1);
while (hx711_get_dout(hx711) != 0)
{
i++;
if (i > UINT16_MAX)
{
return 0;
}
}
/* Get the value */
for (i = 0; i < 24; i++)
{
hx711_set_sck(hx711, 1);
value <<= 1;
mr_delay_us(1);
hx711_set_sck(hx711, 0);
if (hx711_get_dout(hx711) == 1)
{
value++;
}
mr_delay_us(1);
}
hx711_set_sck(hx711, 1);
value = value ^ 0x800000;
mr_delay_us(1);
hx711_set_sck(hx711, 0);
/* Filter the value */
mr_bits_clr(value, (1 << hx711->filter_bits) - 1);
return value;
}
static int mr_hx711_open(struct mr_dev *dev)
{
struct mr_hx711 *hx711 = (struct mr_hx711 *)dev;
hx711->desc = mr_dev_open("pin", MR_OFLAG_RDWR);
if (hx711->desc < 0)
{
return hx711->desc;
}
/* Set the sck pin mode */
mr_dev_ioctl(hx711->desc, MR_CTL_PIN_SET_NUMBER, &hx711->sck_pin);
mr_dev_ioctl(hx711->desc, MR_CTL_PIN_SET_MODE, mr_make_local(int, MR_PIN_MODE_OUTPUT));
/* Set the dout pin mode */
mr_dev_ioctl(hx711->desc, MR_CTL_PIN_SET_NUMBER, &hx711->dout_pin);
mr_dev_ioctl(hx711->desc, MR_CTL_PIN_SET_MODE, mr_make_local(int, MR_PIN_MODE_INPUT_UP));
return MR_EOK;
}
static int mr_hx711_close(struct mr_dev *dev)
{
struct mr_hx711 *hx711 = (struct mr_hx711 *)dev;
/* Reset the sck pin mode */
mr_dev_ioctl(hx711->desc, MR_CTL_PIN_SET_NUMBER, &hx711->sck_pin);
mr_dev_ioctl(hx711->desc, MR_CTL_PIN_SET_MODE, mr_make_local(int, MR_PIN_MODE_NONE));
/* Reset the dout pin mode */
mr_dev_ioctl(hx711->desc, MR_CTL_PIN_SET_NUMBER, &hx711->dout_pin);
mr_dev_ioctl(hx711->desc, MR_CTL_PIN_SET_MODE, mr_make_local(int, MR_PIN_MODE_NONE));
mr_dev_close(hx711->desc);
hx711->desc = -1;
return MR_EOK;
}
static ssize_t mr_hx711_read(struct mr_dev *dev, int off, void *buf, size_t size, int async)
{
struct mr_hx711 *hx711 = (struct mr_hx711 *)dev;
uint32_t *rd_buf = (uint32_t *)buf;
ssize_t rd_size = 0;
mr_bits_clr(size, sizeof(*rd_buf) - 1);
for (rd_size = 0; rd_size < size; rd_size += sizeof(*rd_buf))
{
uint32_t value = hx711_get_value(hx711);
*rd_buf = (value > hx711->self_cal) ? (value - hx711->self_cal) : 0;
rd_buf++;
}
return rd_size;
}
static int mr_hx711_ioctl(struct mr_dev *dev, int off, int cmd, void *args)
{
struct mr_hx711 *hx711 = (struct mr_hx711 *)dev;
switch (cmd)
{
case MR_CTL_HX711_SET_FILTER_BITS:
{
if (args != MR_NULL)
{
int filter = *(int *)args;
hx711->filter_bits = filter;
return MR_EOK;
}
return MR_EINVAL;
}
case MR_CTL_HX711_SET_SELF_CAL:
{
hx711->self_cal = hx711_get_value(hx711);
return MR_EOK;
}
case MR_CTL_HX711_GET_FILTER_BITS:
{
if (args != MR_NULL)
{
*(int *)args = hx711->filter_bits;
return MR_EOK;
}
return MR_EINVAL;
}
case MR_CTL_HX711_GET_SELF_CAL:
{
if (args != MR_NULL)
{
*(uint32_t *)args = hx711->self_cal;
return MR_EOK;
}
return MR_EINVAL;
}
default:
{
return MR_ENOTSUP;
}
}
}
/**
* @brief This function register a hx711 module.
*
* @param hx711 The hx711 module.
* @param name The name of the hx711 module.
* @param sck_pin The sck pin of the hx711 module.
* @param dout_pin The dout pin of the hx711 module.
*
* @return MR_EOK on success, otherwise an error code.
*/
int mr_hx711_register(struct mr_hx711 *hx711, const char *name, int sck_pin, int dout_pin)
{
static struct mr_dev_ops ops =
{
mr_hx711_open,
mr_hx711_close,
mr_hx711_read,
MR_NULL,
mr_hx711_ioctl,
MR_NULL
};
mr_assert(hx711 != MR_NULL);
mr_assert(name != MR_NULL);
mr_assert(sck_pin >= 0);
mr_assert(dout_pin >= 0);
/* Initialize the fields */
hx711->filter_bits = 0;
hx711->self_cal = 0;
hx711->sck_pin = sck_pin;
hx711->dout_pin = dout_pin;
hx711->desc = -1;
/* Register the hx711 */
return mr_dev_register(&hx711->dev, name, Mr_Dev_Type_ADC, MR_SFLAG_RDONLY | MR_SFLAG_NONDRV, &ops, MR_NULL);
}
#endif /* MR_USING_PIN */
#endif /* MR_USING_HX711 */

View File

@@ -1,59 +0,0 @@
/*
* @copyright (c) 2023, MR Development Team
*
* @license SPDX-License-Identifier: Apache-2.0
*
* @date 2023-11-17 MacRsh First version
*/
#ifndef _HX711_H_
#define _HX711_H_
#include "include/mr_api.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifdef MR_USING_HX711
/**
* @brief HX711 command.
*/
#define MR_CTL_HX711_SET_FILTER_BITS ((0x01|0x80) << 16) /**< Set filter bits */
#define MR_CTL_HX711_SET_SELF_CAL ((0x02|0x80) << 16) /**< Set self calibration */
#define MR_CTL_HX711_GET_FILTER_BITS ((0x01|0x00) << 16) /**< Get filter bits */
#define MR_CTL_HX711_GET_SELF_CAL ((0x02|0x00) << 16) /**< Get self calibration */
/**
* @brief HX711 data type.
*/
typedef uint32_t mr_hx711_data_t; /**< HX711 read data type */
/**
* @brief Hx711 structure.
*/
struct mr_hx711
{
struct mr_dev dev; /**< Device */
int filter_bits; /**< Filter bits */
uint32_t self_cal; /**< Self calibration */
int sck_pin; /**< SCK pin */
int dout_pin; /**< DOUT pin */
int desc; /**< Descriptor */
};
/**
* @addtogroup HX711.
* @{
*/
int mr_hx711_register(struct mr_hx711 *hx711, const char *name, int sck_pin, int dout_pin);
/** @} */
#endif /* MR_USING_HX711 */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _HX711_H_ */

View File

@@ -1,300 +0,0 @@
/*
* @copyright (c) 2023, MR Development Team
*
* @license SPDX-License-Identifier: Apache-2.0
*
* @date 2023-11-17 MacRsh First version
*/
#include "icm20602.h"
#ifdef MR_USING_ICM20602
#define ICM20602_SMPLRT_DIV (0x19)
#define ICM20602_CONFIG (0x1A)
#define ICM20602_GYRO_CONFIG (0x1B)
#define ICM20602_ACCEL_CONFIG (0x1C)
#define ICM20602_ACCEL_CONFIG_2 (0x1D)
#define ICM20602_ACCEL_XOUT_H (0x3B)
#define ICM20602_GYRO_XOUT_H (0x43)
#define ICM20602_PWR_MGMT_1 (0x6B)
#define ICM20602_PWR_MGMT_2 (0x6C)
#define ICM20602_WHO_AM_I (0x75)
static void icm20602_write_reg(struct mr_icm20602 *icm20602, uint8_t reg, uint8_t data)
{
mr_dev_ioctl(icm20602->desc, MR_CTL_SET_OFFSET, mr_make_local(int, reg));
mr_dev_write(icm20602->desc, &data, sizeof(data));
}
static uint8_t icm20602_read_reg(struct mr_icm20602 *icm20602, uint8_t reg)
{
uint8_t data = 0;
mr_dev_ioctl(icm20602->desc, MR_CTL_SET_OFFSET, mr_make_local(int, reg | 0x80));
mr_dev_read(icm20602->desc, &data, sizeof(data));
return data;
}
static ssize_t icm20602_read_regs(struct mr_icm20602 *icm20602, uint8_t reg, uint8_t *buf, size_t size)
{
mr_dev_ioctl(icm20602->desc, MR_CTL_SET_OFFSET, mr_make_local(int, reg | 0x80));
return mr_dev_read(icm20602->desc, buf, size);
}
static int icm20602_self_check(struct mr_icm20602 *icm20602)
{
size_t count = 0;
for (count = 0; count < 200; count++)
{
if (icm20602_read_reg(icm20602, ICM20602_WHO_AM_I) == 0x12)
{
return MR_TRUE;
}
}
return MR_FALSE;
}
static int icm20602_config(struct mr_icm20602 *icm20602, struct mr_icm20602_config *config)
{
switch (config->acc_range)
{
case MR_ICM20602_ACC_RANGE_2G:
{
icm20602_write_reg(icm20602, ICM20602_ACCEL_CONFIG, 0x00);
break;
}
case MR_ICM20602_ACC_RANGE_4G:
{
icm20602_write_reg(icm20602, ICM20602_ACCEL_CONFIG, 0x08);
break;
}
case MR_ICM20602_ACC_RANGE_8G:
{
icm20602_write_reg(icm20602, ICM20602_ACCEL_CONFIG, 0x10);
break;
}
case MR_ICM20602_ACC_RANGE_16G:
{
icm20602_write_reg(icm20602, ICM20602_ACCEL_CONFIG, 0x18);
break;
}
default:
{
return MR_ENOTSUP;
}
}
switch (config->gyro_range)
{
case MR_ICM20602_GYRO_RANGE_250DPS:
{
icm20602_write_reg(icm20602, ICM20602_GYRO_CONFIG, 0x00);
break;
}
case MR_ICM20602_GYRO_RANGE_500DPS:
{
icm20602_write_reg(icm20602, ICM20602_GYRO_CONFIG, 0x08);
break;
}
case MR_ICM20602_GYRO_RANGE_1000DPS:
{
icm20602_write_reg(icm20602, ICM20602_GYRO_CONFIG, 0x10);
break;
}
case MR_ICM20602_GYRO_RANGE_2000DPS:
{
icm20602_write_reg(icm20602, ICM20602_GYRO_CONFIG, 0x18);
break;
}
default:
{
return MR_ENOTSUP;
}
}
icm20602->config = *config;
return MR_EOK;
}
static int mr_icm20602_open(struct mr_dev *dev)
{
struct mr_icm20602 *icm20602 = (struct mr_icm20602 *)dev;
char full_name[MR_CFG_NAME_MAX * 2 + 1] = {0};
struct mr_spi_config config = MR_SPI_CONFIG_DEFAULT;
size_t i = 0;
/* Open the icm20602 spi-device */
int ret = mr_dev_get_full_name(dev, full_name, sizeof(full_name));
if (ret != MR_EOK)
{
return ret;
}
icm20602->desc = mr_dev_open(full_name, MR_OFLAG_RDWR);
if (icm20602->desc < 0)
{
return icm20602->desc;
}
config.baud_rate = 10 * 1000 * 1000;
mr_dev_ioctl(icm20602->desc, MR_CTL_SET_CONFIG, &config);
/* Self check */
if (icm20602_self_check(icm20602) == MR_FALSE)
{
mr_log("%s self check failed", dev->name);
return MR_ENOTFOUND;
}
/* Restart */
icm20602_write_reg(icm20602, ICM20602_PWR_MGMT_1, 0x80);
mr_delay_ms(10);
for (i = 0; i < 200; i++)
{
if (icm20602_read_reg(icm20602, ICM20602_PWR_MGMT_1) == 0x41)
{
break;
}
}
if (i == 200)
{
mr_log("%s restart failed\r\n", dev->name);
return MR_ENOTFOUND;
}
/* Init config */
icm20602_write_reg(icm20602, ICM20602_PWR_MGMT_1, 0x01);
icm20602_write_reg(icm20602, ICM20602_PWR_MGMT_2, 0x00);
icm20602_write_reg(icm20602, ICM20602_CONFIG, 0x01);
icm20602_write_reg(icm20602, ICM20602_SMPLRT_DIV, 0x07);
ret = icm20602_config(icm20602, &icm20602->config);
if (ret != MR_EOK)
{
mr_log("%s init config failed\r\n", dev->name);
return ret;
}
icm20602_write_reg(icm20602, ICM20602_ACCEL_CONFIG_2, 0x03);
return MR_EOK;
}
static int mr_icm20602_close(struct mr_dev *dev)
{
struct mr_icm20602 *icm20602 = (struct mr_icm20602 *)dev;
/* Close the icm20602 spi-device */
mr_dev_close(icm20602->desc);
icm20602->desc = -1;
return MR_EOK;
}
static ssize_t mr_icm20602_read(struct mr_dev *dev, int off, void *buf, size_t size, int async)
{
struct mr_icm20602 *icm20602 = (struct mr_icm20602 *)dev;
struct mr_icm20602_data *rd_buf = (struct mr_icm20602_data *)buf;
uint8_t reg = (off == MR_ICM20602_ACC_OFFSET) ? ICM20602_ACCEL_XOUT_H : ICM20602_GYRO_XOUT_H;
ssize_t rd_size = 0;
if ((off != MR_ICM20602_ACC_OFFSET) && (off != MR_ICM20602_GYRO_OFFSET))
{
return MR_EINVAL;
}
mr_bits_clr(size, sizeof(*rd_buf) - 1);
for (rd_size = 0; rd_size < size; rd_size += sizeof(*rd_buf))
{
uint8_t axis_buf[6] = {0};
icm20602_read_regs(icm20602, reg, axis_buf, sizeof(axis_buf));
rd_buf->x = (int16_t)((axis_buf[0] << 8) | axis_buf[1]);
rd_buf->y = (int16_t)((axis_buf[2] << 8) | axis_buf[3]);
rd_buf->z = (int16_t)((axis_buf[4] << 8) | axis_buf[5]);
}
return rd_size;
}
static int mr_icm20602_ioctl(struct mr_dev *dev, int off, int cmd, void *args)
{
struct mr_icm20602 *icm20602 = (struct mr_icm20602 *)dev;
switch (cmd)
{
case MR_CTL_SET_CONFIG:
{
if (args != MR_NULL)
{
struct mr_icm20602_config *config = (struct mr_icm20602_config *)args;
return icm20602_config(icm20602, config);
}
return MR_EINVAL;
}
case MR_CTL_GET_CONFIG:
{
if (args != MR_NULL)
{
struct mr_icm20602_config *config = (struct mr_icm20602_config *)args;
*config = icm20602->config;
return MR_EOK;
}
return MR_EINVAL;
}
default:
{
return MR_ENOTSUP;
}
}
}
/**
* @brief This function register a icm20602 module.
*
* @param icm20602 The icm20602 module.
* @param name The name of the icm20602 module.
* @param cs_pin The cs pin of the icm20602 module.
* @param bus_name The spi-bus name of the icm20602 module.
*
* @return MR_EOK on success, otherwise an error code.
*/
int mr_icm20602_register(struct mr_icm20602 *icm20602, const char *name, int cs_pin, const char *bus_name)
{
static struct mr_dev_ops ops =
{
mr_icm20602_open,
mr_icm20602_close,
mr_icm20602_read,
MR_NULL,
mr_icm20602_ioctl,
MR_NULL
};
struct mr_icm20602_config default_config = MR_ICM20602_CONFIG_DEFAULT;
char cat_name[MR_CFG_NAME_MAX + MR_CFG_NAME_MAX + 1] = {0};
int ret = 0;
mr_assert(icm20602 != MR_NULL);
mr_assert(name != MR_NULL);
mr_assert(cs_pin >= 0);
mr_assert(bus_name != MR_NULL);
/* Register the spi-device */
sprintf(cat_name, "%s/%s", bus_name, name);
ret = mr_spi_dev_register(&icm20602->spi_dev, cat_name, cs_pin, MR_SPI_CS_ACTIVE_LOW);
if (ret != MR_EOK)
{
return ret;
}
/* Initialize the fields */
icm20602->config = default_config;
icm20602->desc = -1;
/* Register the icm20602 */
return mr_dev_register(&icm20602->dev, name, Mr_Dev_Type_Sensor, MR_SFLAG_RDONLY | MR_SFLAG_NONDRV, &ops, MR_NULL);
}
#endif /* MR_USING_ICM20602 */

View File

@@ -1,103 +0,0 @@
/*
* @copyright (c) 2023, MR Development Team
*
* @license SPDX-License-Identifier: Apache-2.0
*
* @date 2023-11-17 MacRsh First version
*/
#ifndef _ICM20602_H_
#define _ICM20602_H_
#include "include/mr_api.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifdef MR_USING_ICM20602
#if !defined(MR_USING_SPI)
#undef MR_USING_ICM20602
#error "Please define MR_USING_SPI. Otherwise ICM20602 will not work."
#else
#include "include/device/spi.h"
/**
* @brief ICM20602 acc Range.
*/
#define MR_ICM20602_ACC_RANGE_2G (2) /**< 2G */
#define MR_ICM20602_ACC_RANGE_4G (4) /**< 4G */
#define MR_ICM20602_ACC_RANGE_8G (8) /**< 8G */
#define MR_ICM20602_ACC_RANGE_16G (16) /**< 16G */
/**
* @brief ICM20602 gyro Range.
*/
#define MR_ICM20602_GYRO_RANGE_250DPS (250) /**< 250DPS */
#define MR_ICM20602_GYRO_RANGE_500DPS (500) /**< 500DPS */
#define MR_ICM20602_GYRO_RANGE_1000DPS (1000) /**< 1000DPS */
#define MR_ICM20602_GYRO_RANGE_2000DPS (2000) /**< 2000DPS */
/**
* @def ICM20602 default config.
*/
#define MR_ICM20602_CONFIG_DEFAULT \
{ \
MR_ICM20602_ACC_RANGE_8G, \
MR_ICM20602_GYRO_RANGE_2000DPS, \
}
/**
* @brief ICM20602 config structure.
*/
struct mr_icm20602_config
{
uint16_t acc_range; /**< Acc range */
uint16_t gyro_range; /**< Gyro range */
};
/**
* @brief ICM20602 offset.
*/
#define MR_ICM20602_ACC_OFFSET (0x00) /**< Acc offset */
#define MR_ICM20602_GYRO_OFFSET (0x01) /**< Gyro offset */
/**
* @brief ICM20602 data type.
*/
typedef struct mr_icm20602_data
{
int16_t x; /**< X axis */
int16_t y; /**< Y axis */
int16_t z; /**< Z axis */
} mr_icm20602_data_t; /**< ICM20602 read data type */
/**
* @brief ICM20602 structure.
*/
struct mr_icm20602
{
struct mr_dev dev; /**< Device */
struct mr_spi_dev spi_dev; /**< SPI device */
struct mr_icm20602_config config; /**< Config */
int desc; /**< Descriptor */
};
/**
* @addtogroup ICM20602.
* @{
*/
int mr_icm20602_register(struct mr_icm20602 *icm20602, const char *name, int cs_pin, const char *bus_name);
/** @} */
#endif /* MR_USING_SPI */
#endif /* MR_USING_ICM20602 */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _ICM20602_H_ */