1.新增内存管理文档。
2.暂时移除module目录。
This commit is contained in:
217
document/mem_manager.md
Normal file
217
document/mem_manager.md
Normal 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;
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -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 */
|
||||
@@ -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_ */
|
||||
@@ -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 */
|
||||
@@ -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_ */
|
||||
@@ -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 */
|
||||
@@ -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_ */
|
||||
Reference in New Issue
Block a user