mirror of
https://github.com/Fishwaldo/bl_mcu_sdk.git
synced 2025-07-10 06:48:51 +00:00
[refactor] move utils into component
This commit is contained in:
parent
d4473020d6
commit
d9adf21997
25 changed files with 1835 additions and 1789 deletions
114
components/utils/CMakeLists.txt
Normal file
114
components/utils/CMakeLists.txt
Normal file
|
@ -0,0 +1,114 @@
|
|||
sdk_generate_library()
|
||||
|
||||
if(CONFIG_LOG_DISABLE)
|
||||
sdk_add_compile_definitions(-DCONFIG_LOG_DISABLE)
|
||||
endif()
|
||||
|
||||
if(CONFIG_ASSERT_DISABLE)
|
||||
sdk_add_compile_definitions(-DCONFIG_ASSERT_DISABLE)
|
||||
endif()
|
||||
|
||||
if(DEFINED CONFIG_LOG_LEVEL)
|
||||
sdk_add_compile_definitions(-DCONFIG_LOG_LEVEL=${CONFIG_LOG_LEVEL})
|
||||
else()
|
||||
sdk_add_compile_definitions(-DCONFIG_LOG_LEVEL=3)
|
||||
endif()
|
||||
|
||||
if(CONFIG_BFLOG_POOL_SIZE)
|
||||
sdk_add_compile_definitions(-DCONFIG_BFLOG_POOL_SIZE=${CONFIG_BFLOG_POOL_SIZE})
|
||||
endif()
|
||||
|
||||
|
||||
# log
|
||||
sdk_library_add_sources(log/log.c)
|
||||
sdk_add_include_directories(log)
|
||||
|
||||
# vsnprintf config
|
||||
if(CONFIG_VSNPRINTF_FLOAT)
|
||||
sdk_add_compile_definitions(-DCONFIG_VLIBC_FLOAT=${CONFIG_VSNPRINTF_FLOAT})
|
||||
sdk_add_compile_definitions(-DCONFIG_LIBC_FLOAT=${CONFIG_VSNPRINTF_FLOAT})
|
||||
endif()
|
||||
if(CONFIG_VSNPRINTF_FLOAT_EX)
|
||||
sdk_add_compile_definitions(-DCONFIG_VLIBC_FLOAT_EX=${CONFIG_VSNPRINTF_FLOAT_EX})
|
||||
sdk_add_compile_definitions(-DCONFIG_LIBC_FLOAT_EX=${CONFIG_VSNPRINTF_FLOAT_EX})
|
||||
endif()
|
||||
if(CONFIG_VSNPRINTF_LONG_LONG)
|
||||
sdk_add_compile_definitions(-DCONFIG_VLIBC_LONG_LONG=${CONFIG_VSNPRINTF_LONG_LONG})
|
||||
sdk_add_compile_definitions(-DCONFIG_LIBC_LONG_LONG=${CONFIG_VSNPRINTF_LONG_LONG})
|
||||
endif()
|
||||
if(CONFIG_VSNPRINTF_WRITEBACK)
|
||||
sdk_add_compile_definitions(-DCONFIG_VLIBC_WRITEBACK=${CONFIG_VSNPRINTF_WRITEBACK})
|
||||
endif()
|
||||
|
||||
# libc or vlibc select
|
||||
if(CONFIG_VLIBC)
|
||||
sdk_add_compile_definitions(-DCONFIG_VLIBC)
|
||||
# vlibc debug enable
|
||||
if (CONFIG_VLIBC_DEBUG)
|
||||
sdk_add_compile_definitions(-DCONFIG_VLIBC_DEBUG)
|
||||
endif()
|
||||
|
||||
# vlibc fatfs port enable
|
||||
if(CONFIG_VLIBC_FATFS)
|
||||
sdk_add_compile_definitions(-DCONFIG_VLIBC_FATFS)
|
||||
endif()
|
||||
|
||||
sdk_library_add_sources(vlibc/printf.c)
|
||||
sdk_library_add_sources(vlibc/syscalls.c)
|
||||
sdk_library_add_sources(vlibc/vlibc_stdio.c)
|
||||
sdk_library_add_sources(vlibc/vlibc_vsnprintf.c)
|
||||
sdk_add_include_directories(vlibc)
|
||||
else()
|
||||
if(CONFIG_VSNPRINTF_NANO)
|
||||
sdk_library_add_sources(libc/vsnprintf_nano.c)
|
||||
else()
|
||||
sdk_library_add_sources(libc/vsnprintf.c)
|
||||
endif()
|
||||
|
||||
sdk_library_add_sources(libc/syscalls.c)
|
||||
sdk_library_add_sources(libc/printf.c)
|
||||
endif()
|
||||
|
||||
# memheap
|
||||
sdk_library_add_sources(mmheap/bflb_mmheap.c)
|
||||
sdk_add_include_directories(mmheap)
|
||||
|
||||
# memheap lock user config
|
||||
if (CONFIG_MMHEAP_USER)
|
||||
sdk_add_compile_definitions(-DCONFIG_MMHEAP_USER)
|
||||
endif()
|
||||
|
||||
# ring_buffer
|
||||
sdk_library_add_sources(ring_buffer/ring_buffer.c)
|
||||
sdk_add_include_directories(ring_buffer)
|
||||
|
||||
# bflb block pool debug enable
|
||||
if (CONFIG_BFLB_BLOCK_POOL_DEBUG)
|
||||
sdk_add_compile_definitions(-DCONFIG_BFLB_BLOCK_POOL_DEBUG)
|
||||
endif()
|
||||
|
||||
# bflb block pool mutex
|
||||
if (CONFIG_BFLB_BLOCK_POOL_MTX_TIMEOUT)
|
||||
sdk_add_compile_definitions(-DCONFIG_BFLB_BLOCK_POOL_MTX_TIMEOUT=${CONFIG_BFLB_BLOCK_POOL_MTX_TIMEOUT})
|
||||
endif()
|
||||
|
||||
# bflb block pool
|
||||
sdk_library_add_sources(bflb_block_pool/bflb_block_pool.c)
|
||||
sdk_add_include_directories(bflb_block_pool)
|
||||
|
||||
# soft crc
|
||||
sdk_library_add_sources(soft_crc/soft_crc.c)
|
||||
sdk_add_include_directories(soft_crc)
|
||||
|
||||
if(DEFINED CONFIG_TIMEZONE)
|
||||
sdk_add_compile_definitions(-DBFLB_TIMESTAMP_TIMEZONE=${CONFIG_TIMEZONE})
|
||||
else()
|
||||
sdk_add_compile_definitions(-DBFLB_TIMESTAMP_TIMEZONE=8)
|
||||
endif()
|
||||
|
||||
# timestamp
|
||||
sdk_library_add_sources(bflb_timestamp/bflb_timestamp.c)
|
||||
sdk_add_include_directories(bflb_timestamp)
|
||||
|
||||
sdk_add_compile_options(-fno-builtin-printf)
|
||||
sdk_add_link_options(-u_malloc_r)
|
338
components/utils/bflb_block_pool/bflb_block_pool.c
Normal file
338
components/utils/bflb_block_pool/bflb_block_pool.c
Normal file
|
@ -0,0 +1,338 @@
|
|||
/**
|
||||
* @file bflb_block_pool.c
|
||||
* @brief
|
||||
*
|
||||
* Copyright (c) 2021 Bouffalolab team
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "bflb_block_pool.h"
|
||||
|
||||
#ifdef CONFIG_BFLB_BLOCK_POOL_DEBUG
|
||||
#define _BFLB_BLOCK_POOL_CHECK(_expr, _ret) \
|
||||
if (!(_expr)) \
|
||||
return _ret
|
||||
#else
|
||||
#define _BFLB_BLOCK_POOL_CHECK(_expr, _ret) ((void)0)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BFLB_BLOCK_POOL_MTX_TIMEOUT
|
||||
#define CONFIG_BFLB_BLOCK_POOL_MTX_TIMEOUT 100
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief create a block blk_pool
|
||||
* @param blk_pool block pool instance
|
||||
* @param blk_size block size
|
||||
* @param blk_align block align
|
||||
* @param pool_addr pool address
|
||||
* @param pool_size pool size
|
||||
* @return int
|
||||
*/
|
||||
int bflb_block_pool_create(bflb_block_pool_t *blk_pool, uint32_t blk_size, uint32_t blk_align, void *pool_addr, uint32_t pool_size)
|
||||
{
|
||||
_BFLB_BLOCK_POOL_CHECK(blk_pool != NULL, -1);
|
||||
_BFLB_BLOCK_POOL_CHECK(blk_size > 0, -1);
|
||||
_BFLB_BLOCK_POOL_CHECK(((blk_align >= BFLB_BLOCK_POOL_ALIGN_1) &&
|
||||
(blk_align <= BFLB_BLOCK_POOL_ALIGN_128)),
|
||||
-1);
|
||||
_BFLB_BLOCK_POOL_CHECK(pool_addr != NULL, -1);
|
||||
_BFLB_BLOCK_POOL_CHECK(pool_size > 0, -1);
|
||||
_BFLB_BLOCK_POOL_CHECK(((uintptr_t)pool_addr & (sizeof(void *) - 1)) == 0, -1);
|
||||
|
||||
uint32_t bitmask = ((0x1 << blk_align) - 1);
|
||||
uint32_t blk_count;
|
||||
uintptr_t address;
|
||||
|
||||
if (blk_size & bitmask) {
|
||||
blk_size = (blk_size & (~bitmask)) + (0x1 << blk_align);
|
||||
}
|
||||
|
||||
blk_count = pool_size / (sizeof(void *) + blk_size);
|
||||
|
||||
if (blk_count == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*!< calculate block area start address */
|
||||
address = (uintptr_t)pool_addr + sizeof(void *) * blk_count;
|
||||
|
||||
/*!< align address */
|
||||
if (address & bitmask) {
|
||||
address = (address & (~bitmask)) + (0x1 << blk_align);
|
||||
}
|
||||
|
||||
/*!< if not enough memory after align */
|
||||
if ((address + (blk_count * blk_size)) > ((uintptr_t)pool_addr + pool_size)) {
|
||||
/*!< do block count -1 */
|
||||
blk_count -= 1;
|
||||
if (blk_count == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*!< recalculate block area start address */
|
||||
address = (uintptr_t)pool_addr + sizeof(void *) * blk_count;
|
||||
|
||||
/*!< align address */
|
||||
if (address & bitmask) {
|
||||
address = (address & (~bitmask)) + (0x1 << blk_align);
|
||||
}
|
||||
}
|
||||
|
||||
/*!< build list */
|
||||
for (uint32_t i = 0; i < blk_count; i++) {
|
||||
((void **)pool_addr)[i] = &((void **)pool_addr)[i + 1];
|
||||
}
|
||||
|
||||
/*!< last node link to NULL */
|
||||
((void **)pool_addr)[blk_count - 1] = NULL;
|
||||
|
||||
/*!< set free block node list */
|
||||
blk_pool->free_list = pool_addr;
|
||||
|
||||
/*!< set pool start address */
|
||||
blk_pool->pool_addr = pool_addr;
|
||||
|
||||
/*!< set block area start address */
|
||||
blk_pool->blk_addr = (void *)address;
|
||||
|
||||
/*!< set block size (aligned) */
|
||||
blk_pool->blk_size = blk_size;
|
||||
|
||||
blk_pool->blk_align = blk_align;
|
||||
|
||||
blk_pool->blk_total = blk_count;
|
||||
|
||||
blk_pool->blk_free = blk_count;
|
||||
|
||||
blk_pool->mtx_get = NULL;
|
||||
blk_pool->mtx_put = NULL;
|
||||
blk_pool->sem_get = NULL;
|
||||
blk_pool->sem_put = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief delete a block blk_pool
|
||||
* @param blk_pool block pool instance
|
||||
* @return int
|
||||
*/
|
||||
int bflb_block_pool_delete(bflb_block_pool_t *blk_pool)
|
||||
{
|
||||
_BFLB_BLOCK_POOL_CHECK(blk_pool != NULL, -1);
|
||||
|
||||
if (blk_pool->blk_total != blk_pool->blk_free) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
blk_pool->free_list = NULL;
|
||||
blk_pool->pool_addr = NULL;
|
||||
blk_pool->blk_addr = NULL;
|
||||
blk_pool->blk_size = 0;
|
||||
blk_pool->blk_align = 0;
|
||||
blk_pool->blk_total = 0;
|
||||
blk_pool->blk_free = 0;
|
||||
blk_pool->mtx_get = NULL;
|
||||
blk_pool->mtx_put = NULL;
|
||||
blk_pool->sem_get = NULL;
|
||||
blk_pool->sem_put = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief register or unregister mutex
|
||||
* @param blk_pool block pool instance
|
||||
* @param get mutex get
|
||||
* @param put mutex put
|
||||
* @return int
|
||||
*/
|
||||
int bflb_block_pool_add_mtx(bflb_block_pool_t *blk_pool, int (*get)(uint32_t wait), void (*put)(void))
|
||||
{
|
||||
_BFLB_BLOCK_POOL_CHECK(blk_pool != NULL, -1);
|
||||
|
||||
if ((get == NULL) || (put == NULL)) {
|
||||
blk_pool->mtx_get = NULL;
|
||||
blk_pool->mtx_put = NULL;
|
||||
} else {
|
||||
blk_pool->mtx_get = get;
|
||||
blk_pool->mtx_put = put;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief register or unregister semaphore
|
||||
* @param blk_pool block pool instance
|
||||
* @param get semaphore get
|
||||
* @param put semaphore put
|
||||
* @return int
|
||||
*/
|
||||
int bflb_block_pool_add_sem(bflb_block_pool_t *blk_pool, int (*get)(uint32_t wait), void (*put)(void))
|
||||
{
|
||||
_BFLB_BLOCK_POOL_CHECK(blk_pool != NULL, -1);
|
||||
|
||||
if ((get == NULL) || (put == NULL)) {
|
||||
blk_pool->sem_get = NULL;
|
||||
blk_pool->sem_put = NULL;
|
||||
} else {
|
||||
blk_pool->sem_get = get;
|
||||
blk_pool->sem_put = put;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief alloc a block
|
||||
* @param blk_pool block pool instance
|
||||
* @param addr block pointer
|
||||
* @param wait timeout
|
||||
* @return int
|
||||
*/
|
||||
int bflb_block_pool_alloc(bflb_block_pool_t *blk_pool, void **addr, uint32_t wait)
|
||||
{
|
||||
_BFLB_BLOCK_POOL_CHECK(blk_pool != NULL, -1);
|
||||
_BFLB_BLOCK_POOL_CHECK(addr != NULL, -1);
|
||||
|
||||
void *node;
|
||||
uint32_t index;
|
||||
|
||||
if (blk_pool->sem_get) {
|
||||
/*!< check for free block by sem */
|
||||
if (blk_pool->sem_get(wait)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*!< check for free block */
|
||||
if (blk_pool->blk_free == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*!< get mutex */
|
||||
if (blk_pool->mtx_get) {
|
||||
if (blk_pool->mtx_get(CONFIG_BFLB_BLOCK_POOL_MTX_TIMEOUT)) {
|
||||
blk_pool->sem_put();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*!< get first free list node */
|
||||
node = blk_pool->free_list;
|
||||
|
||||
/*!< delete node from free_list */
|
||||
blk_pool->free_list = *((void **)node);
|
||||
|
||||
/*!< calculate the index */
|
||||
index = ((uintptr_t)node - (uintptr_t)(blk_pool->pool_addr)) / sizeof(void *);
|
||||
|
||||
/*!< calculate block address */
|
||||
*addr = (void *)((uintptr_t)(blk_pool->blk_addr) + (index * blk_pool->blk_size));
|
||||
|
||||
/*!< decrease free block count */
|
||||
blk_pool->blk_free -= 1;
|
||||
|
||||
/*!< put mutex */
|
||||
if (blk_pool->mtx_put) {
|
||||
blk_pool->mtx_put();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief free a block
|
||||
* @param blk_pool blk_pool
|
||||
* @param addr block pointer
|
||||
* @return int
|
||||
*/
|
||||
int bflb_block_pool_free(bflb_block_pool_t *blk_pool, void *addr)
|
||||
{
|
||||
_BFLB_BLOCK_POOL_CHECK(blk_pool != NULL, -1);
|
||||
_BFLB_BLOCK_POOL_CHECK(addr != NULL, -1);
|
||||
|
||||
void *node;
|
||||
uint32_t index;
|
||||
|
||||
if (blk_pool->mtx_get) {
|
||||
if (blk_pool->mtx_get(CONFIG_BFLB_BLOCK_POOL_MTX_TIMEOUT)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*!< simple check if addr is our block */
|
||||
if (blk_pool->blk_total == blk_pool->blk_free) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*!< calculate the index */
|
||||
/*!< maybe the original value calculated will be negative, but it has no effect. */
|
||||
index = ((uintptr_t)addr - (uintptr_t)(blk_pool->blk_addr)) / blk_pool->blk_size;
|
||||
|
||||
/*!< this is not our block */
|
||||
if (index > blk_pool->blk_total) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*!< calculate node address */
|
||||
node = (void *)((uintptr_t)(blk_pool->pool_addr) + (index * sizeof(void *)));
|
||||
|
||||
/*!< link first free list node */
|
||||
*((void **)node) = blk_pool->free_list;
|
||||
|
||||
/*!< set first free list node */
|
||||
blk_pool->free_list = node;
|
||||
|
||||
/*!< increase free block count */
|
||||
blk_pool->blk_free += 1;
|
||||
|
||||
if (blk_pool->mtx_put) {
|
||||
blk_pool->mtx_put();
|
||||
}
|
||||
|
||||
if (blk_pool->sem_put) {
|
||||
blk_pool->sem_put();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get block blk_pool info
|
||||
* @param blk_pool block pool instance
|
||||
* @param total_blk total block count pointer
|
||||
* @param free_blk free block count pointer
|
||||
* @return int
|
||||
*/
|
||||
void bflb_block_pool_info_get(bflb_block_pool_t *blk_pool, uint32_t *total_blk, uint32_t *free_blk)
|
||||
{
|
||||
_BFLB_BLOCK_POOL_CHECK(blk_pool != NULL, );
|
||||
|
||||
if (total_blk != NULL) {
|
||||
*total_blk = blk_pool->blk_total;
|
||||
}
|
||||
|
||||
if (free_blk != NULL) {
|
||||
*free_blk = blk_pool->blk_free;
|
||||
}
|
||||
}
|
64
components/utils/bflb_block_pool/bflb_block_pool.h
Normal file
64
components/utils/bflb_block_pool/bflb_block_pool.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* @file bflb_block_pool.h
|
||||
* @brief
|
||||
*
|
||||
* Copyright (c) 2021 Bouffalolab team
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _BFLB_BLOCK_POOL_H
|
||||
#define _BFLB_BLOCK_POOL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define BFLB_BLOCK_POOL_ALIGN_1 0x00
|
||||
#define BFLB_BLOCK_POOL_ALIGN_2 0x01
|
||||
#define BFLB_BLOCK_POOL_ALIGN_4 0x02
|
||||
#define BFLB_BLOCK_POOL_ALIGN_8 0x03
|
||||
#define BFLB_BLOCK_POOL_ALIGN_16 0x04
|
||||
#define BFLB_BLOCK_POOL_ALIGN_32 0x05
|
||||
#define BFLB_BLOCK_POOL_ALIGN_64 0x06
|
||||
#define BFLB_BLOCK_POOL_ALIGN_128 0x07
|
||||
|
||||
typedef struct {
|
||||
void *free_list; /*!< free block list */
|
||||
void *pool_addr; /*!< pool start pointer */
|
||||
void *blk_addr; /*!< block area start pointer */
|
||||
uint32_t blk_size; /*!< block size */
|
||||
uint32_t blk_align; /*!< block align */
|
||||
uint32_t blk_total; /*!< total block num */
|
||||
uint32_t blk_free; /*!< free block num */
|
||||
|
||||
int (*mtx_get)(uint32_t wait);
|
||||
void (*mtx_put)(void);
|
||||
int (*sem_get)(uint32_t wait);
|
||||
void (*sem_put)(void);
|
||||
} bflb_block_pool_t;
|
||||
|
||||
extern int bflb_block_pool_create(bflb_block_pool_t *blk_pool, uint32_t blk_size, uint32_t blk_align, void *pool_addr, uint32_t pool_size);
|
||||
extern int bflb_block_pool_delete(bflb_block_pool_t *blk_pool);
|
||||
|
||||
extern int bflb_block_pool_add_mtx(bflb_block_pool_t *blk_pool, int (*get)(uint32_t wait), void (*put)(void));
|
||||
extern int bflb_block_pool_add_sem(bflb_block_pool_t *blk_pool, int (*get)(uint32_t wait), void (*put)(void));
|
||||
|
||||
extern int bflb_block_pool_alloc(bflb_block_pool_t *blk_pool, void **addr, uint32_t wait);
|
||||
extern int bflb_block_pool_free(bflb_block_pool_t *blk_pool, void *addr);
|
||||
|
||||
extern void bflb_block_pool_info_get(bflb_block_pool_t *blk_pool, uint32_t *total_blk, uint32_t *free_blk);
|
||||
|
||||
#endif
|
140
components/utils/bflb_timestamp/bflb_timestamp.c
Normal file
140
components/utils/bflb_timestamp/bflb_timestamp.c
Normal file
|
@ -0,0 +1,140 @@
|
|||
/**
|
||||
* @file bflb_timestamp.c
|
||||
* @brief
|
||||
*
|
||||
* Copyright (c) 2022 Bouffalolab team
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bflb_timestamp.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
static const uint8_t month_day[12] = {
|
||||
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
|
||||
};
|
||||
|
||||
static const uint8_t leap_month_day[12] = {
|
||||
31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief check leap year
|
||||
* @param year year
|
||||
* @return uint8_t 1 leap year, 0 noleap year
|
||||
*/
|
||||
static uint8_t check_leap_year(uint16_t year)
|
||||
{
|
||||
if (year % 4) {
|
||||
return 0;
|
||||
} else {
|
||||
if ((year % 100 == 0) && (year % 400 != 0)) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief calculate week
|
||||
* @param time time
|
||||
* @return uint8_t
|
||||
*/
|
||||
static void cal_weekday(bflb_timestamp_t *time)
|
||||
{
|
||||
uint32_t y, m, d, w;
|
||||
|
||||
y = time->year;
|
||||
m = time->mon;
|
||||
d = time->mday;
|
||||
|
||||
if ((m == 1) || (m == 2)) {
|
||||
m += 12;
|
||||
y--;
|
||||
}
|
||||
|
||||
w = (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400 + 1) % 7;
|
||||
|
||||
time->wday = (uint8_t)w;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief timestamp to time
|
||||
* @param timestamp timestamp
|
||||
* @param time time
|
||||
*/
|
||||
void bflb_timestamp_utc2time(uint32_t utc, bflb_timestamp_t *time)
|
||||
{
|
||||
#define BFLB_TIMESTAMP_FOUR_YEAR_DAY ((365 << 2) + 1)
|
||||
#define BFLB_TIMESTAMP_SEC_NUM_PER_DAY (24 * 60 * 60)
|
||||
#define BFLB_TIMESTAMP_SEC_NUM_PER_HOUR (60 * 60)
|
||||
#define BFLB_TIMESTAMP_SEC_NUM_PER_MINUTE (60)
|
||||
|
||||
#ifndef BFLB_TIMESTAMP_TIMEZONE
|
||||
#define BFLB_TIMESTAMP_TIMEZONE 8
|
||||
#endif
|
||||
|
||||
uint32_t total_day_num;
|
||||
uint32_t current_sec_num;
|
||||
|
||||
uint16_t remain_day;
|
||||
|
||||
uint16_t temp_year;
|
||||
|
||||
const uint8_t *p = NULL;
|
||||
|
||||
total_day_num = utc / BFLB_TIMESTAMP_SEC_NUM_PER_DAY;
|
||||
current_sec_num = utc % BFLB_TIMESTAMP_SEC_NUM_PER_DAY;
|
||||
|
||||
time->hour = current_sec_num / BFLB_TIMESTAMP_SEC_NUM_PER_HOUR;
|
||||
time->min = (current_sec_num % BFLB_TIMESTAMP_SEC_NUM_PER_HOUR) / BFLB_TIMESTAMP_SEC_NUM_PER_MINUTE;
|
||||
time->sec = (current_sec_num % BFLB_TIMESTAMP_SEC_NUM_PER_HOUR) % BFLB_TIMESTAMP_SEC_NUM_PER_MINUTE;
|
||||
|
||||
time->hour += BFLB_TIMESTAMP_TIMEZONE;
|
||||
|
||||
if (time->hour > 23) {
|
||||
time->hour -= 24;
|
||||
total_day_num++;
|
||||
}
|
||||
|
||||
time->year = 1970 + (total_day_num / BFLB_TIMESTAMP_FOUR_YEAR_DAY) * 4;
|
||||
remain_day = total_day_num % BFLB_TIMESTAMP_FOUR_YEAR_DAY;
|
||||
|
||||
temp_year = check_leap_year(time->year) ? 366 : 365;
|
||||
while (remain_day >= temp_year) {
|
||||
time->year++;
|
||||
remain_day -= temp_year;
|
||||
temp_year = check_leap_year(time->year) ? 366 : 365;
|
||||
}
|
||||
|
||||
p = check_leap_year(time->year) ? leap_month_day : month_day;
|
||||
remain_day++;
|
||||
time->mon = 0;
|
||||
while (remain_day > *(p + time->mon)) {
|
||||
remain_day -= *(p + time->mon);
|
||||
time->mon++;
|
||||
}
|
||||
|
||||
time->mon++;
|
||||
time->mday = remain_day;
|
||||
|
||||
time->wday = time->mday + 2 * time->mon + 3 * (time->mon + 1) / 5 +
|
||||
time->year + time->year / 4 - time->year / 100 + time->year / 400;
|
||||
|
||||
cal_weekday(time);
|
||||
}
|
42
components/utils/bflb_timestamp/bflb_timestamp.h
Normal file
42
components/utils/bflb_timestamp/bflb_timestamp.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* @file bflb_timestamp.h
|
||||
* @brief
|
||||
*
|
||||
* Copyright (c) 2022 Bouffalolab team
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _BFLB_TIMESTAMP_H
|
||||
#define _BFLB_TIMESTAMP_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t sec;
|
||||
uint8_t min;
|
||||
uint8_t hour;
|
||||
uint8_t mday;
|
||||
uint8_t mon;
|
||||
uint16_t year;
|
||||
uint8_t wday;
|
||||
} bflb_timestamp_t;
|
||||
|
||||
extern void bflb_timestamp_utc2time(uint32_t utc, bflb_timestamp_t *time);
|
||||
|
||||
#endif
|
90
components/utils/libc/printf.c
Normal file
90
components/utils/libc/printf.c
Normal file
|
@ -0,0 +1,90 @@
|
|||
#include "bflb_uart.h"
|
||||
#include "stdarg.h"
|
||||
|
||||
struct bflb_device_s *console = NULL;
|
||||
|
||||
int printf(const char *fmt, ...)
|
||||
{
|
||||
char print_buf[128];
|
||||
uint32_t len;
|
||||
va_list ap;
|
||||
|
||||
if (console == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
va_start(ap, fmt);
|
||||
len = vsnprintf(print_buf, sizeof(print_buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
len = (len > sizeof(print_buf)) ? sizeof(print_buf) : len;
|
||||
|
||||
bflb_uart_put(console, (uint8_t *)print_buf, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
|
||||
void bflb_dump_hex(const void *ptr, uint32_t buflen)
|
||||
{
|
||||
unsigned char *buf = (unsigned char *)ptr;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < buflen; i += 16) {
|
||||
printf("%08X:", i);
|
||||
|
||||
for (j = 0; j < 16; j++)
|
||||
if (i + j < buflen) {
|
||||
if ((j % 8) == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
printf("%02X ", buf[i + j]);
|
||||
} else
|
||||
printf(" ");
|
||||
printf(" ");
|
||||
|
||||
for (j = 0; j < 16; j++)
|
||||
if (i + j < buflen)
|
||||
printf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// void bflb_dump_hex(uint8_t *data, uint32_t len)
|
||||
// {
|
||||
// uint32_t i = 0;
|
||||
|
||||
// for (i = 0; i < len; i++) {
|
||||
// if (i % 16 == 0) {
|
||||
// printf("\r\n");
|
||||
// }
|
||||
|
||||
// printf("%02x ", data[i]);
|
||||
// }
|
||||
|
||||
// printf("\r\n");
|
||||
// }
|
||||
|
||||
void bflb_reg_dump(uint32_t addr)
|
||||
{
|
||||
printf("%08lx[31:0]=%08lx\r\n", addr, *(volatile uint32_t *)(addr));
|
||||
}
|
||||
|
||||
int bflb_data_compare(const uint8_t *expected, uint8_t *input, uint32_t len)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (input[i] != expected[i]) {
|
||||
printf("Compare fail at %d,input %02x, but expect %02x\r\n", i, input[i], expected[i]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bflb_uart_set_console(struct bflb_device_s *dev)
|
||||
{
|
||||
console = dev;
|
||||
}
|
279
components/utils/libc/syscalls.c
Normal file
279
components/utils/libc/syscalls.c
Normal file
|
@ -0,0 +1,279 @@
|
|||
#include <reent.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include "bflb_uart.h"
|
||||
#ifdef CONFIG_TLSF
|
||||
#include "bflb_tlsf.h"
|
||||
#else
|
||||
#include "bflb_mmheap.h"
|
||||
|
||||
extern struct heap_info mmheap_root;
|
||||
#endif
|
||||
|
||||
extern struct bflb_device_s *console;
|
||||
|
||||
/* Reentrant versions of system calls. */
|
||||
|
||||
/* global errno */
|
||||
static volatile int _sys_errno = 0;
|
||||
|
||||
#ifndef _REENT_ONLY
|
||||
int *__errno()
|
||||
{
|
||||
return (int *)&_sys_errno;
|
||||
}
|
||||
#endif
|
||||
|
||||
int _getpid_r(struct _reent *ptr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _execve_r(struct _reent *ptr, const char *name, char *const *argv, char *const *env)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _fcntl_r(struct _reent *ptr, int fd, int cmd, int arg)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _fork_r(struct _reent *ptr)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _fstat_r(struct _reent *ptr, int fd, struct stat *pstat)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _isatty_r(struct _reent *ptr, int fd)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _kill_r(struct _reent *ptr, int pid, int sig)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _link_r(struct _reent *ptr, const char *old, const char *new)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_off_t _lseek_r(struct _reent *ptr, int fd, _off_t pos, int whence)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _mkdir_r(struct _reent *ptr, const char *name, int mode)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _open_r(struct _reent *ptr, const char *file, int flags, int mode)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _close_r(struct _reent *ptr, int fd)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_ssize_t _read_r(struct _reent *ptr, int fd, void *buf, size_t nbytes)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _rename_r(struct _reent *ptr, const char *old, const char *new)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _stat_r(struct _reent *ptr, const char *file, struct stat *pstat)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _unlink_r(struct _reent *ptr, const char *file)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _wait_r(struct _reent *ptr, int *status)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_ssize_t _write_r(struct _reent *ptr, int fd, const void *buf, size_t nbytes)
|
||||
{
|
||||
if ((STDOUT_FILENO == fd) || (STDERR_FILENO == fd)) {
|
||||
bflb_uart_put(console, (uint8_t *)buf, nbytes);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *_malloc_r(struct _reent *ptr, size_t size)
|
||||
{
|
||||
void *result;
|
||||
#ifdef CONFIG_MEM_USE_FREERTOS
|
||||
result = pvPortMalloc(size);
|
||||
#else
|
||||
#ifdef CONFIG_TLSF
|
||||
result = (void *)bflb_malloc(size);
|
||||
#else
|
||||
result = (void *)bflb_mmheap_alloc(&mmheap_root, size);
|
||||
#endif
|
||||
#endif
|
||||
if (result == NULL) {
|
||||
ptr->_errno = -ENOMEM;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void *_realloc_r(struct _reent *ptr, void *old, size_t newlen)
|
||||
{
|
||||
void *result;
|
||||
#ifdef CONFIG_MEM_USE_FREERTOS
|
||||
#else
|
||||
#ifdef CONFIG_TLSF
|
||||
result = (void *)bflb_realloc(old, newlen);
|
||||
#else
|
||||
result = (void *)bflb_mmheap_realloc(&mmheap_root, old, newlen);
|
||||
#endif
|
||||
#endif
|
||||
if (result == NULL) {
|
||||
ptr->_errno = -ENOMEM;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void *_calloc_r(struct _reent *ptr, size_t size, size_t len)
|
||||
{
|
||||
void *result;
|
||||
#ifdef CONFIG_MEM_USE_FREERTOS
|
||||
result = pvPortMalloc(size * len);
|
||||
#else
|
||||
#ifdef CONFIG_TLSF
|
||||
result = (void *)bflb_calloc(size, len);
|
||||
#else
|
||||
result = (void *)bflb_mmheap_calloc(&mmheap_root, size, len);
|
||||
#endif
|
||||
#endif
|
||||
if (result == NULL) {
|
||||
ptr->_errno = -ENOMEM;
|
||||
}
|
||||
if (result) {
|
||||
memset(result, 0, size * len);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void *_memalign_r(struct _reent *ptr, size_t align, size_t size)
|
||||
{
|
||||
void *result;
|
||||
#ifdef CONFIG_MEM_USE_FREERTOS
|
||||
#else
|
||||
#ifdef CONFIG_TLSF
|
||||
result = (void *)bflb_malloc_align(align, size);
|
||||
#else
|
||||
result = (void *)bflb_mmheap_align_alloc(&mmheap_root, align, size);
|
||||
#endif
|
||||
#endif
|
||||
if (result == NULL) {
|
||||
ptr->_errno = -ENOMEM;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void _free_r(struct _reent *ptr, void *addr)
|
||||
{
|
||||
#ifdef CONFIG_MEM_USE_FREERTOS
|
||||
vPortFree(addr);
|
||||
#else
|
||||
#ifdef CONFIG_TLSF
|
||||
bflb_free(addr);
|
||||
#else
|
||||
bflb_mmheap_free(&mmheap_root, addr);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void *_sbrk_r(struct _reent *ptr, ptrdiff_t incr)
|
||||
{
|
||||
void *ret;
|
||||
ptr->_errno = ENOMEM;
|
||||
ret = (void *)-1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* for exit() and abort() */
|
||||
void __attribute__((noreturn))
|
||||
_exit(int status)
|
||||
{
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
void _system(const char *s)
|
||||
{
|
||||
}
|
||||
|
||||
void __libc_init_array(void)
|
||||
{
|
||||
/* we not use __libc init_aray to initialize C++ objects */
|
||||
}
|
||||
|
||||
mode_t umask(mode_t mask)
|
||||
{
|
||||
return 022;
|
||||
}
|
||||
|
||||
int flock(int fd, int operation)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
These functions are implemented and replaced by the 'common/time.c' file
|
||||
int _gettimeofday_r(struct _reent *ptr, struct timeval *__tp, void *__tzp);
|
||||
_CLOCK_T_ _times_r(struct _reent *ptr, struct tms *ptms);
|
||||
*/
|
1075
components/utils/libc/vsnprintf.c
Normal file
1075
components/utils/libc/vsnprintf.c
Normal file
File diff suppressed because it is too large
Load diff
524
components/utils/libc/vsnprintf_nano.c
Normal file
524
components/utils/libc/vsnprintf_nano.c
Normal file
|
@ -0,0 +1,524 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2006-03-16 Bernard the first version
|
||||
* 2006-05-25 Bernard rewrite vsprintf
|
||||
* 2006-08-10 Bernard add rt_show_version
|
||||
* 2010-03-17 Bernard remove rt_strlcpy function
|
||||
* fix gcc compiling issue.
|
||||
* 2010-04-15 Bernard remove weak definition on ICCM16C compiler
|
||||
* 2012-07-18 Arda add the alignment display for signed integer
|
||||
* 2012-11-23 Bernard fix IAR compiler error.
|
||||
* 2012-12-22 Bernard fix rt_kprintf issue, which found by Grissiom.
|
||||
* 2013-06-24 Bernard remove rt_kprintf if RT_USING_CONSOLE is not defined.
|
||||
* 2013-09-24 aozima make sure the device is in STREAM mode when used by rt_kprintf.
|
||||
* 2015-07-06 Bernard Add rt_assert_handler routine.
|
||||
* 2021-02-28 Meco Man add RT_KSERVICE_USING_STDLIB
|
||||
*/
|
||||
|
||||
#include "string.h"
|
||||
#include "stdint.h"
|
||||
#include "stdarg.h"
|
||||
|
||||
/* use precision */
|
||||
#define RT_PRINTF_PRECISION
|
||||
|
||||
/* private function */
|
||||
#define _ISDIGIT(c) ((unsigned)((c) - '0') < 10)
|
||||
|
||||
#ifdef RT_PRINTF_LONGLONG
|
||||
/**
|
||||
* This function will duplicate a string.
|
||||
*
|
||||
* @param n is the string to be duplicated.
|
||||
*
|
||||
* @param base is support divide instructions value.
|
||||
*
|
||||
* @return the duplicated string pointer.
|
||||
*/
|
||||
static inline int divide(long long *n, int base)
|
||||
{
|
||||
int res;
|
||||
|
||||
/* optimized for processor which does not support divide instructions. */
|
||||
if (base == 10) {
|
||||
res = (int)(((unsigned long long)*n) % 10U);
|
||||
*n = (long long)(((unsigned long long)*n) / 10U);
|
||||
} else {
|
||||
res = (int)(((unsigned long long)*n) % 16U);
|
||||
*n = (long long)(((unsigned long long)*n) / 16U);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
#else
|
||||
static inline int divide(long *n, int base)
|
||||
{
|
||||
int res;
|
||||
|
||||
/* optimized for processor which does not support divide instructions. */
|
||||
if (base == 10) {
|
||||
res = (int)(((unsigned long)*n) % 10U);
|
||||
*n = (long)(((unsigned long)*n) / 10U);
|
||||
} else {
|
||||
res = (int)(((unsigned long)*n) % 16U);
|
||||
*n = (long)(((unsigned long)*n) / 16U);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif /* RT_PRINTF_LONGLONG */
|
||||
|
||||
static inline int skip_atoi(const char **s)
|
||||
{
|
||||
register int i = 0;
|
||||
while (_ISDIGIT(**s))
|
||||
i = i * 10 + *((*s)++) - '0';
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
#define ZEROPAD (1 << 0) /* pad with zero */
|
||||
#define SIGN (1 << 1) /* unsigned/signed long */
|
||||
#define PLUS (1 << 2) /* show plus */
|
||||
#define SPACE (1 << 3) /* space if plus */
|
||||
#define LEFT (1 << 4) /* left justified */
|
||||
#define SPECIAL (1 << 5) /* 0x */
|
||||
#define LARGE (1 << 6) /* use 'ABCDEF' instead of 'abcdef' */
|
||||
|
||||
#ifdef RT_PRINTF_PRECISION
|
||||
static char *print_number(char *buf,
|
||||
char *end,
|
||||
#ifdef RT_PRINTF_LONGLONG
|
||||
long long num,
|
||||
#else
|
||||
long num,
|
||||
#endif /* RT_PRINTF_LONGLONG */
|
||||
int base,
|
||||
int s,
|
||||
int precision,
|
||||
int type)
|
||||
#else
|
||||
static char *print_number(char *buf,
|
||||
char *end,
|
||||
#ifdef RT_PRINTF_LONGLONG
|
||||
long long num,
|
||||
#else
|
||||
long num,
|
||||
#endif /* RT_PRINTF_LONGLONG */
|
||||
int base,
|
||||
int s,
|
||||
int type)
|
||||
#endif /* RT_PRINTF_PRECISION */
|
||||
{
|
||||
char c, sign;
|
||||
#ifdef RT_PRINTF_LONGLONG
|
||||
char tmp[32];
|
||||
#else
|
||||
char tmp[16];
|
||||
#endif /* RT_PRINTF_LONGLONG */
|
||||
int precision_bak = precision;
|
||||
const char *digits;
|
||||
static const char small_digits[] = "0123456789abcdef";
|
||||
static const char large_digits[] = "0123456789ABCDEF";
|
||||
register int i;
|
||||
register int size;
|
||||
|
||||
size = s;
|
||||
|
||||
digits = (type & LARGE) ? large_digits : small_digits;
|
||||
if (type & LEFT)
|
||||
type &= ~ZEROPAD;
|
||||
|
||||
c = (type & ZEROPAD) ? '0' : ' ';
|
||||
|
||||
/* get sign */
|
||||
sign = 0;
|
||||
if (type & SIGN) {
|
||||
if (num < 0) {
|
||||
sign = '-';
|
||||
num = -num;
|
||||
} else if (type & PLUS)
|
||||
sign = '+';
|
||||
else if (type & SPACE)
|
||||
sign = ' ';
|
||||
}
|
||||
|
||||
#ifdef RT_PRINTF_SPECIAL
|
||||
if (type & SPECIAL) {
|
||||
if (base == 16)
|
||||
size -= 2;
|
||||
else if (base == 8)
|
||||
size--;
|
||||
}
|
||||
#endif /* RT_PRINTF_SPECIAL */
|
||||
|
||||
i = 0;
|
||||
if (num == 0)
|
||||
tmp[i++] = '0';
|
||||
else {
|
||||
while (num != 0)
|
||||
tmp[i++] = digits[divide(&num, base)];
|
||||
}
|
||||
|
||||
#ifdef RT_PRINTF_PRECISION
|
||||
if (i > precision)
|
||||
precision = i;
|
||||
size -= precision;
|
||||
#else
|
||||
size -= i;
|
||||
#endif /* RT_PRINTF_PRECISION */
|
||||
|
||||
if (!(type & (ZEROPAD | LEFT))) {
|
||||
if ((sign) && (size > 0))
|
||||
size--;
|
||||
|
||||
while (size-- > 0) {
|
||||
if (buf < end)
|
||||
*buf = ' ';
|
||||
++buf;
|
||||
}
|
||||
}
|
||||
|
||||
if (sign) {
|
||||
if (buf < end) {
|
||||
*buf = sign;
|
||||
}
|
||||
--size;
|
||||
++buf;
|
||||
}
|
||||
|
||||
#ifdef RT_PRINTF_SPECIAL
|
||||
if (type & SPECIAL) {
|
||||
if (base == 8) {
|
||||
if (buf < end)
|
||||
*buf = '0';
|
||||
++buf;
|
||||
} else if (base == 16) {
|
||||
if (buf < end)
|
||||
*buf = '0';
|
||||
++buf;
|
||||
if (buf < end) {
|
||||
*buf = type & LARGE ? 'X' : 'x';
|
||||
}
|
||||
++buf;
|
||||
}
|
||||
}
|
||||
#endif /* RT_PRINTF_SPECIAL */
|
||||
|
||||
/* no align to the left */
|
||||
if (!(type & LEFT)) {
|
||||
while (size-- > 0) {
|
||||
if (buf < end)
|
||||
*buf = c;
|
||||
++buf;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RT_PRINTF_PRECISION
|
||||
while (i < precision--) {
|
||||
if (buf < end)
|
||||
*buf = '0';
|
||||
++buf;
|
||||
}
|
||||
#endif /* RT_PRINTF_PRECISION */
|
||||
|
||||
/* put number in the temporary buffer */
|
||||
while (i-- > 0 && (precision_bak != 0)) {
|
||||
if (buf < end)
|
||||
*buf = tmp[i];
|
||||
++buf;
|
||||
}
|
||||
|
||||
while (size-- > 0) {
|
||||
if (buf < end)
|
||||
*buf = ' ';
|
||||
++buf;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
int vsnprintf (char *, size_t, const char *, va_list) __attribute__ ((alias ("rt_vsnprintf")));
|
||||
|
||||
/**
|
||||
* This function will fill a formatted string to buffer.
|
||||
*
|
||||
* @param buf is the buffer to save formatted string.
|
||||
*
|
||||
* @param size is the size of buffer.
|
||||
*
|
||||
* @param fmt is the format parameters.
|
||||
*
|
||||
* @param args is a list of variable parameters.
|
||||
*
|
||||
* @return The number of characters actually written to buffer.
|
||||
*/
|
||||
int32_t rt_vsnprintf(char *buf,
|
||||
size_t size,
|
||||
const char *fmt,
|
||||
va_list args)
|
||||
{
|
||||
#ifdef RT_PRINTF_LONGLONG
|
||||
unsigned long long num;
|
||||
#else
|
||||
uint32_t num;
|
||||
#endif /* RT_PRINTF_LONGLONG */
|
||||
int i, len;
|
||||
char *str, *end, c;
|
||||
const char *s;
|
||||
|
||||
uint8_t base; /* the base of number */
|
||||
uint8_t flags; /* flags to print number */
|
||||
uint8_t qualifier; /* 'h', 'l', or 'L' for integer fields */
|
||||
int32_t field_width; /* width of output field */
|
||||
|
||||
#ifdef RT_PRINTF_PRECISION
|
||||
int precision; /* min. # of digits for integers and max for a string */
|
||||
#endif /* RT_PRINTF_PRECISION */
|
||||
|
||||
str = buf;
|
||||
end = buf + size;
|
||||
|
||||
/* Make sure end is always >= buf */
|
||||
if (end < buf) {
|
||||
end = ((char *)-1);
|
||||
size = end - buf;
|
||||
}
|
||||
|
||||
for (; *fmt; ++fmt) {
|
||||
if (*fmt != '%') {
|
||||
if (str < end)
|
||||
*str = *fmt;
|
||||
++str;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* process flags */
|
||||
flags = 0;
|
||||
|
||||
while (1) {
|
||||
/* skips the first '%' also */
|
||||
++fmt;
|
||||
if (*fmt == '-')
|
||||
flags |= LEFT;
|
||||
else if (*fmt == '+')
|
||||
flags |= PLUS;
|
||||
else if (*fmt == ' ')
|
||||
flags |= SPACE;
|
||||
else if (*fmt == '#')
|
||||
flags |= SPECIAL;
|
||||
else if (*fmt == '0')
|
||||
flags |= ZEROPAD;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* get field width */
|
||||
field_width = -1;
|
||||
if (_ISDIGIT(*fmt))
|
||||
field_width = skip_atoi(&fmt);
|
||||
else if (*fmt == '*') {
|
||||
++fmt;
|
||||
/* it's the next argument */
|
||||
field_width = va_arg(args, int);
|
||||
if (field_width < 0) {
|
||||
field_width = -field_width;
|
||||
flags |= LEFT;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RT_PRINTF_PRECISION
|
||||
/* get the precision */
|
||||
precision = -1;
|
||||
if (*fmt == '.') {
|
||||
++fmt;
|
||||
if (_ISDIGIT(*fmt))
|
||||
precision = skip_atoi(&fmt);
|
||||
else if (*fmt == '*') {
|
||||
++fmt;
|
||||
/* it's the next argument */
|
||||
precision = va_arg(args, int);
|
||||
}
|
||||
if (precision < 0)
|
||||
precision = 0;
|
||||
}
|
||||
#endif /* RT_PRINTF_PRECISION */
|
||||
/* get the conversion qualifier */
|
||||
qualifier = 0;
|
||||
#ifdef RT_PRINTF_LONGLONG
|
||||
if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L')
|
||||
#else
|
||||
if (*fmt == 'h' || *fmt == 'l')
|
||||
#endif /* RT_PRINTF_LONGLONG */
|
||||
{
|
||||
qualifier = *fmt;
|
||||
++fmt;
|
||||
#ifdef RT_PRINTF_LONGLONG
|
||||
if (qualifier == 'l' && *fmt == 'l') {
|
||||
qualifier = 'L';
|
||||
++fmt;
|
||||
}
|
||||
#endif /* RT_PRINTF_LONGLONG */
|
||||
}
|
||||
|
||||
/* the default base */
|
||||
base = 10;
|
||||
|
||||
switch (*fmt) {
|
||||
case 'c':
|
||||
if (!(flags & LEFT)) {
|
||||
while (--field_width > 0) {
|
||||
if (str < end)
|
||||
*str = ' ';
|
||||
++str;
|
||||
}
|
||||
}
|
||||
|
||||
/* get character */
|
||||
c = (uint8_t)va_arg(args, int);
|
||||
if (str < end)
|
||||
*str = c;
|
||||
++str;
|
||||
|
||||
/* put width */
|
||||
while (--field_width > 0) {
|
||||
if (str < end)
|
||||
*str = ' ';
|
||||
++str;
|
||||
}
|
||||
continue;
|
||||
|
||||
case 's':
|
||||
s = va_arg(args, char *);
|
||||
if (!s)
|
||||
s = "(NULL)";
|
||||
|
||||
for (len = 0; (len != field_width) && (s[len] != '\0'); len++)
|
||||
;
|
||||
#ifdef RT_PRINTF_PRECISION
|
||||
if (precision > 0 && len > precision)
|
||||
len = precision;
|
||||
#endif /* RT_PRINTF_PRECISION */
|
||||
|
||||
if (!(flags & LEFT)) {
|
||||
while (len < field_width--) {
|
||||
if (str < end)
|
||||
*str = ' ';
|
||||
++str;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
if (str < end)
|
||||
*str = *s;
|
||||
++str;
|
||||
++s;
|
||||
}
|
||||
|
||||
while (len < field_width--) {
|
||||
if (str < end)
|
||||
*str = ' ';
|
||||
++str;
|
||||
}
|
||||
continue;
|
||||
|
||||
case 'p':
|
||||
if (field_width == -1) {
|
||||
field_width = sizeof(void *) << 1;
|
||||
flags |= ZEROPAD;
|
||||
}
|
||||
#ifdef RT_PRINTF_PRECISION
|
||||
str = print_number(str, end,
|
||||
(long)va_arg(args, void *),
|
||||
16, field_width, precision, flags);
|
||||
#else
|
||||
str = print_number(str, end,
|
||||
(long)va_arg(args, void *),
|
||||
16, field_width, flags);
|
||||
#endif /* RT_PRINTF_PRECISION */
|
||||
continue;
|
||||
|
||||
case '%':
|
||||
if (str < end)
|
||||
*str = '%';
|
||||
++str;
|
||||
continue;
|
||||
|
||||
/* integer number formats - set up the flags and "break" */
|
||||
case 'o':
|
||||
base = 8;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
flags |= LARGE;
|
||||
case 'x':
|
||||
base = 16;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'i':
|
||||
flags |= SIGN;
|
||||
case 'u':
|
||||
break;
|
||||
|
||||
default:
|
||||
if (str < end)
|
||||
*str = '%';
|
||||
++str;
|
||||
|
||||
if (*fmt) {
|
||||
if (str < end)
|
||||
*str = *fmt;
|
||||
++str;
|
||||
} else {
|
||||
--fmt;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef RT_PRINTF_LONGLONG
|
||||
if (qualifier == 'L')
|
||||
num = va_arg(args, long long);
|
||||
else if (qualifier == 'l')
|
||||
#else
|
||||
if (qualifier == 'l')
|
||||
#endif /* RT_PRINTF_LONGLONG */
|
||||
{
|
||||
num = va_arg(args, uint32_t);
|
||||
if (flags & SIGN)
|
||||
num = (int32_t)num;
|
||||
} else if (qualifier == 'h') {
|
||||
num = (uint16_t)va_arg(args, int32_t);
|
||||
if (flags & SIGN)
|
||||
num = (int16_t)num;
|
||||
} else {
|
||||
num = va_arg(args, uint32_t);
|
||||
if (flags & SIGN)
|
||||
num = (int32_t)num;
|
||||
}
|
||||
#ifdef RT_PRINTF_PRECISION
|
||||
str = print_number(str, end, num, base, field_width, precision, flags);
|
||||
#else
|
||||
str = print_number(str, end, num, base, field_width, flags);
|
||||
#endif /* RT_PRINTF_PRECISION */
|
||||
}
|
||||
|
||||
if (size > 0) {
|
||||
if (str < end)
|
||||
*str = '\0';
|
||||
else {
|
||||
end[-1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/* the trailing null byte doesn't count towards the total
|
||||
* ++str;
|
||||
*/
|
||||
return str - buf;
|
||||
}
|
||||
|
45
components/utils/log/log.c
Normal file
45
components/utils/log/log.c
Normal file
|
@ -0,0 +1,45 @@
|
|||
#ifdef CONFIG_BFLOG
|
||||
#include "bflog.h"
|
||||
|
||||
#ifndef CONFIG_BFLOG_POOL_SIZE
|
||||
#define CONFIG_BFLOG_POOL_SIZE 1024
|
||||
#endif
|
||||
|
||||
bflog_t __bflog_recorder;
|
||||
static uint8_t bflog_pool[CONFIG_BFLOG_POOL_SIZE];
|
||||
bflog_direct_stream_t bflog_direct_stream;
|
||||
|
||||
extern uint16_t __console_output(void *ptr, uint16_t size);
|
||||
|
||||
#endif
|
||||
|
||||
void log_init(void)
|
||||
{
|
||||
#ifdef CONFIG_BFLOG
|
||||
void *record = (void *)&__bflog_recorder;
|
||||
void *direct = (void *)&bflog_direct_stream;
|
||||
|
||||
/*!< create recorder */
|
||||
bflog_create_s(record, bflog_pool, CONFIG_BFLOG_POOL_SIZE, BFLOG_MODE_SYNC);
|
||||
|
||||
/*!< create stream direct */
|
||||
bflog_direct_create(direct, BFLOG_DIRECT_TYPE_STREAM, BFLOG_DIRECT_COLOR_ENABLE, NULL, NULL);
|
||||
bflog_direct_init_stream_s((void *)direct, __console_output);
|
||||
|
||||
/*!< connect direct and recorder */
|
||||
bflog_append_s(record, direct);
|
||||
|
||||
/*!< resume direct */
|
||||
bflog_direct_resume_s(direct);
|
||||
|
||||
/*!< resume record */
|
||||
bflog_resume_s(record);
|
||||
#endif
|
||||
}
|
||||
|
||||
__attribute__((weak)) void error_handler(void)
|
||||
{
|
||||
volatile unsigned char dummy = 0;
|
||||
while (dummy == 0) {
|
||||
}
|
||||
}
|
173
components/utils/log/log.h
Normal file
173
components/utils/log/log.h
Normal file
|
@ -0,0 +1,173 @@
|
|||
/**
|
||||
* @file log.h
|
||||
* @brief
|
||||
*
|
||||
* Copyright (c) 2021 Bouffalolab team
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LOG_H
|
||||
#define _LOG_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef CONFIG_BFLOG
|
||||
#include "bflog.h"
|
||||
extern bflog_t __bflog_recorder;
|
||||
#endif
|
||||
|
||||
#ifndef DBG_TAG
|
||||
#define DBG_TAG ""
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LOG_DISABLE
|
||||
#define LOG_F(...) (void(0))
|
||||
#define LOG_E(...) (void(0))
|
||||
#define LOG_W(...) (void(0))
|
||||
#define LOG_I(...) (void(0))
|
||||
#define LOG_D(...) (void(0))
|
||||
#define LOG_T(...) (void(0))
|
||||
#define LOG_FLUSH() (void(0))
|
||||
#else
|
||||
|
||||
#ifdef CONFIG_BFLOG
|
||||
|
||||
#if (CONFIG_LOG_LEVEL >= 0)
|
||||
#define LOG_F(...) BFLOG_F((void *)&__bflog_recorder, DBG_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_F(...) ((void)0)
|
||||
#endif
|
||||
|
||||
#if (CONFIG_LOG_LEVEL >= 1)
|
||||
#define LOG_E(...) BFLOG_E((void *)&__bflog_recorder, DBG_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_E(...) ((void)0)
|
||||
#endif
|
||||
|
||||
#if (CONFIG_LOG_LEVEL >= 2)
|
||||
#define LOG_W(...) BFLOG_W((void *)&__bflog_recorder, DBG_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_W(...) ((void)0)
|
||||
#endif
|
||||
|
||||
#if (CONFIG_LOG_LEVEL >= 3)
|
||||
#define LOG_I(...) BFLOG_I((void *)&__bflog_recorder, DBG_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_I(...) ((void)0)
|
||||
#endif
|
||||
|
||||
#if (CONFIG_LOG_LEVEL >= 4)
|
||||
#define LOG_D(...) BFLOG_D((void *)&__bflog_recorder, DBG_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_D(...) ((void)0)
|
||||
#endif
|
||||
|
||||
#if (CONFIG_LOG_LEVEL >= 5)
|
||||
#define LOG_T(...) BFLOG_T((void *)&__bflog_recorder, DBG_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_T(...) ((void)0)
|
||||
#endif
|
||||
|
||||
#define LOG_FLUSH() bflog_flush_s(&__bflog_recorder)
|
||||
|
||||
#else
|
||||
|
||||
#if (CONFIG_LOG_LEVEL >= 0)
|
||||
#define LOG_F(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define LOG_F(...) ((void)0)
|
||||
#endif
|
||||
|
||||
#if (CONFIG_LOG_LEVEL >= 1)
|
||||
#define LOG_E(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define LOG_E(...) ((void)0)
|
||||
#endif
|
||||
|
||||
#if (CONFIG_LOG_LEVEL >= 2)
|
||||
#define LOG_W(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define LOG_W(...) ((void)0)
|
||||
#endif
|
||||
|
||||
#if (CONFIG_LOG_LEVEL >= 3)
|
||||
#define LOG_I(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define LOG_I(...) ((void)0)
|
||||
#endif
|
||||
|
||||
#if (CONFIG_LOG_LEVEL >= 4)
|
||||
#define LOG_D(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define LOG_D(...) ((void)0)
|
||||
#endif
|
||||
|
||||
#if (CONFIG_LOG_LEVEL >= 5)
|
||||
#define LOG_T(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define LOG_T(...) ((void)0)
|
||||
#endif
|
||||
|
||||
#define LOG_FLUSH() ((void)0)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern void error_handler(void);
|
||||
|
||||
#ifdef CONFIG_ASSERT_DISABLE
|
||||
|
||||
#define _ASSERT_PARAM(x) ((void)(0))
|
||||
#define _ASSERT_FUNC(x) ((void)(x))
|
||||
#define _CALL_ERROR() error_handler()
|
||||
|
||||
#else
|
||||
|
||||
#define _CALL_ERROR() \
|
||||
do { \
|
||||
printf("(Call Error Handler)\r\n"); \
|
||||
LOG_F("Call Error Handler\r\n"); \
|
||||
LOG_FLUSH(); \
|
||||
error_handler(); \
|
||||
} while (0)
|
||||
|
||||
#define _ASSERT_PARAM(x) \
|
||||
if ((uint32_t)(x) == 0) { \
|
||||
printf("(Assertion Faild)\r\n"); \
|
||||
printf("(%s)\r\n", (const char *)(#x)); \
|
||||
LOG_F("Assertion Faild\r\n"); \
|
||||
LOG_F("%s\r\n", (const char *)(#x)); \
|
||||
LOG_FLUSH(); \
|
||||
error_handler(); \
|
||||
}
|
||||
|
||||
#define _ASSERT_FUNC(x) \
|
||||
do { \
|
||||
if ((uint32_t)(x) == 0) { \
|
||||
printf("(Assertion Faild)\r\n"); \
|
||||
printf("(%s)\r\n", (const char *)(#x)); \
|
||||
LOG_F("Assertion Faild\r\n"); \
|
||||
LOG_F("%s\r\n", (const char *)(#x)); \
|
||||
LOG_FLUSH(); \
|
||||
error_handler(); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#endif
|
421
components/utils/mmheap/bflb_mmheap.c
Normal file
421
components/utils/mmheap/bflb_mmheap.c
Normal file
|
@ -0,0 +1,421 @@
|
|||
/**
|
||||
* @file bflb_mmheap.c
|
||||
* @brief
|
||||
*
|
||||
* Copyright (c) 2021 Bouffalolab team
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bflb_mmheap.h"
|
||||
|
||||
#define MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT 8
|
||||
#define MEM_MANAGE_BITS_PER_BYTE 8
|
||||
#define MEM_MANAGE_MEM_STRUCT_SIZE mmheap_align_up(sizeof(struct heap_node), MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT)
|
||||
#define MEM_MANAGE_MINUM_MEM_SIZE (MEM_MANAGE_MEM_STRUCT_SIZE << 1)
|
||||
#define MEM_MANAGE_ALLOCA_LABAL ((size_t)((size_t)1 << (sizeof(size_t) * MEM_MANAGE_BITS_PER_BYTE - 1)))
|
||||
|
||||
static inline size_t mmheap_align_down(size_t data, size_t align_byte)
|
||||
{
|
||||
return data & ~(align_byte - 1);
|
||||
}
|
||||
|
||||
static inline size_t mmheap_align_up(size_t data, size_t align_byte)
|
||||
{
|
||||
return (data + align_byte - 1) & ~(align_byte - 1);
|
||||
}
|
||||
|
||||
static inline struct heap_node *mmheap_addr_sub(const void *addr)
|
||||
{
|
||||
return (struct heap_node *)((const uint8_t *)addr - MEM_MANAGE_MEM_STRUCT_SIZE);
|
||||
}
|
||||
|
||||
static inline void *mmheap_addr_add(const struct heap_node *mem_node)
|
||||
{
|
||||
return (void *)((const uint8_t *)mem_node + MEM_MANAGE_MEM_STRUCT_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mmheap_insert_node_to_freelist
|
||||
*
|
||||
* @param pRoot
|
||||
* @param pNode
|
||||
*/
|
||||
static inline void mmheap_insert_node_to_freelist(struct heap_info *pRoot, struct heap_node *pNode)
|
||||
{
|
||||
struct heap_node *pPriv_Node;
|
||||
struct heap_node *pNext_Node;
|
||||
/*Find the node with an address similar to pNode*/
|
||||
for (pPriv_Node = pRoot->pStart; pPriv_Node->next_node < pNode; pPriv_Node = pPriv_Node->next_node) {
|
||||
}
|
||||
|
||||
pNext_Node = pPriv_Node->next_node;
|
||||
/*Try to merge the pNode with the previous block*/
|
||||
if ((uint8_t *)mmheap_addr_add(pPriv_Node) + pPriv_Node->mem_size == (uint8_t *)pNode) {
|
||||
if (pPriv_Node != pRoot->pStart) { /*can merge if not start block*/
|
||||
pPriv_Node->mem_size += MEM_MANAGE_MEM_STRUCT_SIZE + pNode->mem_size;
|
||||
pNode = pPriv_Node;
|
||||
} else {
|
||||
/*The latter is not merged if it is a Start block to avoid wasting memory*/
|
||||
pRoot->pStart->next_node = pNode;
|
||||
}
|
||||
} else {
|
||||
/*Insert directly into the free single-chain table when merging is not possible*/
|
||||
pPriv_Node->next_node = pNode;
|
||||
}
|
||||
/*Try to merge the pNode with the next block*/
|
||||
if ((uint8_t *)mmheap_addr_add(pNode) + pNode->mem_size == (uint8_t *)pNext_Node) {
|
||||
if (pNext_Node != pRoot->pEnd) {
|
||||
pNode->mem_size += MEM_MANAGE_MEM_STRUCT_SIZE + pNext_Node->mem_size;
|
||||
pNode->next_node = pNext_Node->next_node;
|
||||
} else {
|
||||
pNode->next_node = pRoot->pEnd;
|
||||
}
|
||||
} else {
|
||||
/*Insert directly into the free single-chain table when merging is not possible*/
|
||||
pNode->next_node = pNext_Node;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mmheap_get_state
|
||||
*
|
||||
* @param pRoot
|
||||
* @param pState
|
||||
*/
|
||||
void mmheap_get_state(struct heap_info *pRoot, struct heap_state *pState)
|
||||
{
|
||||
MMHEAP_ASSERT(pRoot->pStart != NULL);
|
||||
MMHEAP_ASSERT(pRoot->pEnd != NULL);
|
||||
pState->max_node_size = pRoot->pStart->next_node->mem_size;
|
||||
pState->min_node_size = pRoot->pStart->next_node->mem_size;
|
||||
pState->remain_size = 0;
|
||||
pState->free_node_num = 0;
|
||||
MMHEAP_LOCK();
|
||||
for (struct heap_node *pNode = pRoot->pStart->next_node; pNode->next_node != NULL; pNode = pNode->next_node) {
|
||||
pState->remain_size += pNode->mem_size;
|
||||
pState->free_node_num++;
|
||||
if (pNode->mem_size > pState->max_node_size)
|
||||
pState->max_node_size = pNode->mem_size;
|
||||
if (pNode->mem_size < pState->min_node_size)
|
||||
pState->min_node_size = pNode->mem_size;
|
||||
}
|
||||
MMHEAP_UNLOCK();
|
||||
}
|
||||
/**
|
||||
* @brief bflb_mmheap_align_alloc
|
||||
*
|
||||
* @param pRoot
|
||||
* @param align_size
|
||||
* @param want_size
|
||||
* @return void*
|
||||
*/
|
||||
void *bflb_mmheap_align_alloc(struct heap_info *pRoot, size_t align_size, size_t want_size)
|
||||
{
|
||||
void *pReturn = NULL;
|
||||
struct heap_node *pPriv_Node, *pNow_Node;
|
||||
|
||||
MMHEAP_ASSERT(pRoot->pStart != NULL);
|
||||
MMHEAP_ASSERT(pRoot->pEnd != NULL);
|
||||
|
||||
if (want_size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((want_size & MEM_MANAGE_ALLOCA_LABAL) != 0) {
|
||||
MMHEAP_MALLOC_FAIL();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (align_size & (align_size - 1)) {
|
||||
MMHEAP_MALLOC_FAIL();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MMHEAP_LOCK();
|
||||
if (want_size < MEM_MANAGE_MINUM_MEM_SIZE)
|
||||
want_size = MEM_MANAGE_MINUM_MEM_SIZE;
|
||||
if (align_size < MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT)
|
||||
align_size = MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT;
|
||||
|
||||
want_size = mmheap_align_up(want_size, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);
|
||||
|
||||
pPriv_Node = pRoot->pStart;
|
||||
pNow_Node = pRoot->pStart->next_node;
|
||||
|
||||
while (pNow_Node->next_node != NULL) {
|
||||
if (pNow_Node->mem_size >= want_size + MEM_MANAGE_MEM_STRUCT_SIZE) {
|
||||
size_t use_align_size;
|
||||
size_t new_size;
|
||||
pReturn = (void *)mmheap_align_up((size_t)mmheap_addr_add(pNow_Node), align_size); /*Calculate the aligned address*/
|
||||
use_align_size = (uint8_t *)pReturn - (uint8_t *)mmheap_addr_add(pNow_Node); /*Calculate the memory consumed by the alignment*/
|
||||
if (use_align_size != 0) { /*if Memory misalignment*/
|
||||
if (use_align_size < MEM_MANAGE_MINUM_MEM_SIZE + MEM_MANAGE_MEM_STRUCT_SIZE) { /*The unaligned value is too small*/
|
||||
pReturn = (void *)mmheap_align_up(
|
||||
(size_t)mmheap_addr_add(pNow_Node) + MEM_MANAGE_MINUM_MEM_SIZE + MEM_MANAGE_MEM_STRUCT_SIZE, align_size);
|
||||
use_align_size = (uint8_t *)pReturn - (uint8_t *)mmheap_addr_add(pNow_Node);
|
||||
}
|
||||
if (use_align_size <= pNow_Node->mem_size) {
|
||||
new_size = pNow_Node->mem_size - use_align_size; /*Calculate the remaining memory size by removing the memory consumed by alignment*/
|
||||
if (new_size >= want_size) { /*Meet the conditions for distribution*/
|
||||
struct heap_node *pNew_Node = mmheap_addr_sub(pReturn);
|
||||
pNow_Node->mem_size -= new_size + MEM_MANAGE_MEM_STRUCT_SIZE; /*Split Node*/
|
||||
pNew_Node->mem_size = new_size; /*The new node is also not in the free chain and does not need to be discharged from the free chain*/
|
||||
pNew_Node->next_node = NULL;
|
||||
pNow_Node = pNew_Node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else { /*Memory is directly aligned*/
|
||||
pPriv_Node->next_node = pNow_Node->next_node;
|
||||
pNow_Node->next_node = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pPriv_Node = pNow_Node;
|
||||
pNow_Node = pNow_Node->next_node;
|
||||
}
|
||||
|
||||
if (pNow_Node == pRoot->pEnd) {
|
||||
MMHEAP_UNLOCK();
|
||||
MMHEAP_MALLOC_FAIL();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pNow_Node->mem_size >= MEM_MANAGE_MINUM_MEM_SIZE + MEM_MANAGE_MEM_STRUCT_SIZE + want_size) { /*Node memory is still available*/
|
||||
struct heap_node *pNew_Node = (struct heap_node *)((uint8_t *)mmheap_addr_add(pNow_Node) + want_size); /*Calculate the address of the node that will be moved into the free chain table*/
|
||||
pNew_Node->mem_size = pNow_Node->mem_size - want_size - MEM_MANAGE_MEM_STRUCT_SIZE;
|
||||
pNew_Node->next_node = NULL;
|
||||
pNow_Node->mem_size = want_size;
|
||||
mmheap_insert_node_to_freelist(pRoot, pNew_Node);
|
||||
}
|
||||
pNow_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL;
|
||||
MMHEAP_UNLOCK();
|
||||
return pReturn;
|
||||
}
|
||||
/**
|
||||
* @brief bflb_mmheap_alloc
|
||||
*
|
||||
* @param pRoot
|
||||
* @param want_size
|
||||
* @return void*
|
||||
*/
|
||||
void *bflb_mmheap_alloc(struct heap_info *pRoot, size_t want_size)
|
||||
{
|
||||
return bflb_mmheap_align_alloc(pRoot, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT, want_size);
|
||||
}
|
||||
/**
|
||||
* @brief bflb_mmheap_realloc
|
||||
*
|
||||
* @param pRoot
|
||||
* @param src_addr
|
||||
* @param want_size
|
||||
* @return void*
|
||||
*/
|
||||
void *bflb_mmheap_realloc(struct heap_info *pRoot, void *src_addr, size_t want_size)
|
||||
{
|
||||
void *pReturn = NULL;
|
||||
struct heap_node *pNext_Node, *pPriv_Node;
|
||||
struct heap_node *pSrc_Node;
|
||||
MMHEAP_ASSERT(pRoot->pStart != NULL);
|
||||
MMHEAP_ASSERT(pRoot->pEnd != NULL);
|
||||
if (src_addr == NULL) {
|
||||
return bflb_mmheap_align_alloc(pRoot, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT, want_size);
|
||||
}
|
||||
if (want_size == 0) {
|
||||
bflb_mmheap_free(pRoot, src_addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MMHEAP_LOCK();
|
||||
if ((want_size & MEM_MANAGE_ALLOCA_LABAL) != 0) {
|
||||
MMHEAP_UNLOCK();
|
||||
MMHEAP_MALLOC_FAIL();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pSrc_Node = mmheap_addr_sub(src_addr);
|
||||
|
||||
if ((pSrc_Node->mem_size & MEM_MANAGE_ALLOCA_LABAL) == 0) {
|
||||
MMHEAP_UNLOCK();
|
||||
MMHEAP_ASSERT((pSrc_Node->mem_size & MEM_MANAGE_ALLOCA_LABAL) != 0);
|
||||
MMHEAP_MALLOC_FAIL();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pSrc_Node->mem_size &= ~MEM_MANAGE_ALLOCA_LABAL;
|
||||
if (pSrc_Node->mem_size >= want_size) {
|
||||
pSrc_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL;
|
||||
pReturn = src_addr;
|
||||
MMHEAP_UNLOCK();
|
||||
return pReturn;
|
||||
}
|
||||
/*Start looking in the free list for blocks similar to this block*/
|
||||
for (pPriv_Node = pRoot->pStart; pPriv_Node->next_node < pSrc_Node; pPriv_Node = pPriv_Node->next_node) {
|
||||
}
|
||||
pNext_Node = pPriv_Node->next_node;
|
||||
|
||||
if (pNext_Node != pRoot->pEnd &&
|
||||
((uint8_t *)src_addr + pSrc_Node->mem_size == (uint8_t *)pNext_Node) &&
|
||||
(pSrc_Node->mem_size + pNext_Node->mem_size + MEM_MANAGE_MEM_STRUCT_SIZE >= want_size)) {
|
||||
/*Meet next node non-end, memory contiguous, enough memory left*/
|
||||
pReturn = src_addr;
|
||||
pPriv_Node->next_node = pNext_Node->next_node;
|
||||
pSrc_Node->mem_size += MEM_MANAGE_MEM_STRUCT_SIZE + pNext_Node->mem_size;
|
||||
want_size = mmheap_align_up(want_size, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);
|
||||
if (pSrc_Node->mem_size >= MEM_MANAGE_MINUM_MEM_SIZE + MEM_MANAGE_MEM_STRUCT_SIZE + want_size) { /*Removing the remaining space allocated is enough to open new blocks*/
|
||||
struct heap_node *pNew_Node = (struct heap_node *)((uint8_t *)mmheap_addr_add(pSrc_Node) + want_size);
|
||||
pNew_Node->next_node = NULL;
|
||||
pNew_Node->mem_size = pSrc_Node->mem_size - want_size - MEM_MANAGE_MEM_STRUCT_SIZE;
|
||||
pSrc_Node->mem_size = want_size;
|
||||
mmheap_insert_node_to_freelist(pRoot, pNew_Node);
|
||||
}
|
||||
pSrc_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL;
|
||||
MMHEAP_UNLOCK();
|
||||
} else {
|
||||
MMHEAP_UNLOCK();
|
||||
pReturn = bflb_mmheap_align_alloc(pRoot, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT, want_size);
|
||||
if (pReturn == NULL) {
|
||||
pSrc_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL;
|
||||
MMHEAP_MALLOC_FAIL();
|
||||
return NULL;
|
||||
}
|
||||
MMHEAP_LOCK();
|
||||
memcpy(pReturn, src_addr, pSrc_Node->mem_size);
|
||||
pSrc_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL;
|
||||
MMHEAP_UNLOCK();
|
||||
bflb_mmheap_free(pRoot, src_addr);
|
||||
}
|
||||
return pReturn;
|
||||
}
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param pRoot
|
||||
* @param num
|
||||
* @param size
|
||||
* @return void*
|
||||
*/
|
||||
void *bflb_mmheap_calloc(struct heap_info *pRoot, size_t num, size_t size)
|
||||
{
|
||||
void *pReturn = NULL;
|
||||
|
||||
pReturn = (void *)bflb_mmheap_alloc(pRoot, size * num);
|
||||
|
||||
if (pReturn) {
|
||||
memset(pReturn, 0, num * size);
|
||||
}
|
||||
|
||||
return pReturn;
|
||||
}
|
||||
/**
|
||||
* @brief bflb_mmheap_free
|
||||
*
|
||||
* @param pRoot
|
||||
* @param addr
|
||||
*/
|
||||
void bflb_mmheap_free(struct heap_info *pRoot, void *addr)
|
||||
{
|
||||
struct heap_node *pFree_Node;
|
||||
MMHEAP_ASSERT(pRoot->pStart != NULL);
|
||||
MMHEAP_ASSERT(pRoot->pEnd != NULL);
|
||||
MMHEAP_LOCK();
|
||||
if (addr == NULL) {
|
||||
MMHEAP_UNLOCK();
|
||||
return;
|
||||
}
|
||||
pFree_Node = mmheap_addr_sub(addr);
|
||||
|
||||
if ((pFree_Node->mem_size & MEM_MANAGE_ALLOCA_LABAL) == 0) {
|
||||
MMHEAP_UNLOCK();
|
||||
MMHEAP_ASSERT((pFree_Node->mem_size & MEM_MANAGE_ALLOCA_LABAL) != 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pFree_Node->next_node != NULL) {
|
||||
MMHEAP_UNLOCK();
|
||||
MMHEAP_ASSERT(pFree_Node->next_node == NULL);
|
||||
return;
|
||||
}
|
||||
pFree_Node->mem_size &= ~MEM_MANAGE_ALLOCA_LABAL;
|
||||
mmheap_insert_node_to_freelist(pRoot, pFree_Node);
|
||||
MMHEAP_UNLOCK();
|
||||
}
|
||||
/**
|
||||
* @brief bflb_mmheap_init
|
||||
*
|
||||
* @param pRoot
|
||||
* @param pRegion
|
||||
*/
|
||||
void bflb_mmheap_init(struct heap_info *pRoot, const struct heap_region *pRegion)
|
||||
{
|
||||
struct heap_node *align_addr;
|
||||
size_t align_size;
|
||||
struct heap_node *pPriv_node = NULL;
|
||||
|
||||
pRoot->total_size = 0;
|
||||
pRoot->pEnd = NULL;
|
||||
pRoot->pStart = NULL;
|
||||
|
||||
for (; pRegion->addr != NULL; pRegion++) {
|
||||
align_addr = (struct heap_node *)mmheap_align_up((size_t)pRegion->addr, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT); /*Calculate the aligned address*/
|
||||
if ((uint8_t *)align_addr > pRegion->mem_size + (uint8_t *)pRegion->addr) /*Alignment consumes more memory than the memory area*/
|
||||
continue;
|
||||
align_size = pRegion->mem_size - ((uint8_t *)align_addr - (uint8_t *)pRegion->addr); /*Calculate the size of memory left after alignment*/
|
||||
if (align_size < MEM_MANAGE_MINUM_MEM_SIZE + MEM_MANAGE_MEM_STRUCT_SIZE) /*if Aligning the remaining memory is too small*/
|
||||
continue;
|
||||
align_size -= MEM_MANAGE_MEM_STRUCT_SIZE; /*Find the size of the memory block after removing the table header*/
|
||||
align_addr->mem_size = align_size;
|
||||
align_addr->next_node = NULL;
|
||||
if (pRoot->pStart == NULL) {
|
||||
pRoot->pStart = align_addr; /*set current addr for start*/
|
||||
if (align_size >= MEM_MANAGE_MINUM_MEM_SIZE + MEM_MANAGE_MEM_STRUCT_SIZE) { /*If the remaining blocks are large enough*/
|
||||
align_size -= MEM_MANAGE_MEM_STRUCT_SIZE; /*Remove the next block of table headers remaining memory size*/
|
||||
align_addr = (struct heap_node *)((uint8_t *)pRoot->pStart + MEM_MANAGE_MEM_STRUCT_SIZE); //the next block addr
|
||||
align_addr->mem_size = align_size;
|
||||
align_addr->next_node = NULL;
|
||||
pRoot->pStart->mem_size = 0;
|
||||
pRoot->pStart->next_node = align_addr;
|
||||
pRoot->total_size = align_addr->mem_size;
|
||||
} else { /*The memory is too small, and the address of the current memory block is recorded as start*/
|
||||
pRoot->total_size = 0;
|
||||
pRoot->pStart->mem_size = 0;
|
||||
}
|
||||
} else {
|
||||
pPriv_node->next_node = align_addr;
|
||||
pRoot->total_size += align_size;
|
||||
}
|
||||
pPriv_node = align_addr;
|
||||
}
|
||||
//At this point, pPriv_node is the last block, then place the end of the table at the end of the block, find the address to place the end block, end block is only convenient for traversal, so as small as possible, assigned to MEM_MANAGE_MEM_STRUCT_SIZE
|
||||
align_addr = (struct heap_node *)mmheap_align_down(
|
||||
(size_t)mmheap_addr_add(pPriv_node) + pPriv_node->mem_size - MEM_MANAGE_MEM_STRUCT_SIZE, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);
|
||||
align_size = (uint8_t *)align_addr - (uint8_t *)mmheap_addr_add(pPriv_node); /*Find the remaining size of the previous block after the end block is allocated*/
|
||||
if (align_size >= MEM_MANAGE_MINUM_MEM_SIZE) {
|
||||
pRoot->total_size -= pPriv_node->mem_size - align_size; /*Removing memory consumed by allocating end blocks*/
|
||||
pRoot->pEnd = align_addr; /*Update the address at the end of the list*/
|
||||
pPriv_node->next_node = align_addr;
|
||||
pPriv_node->mem_size = align_size;
|
||||
align_addr->next_node = NULL;
|
||||
align_addr->mem_size = 0; /*The end block is not involved in memory allocation, so a direct 0 is sufficient*/
|
||||
} else { /*The last block is too small, directly as the end block*/
|
||||
pRoot->pEnd = pPriv_node;
|
||||
pRoot->total_size -= pPriv_node->mem_size;
|
||||
}
|
||||
MMHEAP_ASSERT(pRoot->pStart != NULL);
|
||||
MMHEAP_ASSERT(pRoot->pEnd != NULL);
|
||||
}
|
163
components/utils/mmheap/bflb_mmheap.h
Normal file
163
components/utils/mmheap/bflb_mmheap.h
Normal file
|
@ -0,0 +1,163 @@
|
|||
/**
|
||||
* @file bflb_mmheap.h
|
||||
* @brief
|
||||
*
|
||||
* Copyright (c) 2021 Bouffalolab team
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
#ifndef __BFLB_MMHEAP_H
|
||||
#define __BFLB_MMHEAP_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef CONFIG_MMHEAP_USER
|
||||
#include "mmheap_user.h"
|
||||
#endif
|
||||
|
||||
#ifndef MMHEAP_LOCK
|
||||
#define MMHEAP_LOCK()
|
||||
#endif
|
||||
|
||||
#ifndef MMHEAP_UNLOCK
|
||||
#define MMHEAP_UNLOCK()
|
||||
#endif
|
||||
|
||||
#ifndef MMHEAP_ASSERT
|
||||
#define MMHEAP_ASSERT(A) \
|
||||
if (!(A)) \
|
||||
printf("mmheap malloc error:drv_mmheap,%d\r\n", __LINE__)
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef MMHEAP_MALLOC_FAIL
|
||||
#define MMHEAP_MALLOC_FAIL() printf("mmheap malloc fail:drv_mmheap,%d\r\n", __LINE__)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct heap_region {
|
||||
void *addr;
|
||||
size_t mem_size;
|
||||
};
|
||||
|
||||
struct heap_node {
|
||||
struct heap_node *next_node;
|
||||
size_t mem_size;
|
||||
};
|
||||
|
||||
struct heap_info {
|
||||
struct heap_node *pStart;
|
||||
struct heap_node *pEnd;
|
||||
size_t total_size;
|
||||
};
|
||||
|
||||
struct heap_state {
|
||||
size_t remain_size;
|
||||
size_t free_node_num;
|
||||
size_t max_node_size;
|
||||
size_t min_node_size;
|
||||
};
|
||||
|
||||
void bflb_mmheap_init(struct heap_info *pRoot, const struct heap_region *pRigon);
|
||||
/**
|
||||
* @brief Alloc start address aligned memory from the heap.
|
||||
* Alloc aligned address and specified size memory from the heap.
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] pRoot heap info.
|
||||
* @param[in] align_size address align mask of the memory.
|
||||
* @param[in] want_size size of the memory.
|
||||
*
|
||||
* @return the pointer to the allocated memory.
|
||||
*/
|
||||
void *bflb_mmheap_align_alloc(struct heap_info *pRoot, size_t align_size, size_t want_size);
|
||||
/**
|
||||
* @brief Alloc memory.
|
||||
* Allocate size bytes and returns a pointer to the allocated memory.
|
||||
*
|
||||
* @attention size should no bigger than MMHEAP_BLK_SIZE_MAX.
|
||||
*
|
||||
* @param[in] pRoot heap info.
|
||||
* @param[in] want_size size of the memory.
|
||||
*
|
||||
* @return the pointer to the allocated memory.
|
||||
*/
|
||||
void *bflb_mmheap_alloc(struct heap_info *pRoot, size_t want_size);
|
||||
/**
|
||||
* @brief Realloc memory from the heap.
|
||||
* Change the size of the memory block pointed to by ptr to size bytes.
|
||||
*
|
||||
* @attention
|
||||
* <ul>
|
||||
* <li> if ptr is NULL, then the call is equivalent to mmheap_alloc(size), for all values of size.
|
||||
* <li> if ptr is if size is equal to zero, and ptr is not NULL, then the call is equivalent to mmheap_free(ptr).
|
||||
* </ul>
|
||||
*
|
||||
* @param[in] pRoot heap info.
|
||||
* @param[in] src_addr old pointer to the memory space.
|
||||
* @param[in] want_size new size of the memory space.
|
||||
*
|
||||
* @return the new pointer to the allocated memory.
|
||||
*/
|
||||
void *bflb_mmheap_realloc(struct heap_info *pRoot, void *src_addr, size_t want_size);
|
||||
/**
|
||||
* @brief Cealloc memory from the heap.
|
||||
* Change the size of the memory block pointed to by ptr to size bytes.
|
||||
*
|
||||
* @attention
|
||||
* <ul>
|
||||
* <li> if ptr is NULL, then the call is equivalent to mmheap_alloc(size), for all values of size.
|
||||
* <li> if ptr is if size is equal to zero, and ptr is not NULL, then the call is equivalent to mmheap_free(ptr).
|
||||
* </ul>
|
||||
*
|
||||
* @param[in] pRoot heap info.
|
||||
* @param[in] num size number.
|
||||
* @param[in] size new size of the memory space.
|
||||
*
|
||||
* @return the new pointer to the allocated memory.
|
||||
*/
|
||||
void *bflb_mmheap_calloc(struct heap_info *pRoot, size_t num, size_t size);
|
||||
/**
|
||||
* @brief Free the memory.
|
||||
* Free the memory space pointed to by ptr, which must have been returned by a previous call to mmheap_alloc(), mmheap_aligned_alloc(), or mmheap_realloc().
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] pRoot heap info.
|
||||
* @param[in] addr pointer to the memory.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void bflb_mmheap_free(struct heap_info *pRoot, void *addr);
|
||||
/**
|
||||
* @brief get mmheap state
|
||||
*
|
||||
* @param pRoot heap info.
|
||||
* @param pState heap state
|
||||
*/
|
||||
void bflb_mmheap_get_state(struct heap_info *pRoot, struct heap_state *pState);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
675
components/utils/ring_buffer/ring_buffer.c
Normal file
675
components/utils/ring_buffer/ring_buffer.c
Normal file
|
@ -0,0 +1,675 @@
|
|||
/**
|
||||
* @file ring_buffer.c
|
||||
* @brief
|
||||
*
|
||||
* Copyright (c) 2021 Bouffalolab team
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
#include "ring_buffer.h"
|
||||
|
||||
/** @addtogroup BL_Common_Component
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup RING_BUFFER
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup RING_BUFFER_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*@} end of group RING_BUFFER_Private_Macros */
|
||||
|
||||
/** @defgroup RING_BUFFER_Private_Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*@} end of group RING_BUFFER_Private_Types */
|
||||
|
||||
/** @defgroup RING_BUFFER_Private_Fun_Declaration
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*@} end of group RING_BUFFER_Private_Fun_Declaration */
|
||||
|
||||
/** @defgroup RING_BUFFER_Private_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*@} end of group RING_BUFFER_Private_Variables */
|
||||
|
||||
/** @defgroup RING_BUFFER_Global_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*@} end of group RING_BUFFER_Global_Variables */
|
||||
|
||||
/** @defgroup RING_BUFFER_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*@} end of group RING_BUFFER_Private_Functions */
|
||||
|
||||
/** @defgroup RING_BUFFER_Public_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief Ring buffer init function
|
||||
*
|
||||
* @param rbType: Ring buffer type structure pointer
|
||||
* @param buffer: Pointer of ring buffer
|
||||
* @param size: Size of ring buffer
|
||||
* @param lockCb: Ring buffer lock callback function pointer
|
||||
* @param unlockCb: Ring buffer unlock callback function pointer
|
||||
*
|
||||
* @return SUCCESS
|
||||
*
|
||||
*******************************************************************************/
|
||||
void Ring_Buffer_Init(Ring_Buffer_Type *rbType, uint8_t *buffer, uint32_t size, ringBuffer_Lock_Callback *lockCb, ringBuffer_Lock_Callback *unlockCb)
|
||||
{
|
||||
/* Init ring buffer pointer */
|
||||
rbType->pointer = buffer;
|
||||
|
||||
/* Init read/write mirror and index */
|
||||
rbType->readMirror = 0;
|
||||
rbType->readIndex = 0;
|
||||
rbType->writeMirror = 0;
|
||||
rbType->writeIndex = 0;
|
||||
|
||||
/* Set ring buffer size */
|
||||
rbType->size = size;
|
||||
|
||||
/* Set lock and unlock callback function */
|
||||
rbType->lock = lockCb;
|
||||
rbType->unlock = unlockCb;
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief Ring buffer reset function
|
||||
*
|
||||
* @param rbType: Ring buffer type structure pointer
|
||||
*
|
||||
* @return SUCCESS
|
||||
*
|
||||
*******************************************************************************/
|
||||
void Ring_Buffer_Reset(Ring_Buffer_Type *rbType)
|
||||
{
|
||||
if (rbType->lock != NULL) {
|
||||
rbType->lock();
|
||||
}
|
||||
|
||||
/* Clear read/write mirror and index */
|
||||
rbType->readMirror = 0;
|
||||
rbType->readIndex = 0;
|
||||
rbType->writeMirror = 0;
|
||||
rbType->writeIndex = 0;
|
||||
|
||||
if (rbType->unlock != NULL) {
|
||||
rbType->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief Use callback function to write ring buffer function
|
||||
*
|
||||
* @param rbType: Ring buffer type structure pointer
|
||||
* @param length: Length of data want to write
|
||||
* @param writeCb: Callback function pointer
|
||||
* @param parameter: Parameter that callback function may use
|
||||
*
|
||||
* @return Length of data actually write
|
||||
*
|
||||
*******************************************************************************/
|
||||
uint32_t Ring_Buffer_Write_Callback(Ring_Buffer_Type *rbType, uint32_t length, ringBuffer_Write_Callback *writeCb, void *parameter)
|
||||
{
|
||||
uint32_t sizeRemained = Ring_Buffer_Get_Empty_Length(rbType);
|
||||
|
||||
if (writeCb == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rbType->lock != NULL) {
|
||||
rbType->lock();
|
||||
}
|
||||
|
||||
/* Ring buffer has no space for new data */
|
||||
if (sizeRemained == 0) {
|
||||
if (rbType->unlock != NULL) {
|
||||
rbType->unlock();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Drop part of data when length out of space remained */
|
||||
if (length > sizeRemained) {
|
||||
length = sizeRemained;
|
||||
}
|
||||
|
||||
/* Get size of space remained in current mirror */
|
||||
sizeRemained = rbType->size - rbType->writeIndex;
|
||||
|
||||
if (sizeRemained > length) {
|
||||
/* Space remained is enough for data in current mirror */
|
||||
writeCb(parameter, &rbType->pointer[rbType->writeIndex], length);
|
||||
rbType->writeIndex += length;
|
||||
} else {
|
||||
/* Data is divided to two parts with different mirror */
|
||||
writeCb(parameter, &rbType->pointer[rbType->writeIndex], sizeRemained);
|
||||
writeCb(parameter, &rbType->pointer[0], length - sizeRemained);
|
||||
rbType->writeIndex = length - sizeRemained;
|
||||
rbType->writeMirror = ~rbType->writeMirror;
|
||||
}
|
||||
|
||||
if (rbType->unlock != NULL) {
|
||||
rbType->unlock();
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief Copy data from data buffer to ring buffer function
|
||||
*
|
||||
* @param parameter: Pointer to source pointer
|
||||
* @param dest: Ring buffer to write
|
||||
* @param length: Length of data to write
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
static void Ring_Buffer_Write_Copy(void *parameter, uint8_t *dest, uint32_t length)
|
||||
{
|
||||
uint8_t **src = (uint8_t **)parameter;
|
||||
|
||||
arch_memcpy_fast(dest, *src, length);
|
||||
*src += length;
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief Write ring buffer function
|
||||
*
|
||||
* @param rbType: Ring buffer type structure pointer
|
||||
* @param data: Data to write
|
||||
* @param length: Length of data
|
||||
*
|
||||
* @return Length of data writted actually
|
||||
*
|
||||
*******************************************************************************/
|
||||
uint32_t Ring_Buffer_Write(Ring_Buffer_Type *rbType, const uint8_t *data, uint32_t length)
|
||||
{
|
||||
return Ring_Buffer_Write_Callback(rbType, length, Ring_Buffer_Write_Copy, &data);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief Write 1 byte to ring buffer function
|
||||
*
|
||||
* @param rbType: Ring buffer type structure pointer
|
||||
* @param data: Data to write
|
||||
*
|
||||
* @return Length of data writted actually
|
||||
*
|
||||
*******************************************************************************/
|
||||
uint32_t Ring_Buffer_Write_Byte(Ring_Buffer_Type *rbType, const uint8_t data)
|
||||
{
|
||||
if (rbType->lock != NULL) {
|
||||
rbType->lock();
|
||||
}
|
||||
|
||||
/* Ring buffer has no space for new data */
|
||||
if (!Ring_Buffer_Get_Empty_Length(rbType)) {
|
||||
if (rbType->unlock != NULL) {
|
||||
rbType->unlock();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
rbType->pointer[rbType->writeIndex] = data;
|
||||
|
||||
/* Judge to change index and mirror */
|
||||
if (rbType->writeIndex != (rbType->size - 1)) {
|
||||
rbType->writeIndex++;
|
||||
} else {
|
||||
rbType->writeIndex = 0;
|
||||
rbType->writeMirror = ~rbType->writeMirror;
|
||||
}
|
||||
|
||||
if (rbType->unlock != NULL) {
|
||||
rbType->unlock();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief Write ring buffer function, old data will be covered by new data when ring buffer is
|
||||
* full
|
||||
*
|
||||
* @param rbType: Ring buffer type structure pointer
|
||||
* @param data: Data to write
|
||||
* @param length: Length of data
|
||||
*
|
||||
* @return Length of data writted actually
|
||||
*
|
||||
*******************************************************************************/
|
||||
uint32_t Ring_Buffer_Write_Force(Ring_Buffer_Type *rbType, const uint8_t *data, uint32_t length)
|
||||
{
|
||||
uint32_t sizeRemained = Ring_Buffer_Get_Empty_Length(rbType);
|
||||
uint32_t indexRemained = rbType->size - rbType->writeIndex;
|
||||
|
||||
if (rbType->lock != NULL) {
|
||||
rbType->lock();
|
||||
}
|
||||
|
||||
/* Drop extra data when data length is large than size of ring buffer */
|
||||
if (length > rbType->size) {
|
||||
data = &data[length - rbType->size];
|
||||
length = rbType->size;
|
||||
}
|
||||
|
||||
if (indexRemained > length) {
|
||||
/* Space remained is enough for data in current mirror */
|
||||
arch_memcpy_fast(&rbType->pointer[rbType->writeIndex], data, length);
|
||||
rbType->writeIndex += length;
|
||||
|
||||
/* Update read index */
|
||||
if (length > sizeRemained) {
|
||||
rbType->readIndex = rbType->writeIndex;
|
||||
}
|
||||
} else {
|
||||
/* Data is divided to two parts with different mirror */
|
||||
arch_memcpy_fast(&rbType->pointer[rbType->writeIndex], data, indexRemained);
|
||||
arch_memcpy_fast(&rbType->pointer[0], &data[indexRemained], length - indexRemained);
|
||||
rbType->writeIndex = length - indexRemained;
|
||||
rbType->writeMirror = ~rbType->writeMirror;
|
||||
|
||||
/* Update read index and mirror */
|
||||
if (length > sizeRemained) {
|
||||
rbType->readIndex = rbType->writeIndex;
|
||||
rbType->readMirror = ~rbType->readMirror;
|
||||
}
|
||||
}
|
||||
|
||||
if (rbType->unlock != NULL) {
|
||||
rbType->unlock();
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief Write 1 byte to ring buffer function, old data will be covered by new data when ring
|
||||
* buffer is full
|
||||
*
|
||||
* @param rbType: Ring buffer type structure pointer
|
||||
* @param data: Data to write
|
||||
*
|
||||
* @return Length of data writted actually
|
||||
*
|
||||
*******************************************************************************/
|
||||
uint32_t Ring_Buffer_Write_Byte_Force(Ring_Buffer_Type *rbType, const uint8_t data)
|
||||
{
|
||||
Ring_Buffer_Status_Type status = Ring_Buffer_Get_Status(rbType);
|
||||
|
||||
if (rbType->lock != NULL) {
|
||||
rbType->lock();
|
||||
}
|
||||
|
||||
rbType->pointer[rbType->writeIndex] = data;
|
||||
|
||||
/* Judge to change index and mirror */
|
||||
if (rbType->writeIndex == rbType->size - 1) {
|
||||
rbType->writeIndex = 0;
|
||||
rbType->writeMirror = ~rbType->writeMirror;
|
||||
|
||||
/* Update read index and mirror */
|
||||
if (status == RING_BUFFER_FULL) {
|
||||
rbType->readIndex = rbType->writeIndex;
|
||||
rbType->readMirror = ~rbType->readMirror;
|
||||
}
|
||||
} else {
|
||||
rbType->writeIndex++;
|
||||
|
||||
/* Update read index */
|
||||
if (status == RING_BUFFER_FULL) {
|
||||
rbType->readIndex = rbType->writeIndex;
|
||||
}
|
||||
}
|
||||
|
||||
if (rbType->unlock != NULL) {
|
||||
rbType->unlock();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief Use callback function to read ring buffer function
|
||||
*
|
||||
* @param rbType: Ring buffer type structure pointer
|
||||
* @param length: Length of data want to read
|
||||
* @param readCb: Callback function pointer
|
||||
* @param parameter: Parameter that callback function may use
|
||||
*
|
||||
* @return Length of data actually read
|
||||
*
|
||||
*******************************************************************************/
|
||||
uint32_t Ring_Buffer_Read_Callback(Ring_Buffer_Type *rbType, uint32_t length, ringBuffer_Read_Callback *readCb, void *parameter)
|
||||
{
|
||||
uint32_t size = Ring_Buffer_Get_Length(rbType);
|
||||
|
||||
if (readCb == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rbType->lock != NULL) {
|
||||
rbType->lock();
|
||||
}
|
||||
|
||||
/* Ring buffer has no data */
|
||||
if (!size) {
|
||||
if (rbType->unlock != NULL) {
|
||||
rbType->unlock();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ring buffer do not have enough data */
|
||||
if (size < length) {
|
||||
length = size;
|
||||
}
|
||||
|
||||
/* Get size of space remained in current mirror */
|
||||
size = rbType->size - rbType->readIndex;
|
||||
|
||||
if (size > length) {
|
||||
/* Read all data needed */
|
||||
readCb(parameter, &rbType->pointer[rbType->readIndex], length);
|
||||
rbType->readIndex += length;
|
||||
} else {
|
||||
/* Read two part of data in different mirror */
|
||||
readCb(parameter, &rbType->pointer[rbType->readIndex], size);
|
||||
readCb(parameter, &rbType->pointer[0], length - size);
|
||||
rbType->readIndex = length - size;
|
||||
rbType->readMirror = ~rbType->readMirror;
|
||||
}
|
||||
|
||||
if (rbType->unlock != NULL) {
|
||||
rbType->unlock();
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief Copy data from ring buffer to data buffer function
|
||||
*
|
||||
* @param parameter: Pointer to destination pointer
|
||||
* @param data: Data buffer to copy
|
||||
* @param length: Length of data to copy
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
static void Ring_Buffer_Read_Copy(void *parameter, uint8_t *data, uint32_t length)
|
||||
{
|
||||
uint8_t **dest = (uint8_t **)parameter;
|
||||
|
||||
arch_memcpy_fast(*dest, data, length);
|
||||
*dest += length;
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief Read ring buffer function
|
||||
*
|
||||
* @param rbType: Ring buffer type structure pointer
|
||||
* @param data: Buffer for data read
|
||||
* @param length: Length of data to read
|
||||
*
|
||||
* @return Length of data read actually
|
||||
*
|
||||
*******************************************************************************/
|
||||
uint32_t Ring_Buffer_Read(Ring_Buffer_Type *rbType, uint8_t *data, uint32_t length)
|
||||
{
|
||||
return Ring_Buffer_Read_Callback(rbType, length, Ring_Buffer_Read_Copy, &data);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief Read 1 byte from ring buffer function
|
||||
*
|
||||
* @param rbType: Ring buffer type structure pointer
|
||||
* @param data: Data read
|
||||
*
|
||||
* @return Length of data actually read
|
||||
*
|
||||
*******************************************************************************/
|
||||
uint32_t Ring_Buffer_Read_Byte(Ring_Buffer_Type *rbType, uint8_t *data)
|
||||
{
|
||||
if (rbType->lock != NULL) {
|
||||
rbType->lock();
|
||||
}
|
||||
|
||||
/* Ring buffer has no data */
|
||||
if (!Ring_Buffer_Get_Length(rbType)) {
|
||||
if (rbType->unlock != NULL) {
|
||||
rbType->unlock();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read data */
|
||||
*data = rbType->pointer[rbType->readIndex];
|
||||
|
||||
/* Update read index and mirror */
|
||||
if (rbType->readIndex == rbType->size - 1) {
|
||||
rbType->readIndex = 0;
|
||||
rbType->readMirror = ~rbType->readMirror;
|
||||
} else {
|
||||
rbType->readIndex++;
|
||||
}
|
||||
|
||||
if (rbType->unlock != NULL) {
|
||||
rbType->unlock();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief Read ring buffer function, do not remove from buffer actually
|
||||
*
|
||||
* @param rbType: Ring buffer type structure pointer
|
||||
* @param data: Buffer for data read
|
||||
* @param length: Length of data to read
|
||||
*
|
||||
* @return Length of data read actually
|
||||
*
|
||||
*******************************************************************************/
|
||||
uint32_t Ring_Buffer_Peek(Ring_Buffer_Type *rbType, uint8_t *data, uint32_t length)
|
||||
{
|
||||
uint32_t size = Ring_Buffer_Get_Length(rbType);
|
||||
|
||||
if (rbType->lock != NULL) {
|
||||
rbType->lock();
|
||||
}
|
||||
|
||||
/* Ring buffer has no data */
|
||||
if (!size) {
|
||||
if (rbType->unlock != NULL) {
|
||||
rbType->unlock();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ring buffer do not have enough data */
|
||||
if (size < length) {
|
||||
length = size;
|
||||
}
|
||||
|
||||
/* Get size of space remained in current mirror */
|
||||
size = rbType->size - rbType->readIndex;
|
||||
|
||||
if (size > length) {
|
||||
/* Read all data needed */
|
||||
arch_memcpy_fast(data, &rbType->pointer[rbType->readIndex], length);
|
||||
} else {
|
||||
/* Read two part of data in different mirror */
|
||||
arch_memcpy_fast(data, &rbType->pointer[rbType->readIndex], size);
|
||||
arch_memcpy_fast(&data[size], &rbType->pointer[0], length - size);
|
||||
}
|
||||
|
||||
if (rbType->unlock != NULL) {
|
||||
rbType->unlock();
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief Read 1 byte from ring buffer function, do not remove from buffer actually
|
||||
*
|
||||
* @param rbType: Ring buffer type structure pointer
|
||||
* @param data: Data read
|
||||
*
|
||||
* @return Length of data actually read
|
||||
*
|
||||
*******************************************************************************/
|
||||
uint32_t Ring_Buffer_Peek_Byte(Ring_Buffer_Type *rbType, uint8_t *data)
|
||||
{
|
||||
if (rbType->lock != NULL) {
|
||||
rbType->lock();
|
||||
}
|
||||
|
||||
/* Ring buffer has no data */
|
||||
if (!Ring_Buffer_Get_Length(rbType)) {
|
||||
if (rbType->unlock != NULL) {
|
||||
rbType->unlock();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read data */
|
||||
*data = rbType->pointer[rbType->readIndex];
|
||||
|
||||
if (rbType->unlock != NULL) {
|
||||
rbType->unlock();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief Get length of data in ring buffer function
|
||||
*
|
||||
* @param rbType: Ring buffer type structure pointer
|
||||
*
|
||||
* @return Length of data
|
||||
*
|
||||
*******************************************************************************/
|
||||
uint32_t Ring_Buffer_Get_Length(Ring_Buffer_Type *rbType)
|
||||
{
|
||||
uint32_t readMirror = 0;
|
||||
uint32_t writeMirror = 0;
|
||||
uint32_t readIndex = 0;
|
||||
uint32_t writeIndex = 0;
|
||||
uint32_t size = 0;
|
||||
|
||||
if (rbType->lock != NULL) {
|
||||
rbType->lock();
|
||||
}
|
||||
|
||||
readMirror = rbType->readMirror;
|
||||
writeMirror = rbType->writeMirror;
|
||||
readIndex = rbType->readIndex;
|
||||
writeIndex = rbType->writeIndex;
|
||||
size = rbType->size;
|
||||
|
||||
if (rbType->unlock != NULL) {
|
||||
rbType->unlock();
|
||||
}
|
||||
|
||||
if (readMirror == writeMirror) {
|
||||
return writeIndex - readIndex;
|
||||
} else {
|
||||
return size - (readIndex - writeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief Get space remained in ring buffer function
|
||||
*
|
||||
* @param rbType: Ring buffer type structure pointer
|
||||
*
|
||||
* @return Length of space remained
|
||||
*
|
||||
*******************************************************************************/
|
||||
uint32_t Ring_Buffer_Get_Empty_Length(Ring_Buffer_Type *rbType)
|
||||
{
|
||||
return (rbType->size - Ring_Buffer_Get_Length(rbType));
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief Get ring buffer status function
|
||||
*
|
||||
* @param rbType: Ring buffer type structure pointer
|
||||
*
|
||||
* @return Status of ring buffer
|
||||
*
|
||||
*******************************************************************************/
|
||||
Ring_Buffer_Status_Type Ring_Buffer_Get_Status(Ring_Buffer_Type *rbType)
|
||||
{
|
||||
if (rbType->lock != NULL) {
|
||||
rbType->lock();
|
||||
}
|
||||
|
||||
/* Judge empty or full */
|
||||
if (rbType->readIndex == rbType->writeIndex) {
|
||||
if (rbType->readMirror == rbType->writeMirror) {
|
||||
if (rbType->unlock != NULL) {
|
||||
rbType->unlock();
|
||||
}
|
||||
|
||||
return RING_BUFFER_EMPTY;
|
||||
} else {
|
||||
if (rbType->unlock != NULL) {
|
||||
rbType->unlock();
|
||||
}
|
||||
|
||||
return RING_BUFFER_FULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (rbType->unlock != NULL) {
|
||||
rbType->unlock();
|
||||
}
|
||||
|
||||
return RING_BUFFER_PARTIAL;
|
||||
}
|
||||
|
||||
/*@} end of group RING_BUFFER_Public_Functions */
|
||||
|
||||
/*@} end of group RING_BUFFER */
|
||||
|
||||
/*@} end of group BL_Common_Component */
|
116
components/utils/ring_buffer/ring_buffer.h
Normal file
116
components/utils/ring_buffer/ring_buffer.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
/**
|
||||
* @file ring_buffer.h
|
||||
* @brief
|
||||
*
|
||||
* Copyright (c) 2021 Bouffalolab team
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
#ifndef __RING_BUFFER_H__
|
||||
#define __RING_BUFFER_H__
|
||||
|
||||
#include "bflb_core.h"
|
||||
|
||||
/** @addtogroup BL_Common_Component
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup RING_BUFFER
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup RING_BUFFER_Public_Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Ring buffer status type definition
|
||||
*/
|
||||
typedef enum {
|
||||
RING_BUFFER_EMPTY, /*!< Ring buffer is empty */
|
||||
RING_BUFFER_PARTIAL, /*!< Ring buffer has partial data */
|
||||
RING_BUFFER_FULL, /*!< Ring buffer is full */
|
||||
} Ring_Buffer_Status_Type;
|
||||
|
||||
/**
|
||||
* @brief Ring buffer structure definition
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *pointer; /*!< Pointer of ring buffer */
|
||||
uint8_t readMirror; /*!< Read mirror,used to judge empty or full */
|
||||
uint32_t readIndex; /*!< Index of read address */
|
||||
uint8_t writeMirror; /*!< Write mirror,used to judge empty or full */
|
||||
uint32_t writeIndex; /*!< Index of write address */
|
||||
uint32_t size; /*!< Size of ring buffer */
|
||||
void (*lock)(void); /*!< Lock ring buffer */
|
||||
void (*unlock)(void); /*!< Unlock ring buffer */
|
||||
} Ring_Buffer_Type;
|
||||
|
||||
/*@} end of group RING_BUFFER_Public_Types */
|
||||
|
||||
/** @defgroup RING_BUFFER_Public_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup RING_BUFFER_STATUS_TYPE
|
||||
* @{
|
||||
*/
|
||||
#define IS_RING_BUFFER_STATUS_TYPE(type) (((type) == RING_BUFFER_EMPTY) || \
|
||||
((type) == RING_BUFFER_PARTIAL) || \
|
||||
((type) == RING_BUFFER_FULL))
|
||||
|
||||
/*@} end of group RING_BUFFER_Public_Constants */
|
||||
|
||||
/** @defgroup RING_BUFFER_Public_Macros
|
||||
* @{
|
||||
*/
|
||||
typedef void(ringBuffer_Lock_Callback)(void);
|
||||
typedef void(ringBuffer_Read_Callback)(void *, uint8_t *, uint32_t);
|
||||
typedef void(ringBuffer_Write_Callback)(void *, uint8_t *, uint32_t);
|
||||
|
||||
/*@} end of group RING_BUFFER_Public_Macros */
|
||||
|
||||
/** @defgroup RING_BUFFER_Public_Functions
|
||||
* @{
|
||||
*/
|
||||
void Ring_Buffer_Init(Ring_Buffer_Type *rbType, uint8_t *buffer, uint32_t size, ringBuffer_Lock_Callback *lockCb,
|
||||
ringBuffer_Lock_Callback *unlockCb);
|
||||
void Ring_Buffer_Reset(Ring_Buffer_Type *rbType);
|
||||
uint32_t Ring_Buffer_Write_Callback(Ring_Buffer_Type *rbType, uint32_t length, ringBuffer_Write_Callback *writeCb,
|
||||
void *parameter);
|
||||
uint32_t Ring_Buffer_Write(Ring_Buffer_Type *rbType, const uint8_t *data, uint32_t length);
|
||||
uint32_t Ring_Buffer_Write_Byte(Ring_Buffer_Type *rbType, const uint8_t data);
|
||||
uint32_t Ring_Buffer_Write_Force(Ring_Buffer_Type *rbType, const uint8_t *data, uint32_t length);
|
||||
uint32_t Ring_Buffer_Write_Byte_Force(Ring_Buffer_Type *rbType, const uint8_t data);
|
||||
uint32_t Ring_Buffer_Read_Callback(Ring_Buffer_Type *rbType, uint32_t length, ringBuffer_Read_Callback *readCb,
|
||||
void *parameter);
|
||||
uint32_t Ring_Buffer_Read(Ring_Buffer_Type *rbType, uint8_t *data, uint32_t length);
|
||||
uint32_t Ring_Buffer_Read_Byte(Ring_Buffer_Type *rbType, uint8_t *data);
|
||||
uint32_t Ring_Buffer_Peek(Ring_Buffer_Type *rbType, uint8_t *data, uint32_t length);
|
||||
uint32_t Ring_Buffer_Peek_Byte(Ring_Buffer_Type *rbType, uint8_t *data);
|
||||
uint32_t Ring_Buffer_Get_Length(Ring_Buffer_Type *rbType);
|
||||
uint32_t Ring_Buffer_Get_Empty_Length(Ring_Buffer_Type *rbType);
|
||||
Ring_Buffer_Status_Type Ring_Buffer_Get_Status(Ring_Buffer_Type *rbType);
|
||||
|
||||
/*@} end of group RING_BUFFER_Public_Functions */
|
||||
|
||||
/*@} end of group RING_BUFFER */
|
||||
|
||||
/*@} end of group BL_Common_Component */
|
||||
|
||||
#endif /* __RING_BUFFER_H__ */
|
192
components/utils/soft_crc/soft_crc.c
Normal file
192
components/utils/soft_crc/soft_crc.c
Normal file
|
@ -0,0 +1,192 @@
|
|||
/**
|
||||
* @file softcrc.c
|
||||
* @brief
|
||||
*
|
||||
* Copyright (c) 2021 Bouffalolab team
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
#include "soft_crc.h"
|
||||
#include "bflb_core.h"
|
||||
|
||||
// ---------------- POPULAR POLYNOMIALS ----------------
|
||||
// CCITT: x^16 + x^12 + x^5 + x^0 (0x1021,init 0x0000)
|
||||
// CRC-16: x^16 + x^15 + x^2 + x^0 (0x8005,init 0xFFFF)
|
||||
// we use 0x8005 here and
|
||||
|
||||
const uint8_t chCRCHTalbe[] = {
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40
|
||||
};
|
||||
|
||||
const uint8_t chCRCLTalbe[] = {
|
||||
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
|
||||
0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
|
||||
0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
|
||||
0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
|
||||
0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
|
||||
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
|
||||
0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
|
||||
0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
|
||||
0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
|
||||
0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
|
||||
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
|
||||
0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
|
||||
0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,
|
||||
0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
|
||||
0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
|
||||
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
|
||||
0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
|
||||
0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
|
||||
0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
|
||||
0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
|
||||
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
|
||||
0x41, 0x81, 0x80, 0x40
|
||||
};
|
||||
|
||||
uint16_t bflb_soft_crc16(void *in, uint32_t len)
|
||||
{
|
||||
uint8_t chCRCHi = 0xFF;
|
||||
uint8_t chCRCLo = 0xFF;
|
||||
uint16_t wIndex;
|
||||
uint8_t *data = (uint8_t *)in;
|
||||
|
||||
while (len--) {
|
||||
wIndex = chCRCLo ^ *data++;
|
||||
chCRCLo = chCRCHi ^ chCRCHTalbe[wIndex];
|
||||
chCRCHi = chCRCLTalbe[wIndex];
|
||||
}
|
||||
|
||||
return ((chCRCHi << 8) | chCRCLo);
|
||||
}
|
||||
|
||||
/*
|
||||
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1
|
||||
*/
|
||||
const uint32_t crc32Tab[256] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
|
||||
uint32_t bflb_soft_crc32_table(void *in, uint32_t len)
|
||||
{
|
||||
uint32_t crc = 0;
|
||||
uint8_t *data = (uint8_t *)in;
|
||||
|
||||
crc = crc ^ 0xffffffff;
|
||||
|
||||
while (len--) {
|
||||
crc = crc32Tab[(crc ^ *data++) & 0xFF] ^ (crc >> 8);
|
||||
}
|
||||
|
||||
return crc ^ 0xffffffff;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Name: CRC-32 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
|
||||
* Poly: 0x4C11DB7
|
||||
* Init: 0xFFFFFFF
|
||||
* Refin: True
|
||||
* Refout: True
|
||||
* Xorout: 0xFFFFFFF
|
||||
* Alias: CRC_32/ADCCP
|
||||
* Use: WinRAR,ect.
|
||||
*****************************************************************************/
|
||||
uint32_t ATTR_TCM_SECTION bflb_soft_crc32_ex(uint32_t initial, void *in, uint32_t len)
|
||||
{
|
||||
uint8_t i;
|
||||
uint32_t crc = ~initial; // Initial value
|
||||
uint8_t *data = (uint8_t *)in;
|
||||
|
||||
while (len--) {
|
||||
crc ^= *data++; // crc ^= *data; data++;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
if (crc & 1) {
|
||||
crc = (crc >> 1) ^ 0xEDB88320; // 0xEDB88320= reverse 0x04C11DB7
|
||||
} else {
|
||||
crc = (crc >> 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
uint32_t ATTR_TCM_SECTION bflb_soft_crc32(void *in, uint32_t len)
|
||||
{
|
||||
return bflb_soft_crc32_ex(0, in, len);
|
||||
}
|
31
components/utils/soft_crc/soft_crc.h
Normal file
31
components/utils/soft_crc/soft_crc.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* @file softcrc.h
|
||||
* @brief
|
||||
*
|
||||
* Copyright (c) 2021 Bouffalolab team
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
#ifndef __SOFT_CRC_H__
|
||||
#define __SOFT_CRC_H__
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
uint16_t bflb_soft_crc16(void *in, uint32_t len);
|
||||
uint32_t bflb_soft_crc32(void *in, uint32_t len);
|
||||
|
||||
#endif
|
108
components/utils/vlibc/printf.c
Normal file
108
components/utils/vlibc/printf.c
Normal file
|
@ -0,0 +1,108 @@
|
|||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include "bflb_uart.h"
|
||||
#include "vlibc_stdio.h"
|
||||
|
||||
#define IOCONSOLE_IO ((uint32_t)0x00000001)
|
||||
#define IOCONSOLE_NAME "console"
|
||||
|
||||
struct bflb_device_s *console = NULL;
|
||||
|
||||
uint16_t __console_output(void *ptr, uint16_t size)
|
||||
{
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
bflb_uart_putchar(console, ((char *)ptr)[i]);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
__WEAK uint32_t __vlibc_io_init(const char *name, uint8_t mode)
|
||||
{
|
||||
(void)mode;
|
||||
if (strcmp(name, IOCONSOLE_NAME) == 0) {
|
||||
return IOCONSOLE_IO;
|
||||
} else {
|
||||
}
|
||||
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
__WEAK uint32_t __vlibc_io_deinit(struct __vlibc_io *io)
|
||||
{
|
||||
if (io->dev == IOCONSOLE_IO) {
|
||||
return IOCONSOLE_IO;
|
||||
} else {
|
||||
}
|
||||
|
||||
return EOF;
|
||||
}
|
||||
|
||||
__WEAK size_t __vlibc_io_mem2dev(struct __vlibc_io *io, const void *ptr, size_t size)
|
||||
{
|
||||
if (io->dev == IOCONSOLE_IO) {
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
bflb_uart_putchar(console, ((char *)ptr)[i]);
|
||||
}
|
||||
return size;
|
||||
} else {
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
|
||||
void bflb_dump_hex(const void *ptr, uint32_t buflen)
|
||||
{
|
||||
unsigned char *buf = (unsigned char *)ptr;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < buflen; i += 16) {
|
||||
printf("%08X:", i);
|
||||
|
||||
for (j = 0; j < 16; j++)
|
||||
if (i + j < buflen) {
|
||||
if ((j % 8) == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
printf("%02X ", buf[i + j]);
|
||||
} else
|
||||
printf(" ");
|
||||
printf(" ");
|
||||
|
||||
for (j = 0; j < 16; j++)
|
||||
if (i + j < buflen)
|
||||
printf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void bflb_reg_dump(uint32_t addr)
|
||||
{
|
||||
printf("%08lx[31:0]=%08lx\r\n", addr, *(volatile uint32_t *)(uintptr_t)(addr));
|
||||
}
|
||||
|
||||
int bflb_data_compare(const uint8_t *expected, uint8_t *input, uint32_t len)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (input[i] != expected[i]) {
|
||||
printf("Compare fail at %d,input %02x, but expect %02x\r\n", i, input[i], expected[i]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bflb_uart_set_console(struct bflb_device_s *dev)
|
||||
{
|
||||
console = dev;
|
||||
bflb_uart_putchar(console, '\r');
|
||||
vlibc_stdout = vlibc_fopen("<" IOCONSOLE_NAME, "w");
|
||||
vlibc_setvbuf(vlibc_stdout, NULL, _IONBF, 0);
|
||||
vlibc_stderr = vlibc_stdout;
|
||||
|
||||
extern void log_init(void);
|
||||
log_init();
|
||||
}
|
279
components/utils/vlibc/syscalls.c
Normal file
279
components/utils/vlibc/syscalls.c
Normal file
|
@ -0,0 +1,279 @@
|
|||
#include <reent.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include "bflb_uart.h"
|
||||
#ifdef CONFIG_TLSF
|
||||
#include "bflb_tlsf.h"
|
||||
#else
|
||||
#include "bflb_mmheap.h"
|
||||
|
||||
extern struct heap_info mmheap_root;
|
||||
#endif
|
||||
|
||||
extern struct bflb_device_s *console;
|
||||
|
||||
/* Reentrant versions of system calls. */
|
||||
|
||||
/* global errno */
|
||||
static volatile int _sys_errno = 0;
|
||||
|
||||
#ifndef _REENT_ONLY
|
||||
int *__errno()
|
||||
{
|
||||
return (int *)&_sys_errno;
|
||||
}
|
||||
#endif
|
||||
|
||||
int _getpid_r(struct _reent *ptr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _execve_r(struct _reent *ptr, const char *name, char *const *argv, char *const *env)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _fcntl_r(struct _reent *ptr, int fd, int cmd, int arg)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _fork_r(struct _reent *ptr)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _fstat_r(struct _reent *ptr, int fd, struct stat *pstat)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _isatty_r(struct _reent *ptr, int fd)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _kill_r(struct _reent *ptr, int pid, int sig)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _link_r(struct _reent *ptr, const char *old, const char *new)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_off_t _lseek_r(struct _reent *ptr, int fd, _off_t pos, int whence)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _mkdir_r(struct _reent *ptr, const char *name, int mode)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _open_r(struct _reent *ptr, const char *file, int flags, int mode)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _close_r(struct _reent *ptr, int fd)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_ssize_t _read_r(struct _reent *ptr, int fd, void *buf, size_t nbytes)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _rename_r(struct _reent *ptr, const char *old, const char *new)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _stat_r(struct _reent *ptr, const char *file, struct stat *pstat)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _unlink_r(struct _reent *ptr, const char *file)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _wait_r(struct _reent *ptr, int *status)
|
||||
{
|
||||
/* return "not supported" */
|
||||
ptr->_errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_ssize_t _write_r(struct _reent *ptr, int fd, const void *buf, size_t nbytes)
|
||||
{
|
||||
if ((STDOUT_FILENO == fd) || (STDERR_FILENO == fd)) {
|
||||
bflb_uart_put(console, (uint8_t *)buf, nbytes);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *_malloc_r(struct _reent *ptr, size_t size)
|
||||
{
|
||||
void *result;
|
||||
#ifdef CONFIG_MEM_USE_FREERTOS
|
||||
result = pvPortMalloc(size);
|
||||
#else
|
||||
#ifdef CONFIG_TLSF
|
||||
result = (void *)bflb_malloc(size);
|
||||
#else
|
||||
result = (void *)bflb_mmheap_alloc(&mmheap_root, size);
|
||||
#endif
|
||||
#endif
|
||||
if (result == NULL) {
|
||||
ptr->_errno = -ENOMEM;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void *_realloc_r(struct _reent *ptr, void *old, size_t newlen)
|
||||
{
|
||||
void *result;
|
||||
#ifdef CONFIG_MEM_USE_FREERTOS
|
||||
#else
|
||||
#ifdef CONFIG_TLSF
|
||||
result = (void *)bflb_realloc(old, newlen);
|
||||
#else
|
||||
result = (void *)bflb_mmheap_realloc(&mmheap_root, old, newlen);
|
||||
#endif
|
||||
#endif
|
||||
if (result == NULL) {
|
||||
ptr->_errno = -ENOMEM;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void *_calloc_r(struct _reent *ptr, size_t size, size_t len)
|
||||
{
|
||||
void *result;
|
||||
#ifdef CONFIG_MEM_USE_FREERTOS
|
||||
result = pvPortMalloc(size * len);
|
||||
#else
|
||||
#ifdef CONFIG_TLSF
|
||||
result = (void *)bflb_calloc(size, len);
|
||||
#else
|
||||
result = (void *)bflb_mmheap_calloc(&mmheap_root, size, len);
|
||||
#endif
|
||||
#endif
|
||||
if (result == NULL) {
|
||||
ptr->_errno = -ENOMEM;
|
||||
}
|
||||
if (result) {
|
||||
memset(result, 0, size * len);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void *_memalign_r(struct _reent *ptr, size_t align, size_t size)
|
||||
{
|
||||
void *result;
|
||||
#ifdef CONFIG_MEM_USE_FREERTOS
|
||||
#else
|
||||
#ifdef CONFIG_TLSF
|
||||
result = (void *)bflb_malloc_align(align, size);
|
||||
#else
|
||||
result = (void *)bflb_mmheap_align_alloc(&mmheap_root, align, size);
|
||||
#endif
|
||||
#endif
|
||||
if (result == NULL) {
|
||||
ptr->_errno = -ENOMEM;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void _free_r(struct _reent *ptr, void *addr)
|
||||
{
|
||||
#ifdef CONFIG_MEM_USE_FREERTOS
|
||||
vPortFree(addr);
|
||||
#else
|
||||
#ifdef CONFIG_TLSF
|
||||
bflb_free(addr);
|
||||
#else
|
||||
bflb_mmheap_free(&mmheap_root, addr);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void *_sbrk_r(struct _reent *ptr, ptrdiff_t incr)
|
||||
{
|
||||
void *ret;
|
||||
ptr->_errno = ENOMEM;
|
||||
ret = (void *)-1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* for exit() and abort() */
|
||||
void __attribute__((noreturn))
|
||||
_exit(int status)
|
||||
{
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
void _system(const char *s)
|
||||
{
|
||||
}
|
||||
|
||||
void __libc_init_array(void)
|
||||
{
|
||||
/* we not use __libc init_aray to initialize C++ objects */
|
||||
}
|
||||
|
||||
mode_t umask(mode_t mask)
|
||||
{
|
||||
return 022;
|
||||
}
|
||||
|
||||
int flock(int fd, int operation)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
These functions are implemented and replaced by the 'common/time.c' file
|
||||
int _gettimeofday_r(struct _reent *ptr, struct timeval *__tp, void *__tzp);
|
||||
_CLOCK_T_ _times_r(struct _reent *ptr, struct tms *ptms);
|
||||
*/
|
1561
components/utils/vlibc/vlibc_stdio.c
Normal file
1561
components/utils/vlibc/vlibc_stdio.c
Normal file
File diff suppressed because it is too large
Load diff
170
components/utils/vlibc/vlibc_stdio.h
Normal file
170
components/utils/vlibc/vlibc_stdio.h
Normal file
|
@ -0,0 +1,170 @@
|
|||
#ifndef _VLIBC_STDIO_H
|
||||
#define _VLIBC_STDIO_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef CONFIG_VLIBC_FATFS
|
||||
#include "ff.h"
|
||||
#endif
|
||||
|
||||
/** @addtogroup Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
struct __vlibc_io {
|
||||
char *bg; /*!< buffer begin pointer */
|
||||
char *wp; /*!< buffer write pointer */
|
||||
char *rp; /*!< buffer read pointer */
|
||||
char *ed; /*!< buffer end pointer */
|
||||
|
||||
uint32_t dev; /*!< io device */
|
||||
uint8_t flag; /*!< io flag */
|
||||
uint8_t vbuf; /*!< buffer mode */
|
||||
uint8_t abuf; /*!< buffer auto */
|
||||
uint8_t err; /*!< error */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
|
||||
union {
|
||||
struct __vlibc_io *io;
|
||||
#ifdef CONFIG_VLIBC_FATFS
|
||||
FIL *file;
|
||||
#else
|
||||
int *file;
|
||||
#endif
|
||||
};
|
||||
} vlibc_file_t;
|
||||
|
||||
/*!< file type */
|
||||
#define VLIBC_FILE vlibc_file_t
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup stdio extra
|
||||
* @{
|
||||
*/
|
||||
extern uint32_t __vlibc_io_init(const char *name, uint8_t mode);
|
||||
extern uint32_t __vlibc_io_deinit(struct __vlibc_io *io);
|
||||
extern size_t __vlibc_io_mem2dev(struct __vlibc_io *io, const void *ptr, size_t size);
|
||||
extern size_t __vlibc_io_dev2mem(struct __vlibc_io *io, void *ptr, size_t size);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup Marcos
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define _VLIBC_MAGIC_MASK ((unsigned int)(0xffff0000))
|
||||
#define _VLIBC_IO_MAGIC_CODE ((unsigned int)(0x10de0000))
|
||||
#define _VLIBC_FILE_MAGIC_CODE ((unsigned int)(0xf11e0000))
|
||||
|
||||
#define _VLIBC_IO_WRITE ((unsigned char)(0x01))
|
||||
#define _VLIBC_IO_READ ((unsigned char)(0x02))
|
||||
|
||||
/*!< io buffer size */
|
||||
#define VLIBC_BUFSIZ 256
|
||||
|
||||
/*!< file stack buffer size */
|
||||
#define VLIBC_FBUFSIZ 256
|
||||
|
||||
/*!< max open file count at the same time */
|
||||
#define VLIBC_FOPEN_MAX 20
|
||||
|
||||
/*!< max file name length */
|
||||
#define VLIBC_FILENAME_MAX 256
|
||||
|
||||
/*!< max io name length */
|
||||
#define _VLIBC_IONAME_MAX 32
|
||||
|
||||
/*!< max tmpnam file name length */
|
||||
#define VLIBC_L_tmpnam VLIBC_FILENAME_MAX
|
||||
|
||||
/*!< max tmpnam rand name */
|
||||
#define VLIBC_TMP_MAX 0
|
||||
|
||||
/*!< stand io */
|
||||
extern vlibc_file_t *__vlibc_stdio_fileptrs[3];
|
||||
#define vlibc_stdin (__vlibc_stdio_fileptrs[0])
|
||||
#define vlibc_stdout (__vlibc_stdio_fileptrs[1])
|
||||
#define vlibc_stderr (__vlibc_stdio_fileptrs[2])
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup stdio functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern void vlibc_clearerr(VLIBC_FILE *);
|
||||
extern int vlibc_feof(VLIBC_FILE *);
|
||||
extern int vlibc_ferror(VLIBC_FILE *);
|
||||
|
||||
extern VLIBC_FILE *vlibc_fopen(const char *, const char *);
|
||||
extern VLIBC_FILE *vlibc_freopen(const char *, const char *, VLIBC_FILE *);
|
||||
extern int vlibc_fclose(VLIBC_FILE *);
|
||||
|
||||
extern size_t vlibc_fread(void *, size_t, size_t, VLIBC_FILE *);
|
||||
extern size_t vlibc_fwrite(const void *, size_t, size_t, VLIBC_FILE *);
|
||||
|
||||
extern int vlibc_fflush(VLIBC_FILE *);
|
||||
extern int vlibc_fseek(VLIBC_FILE *, long, int);
|
||||
extern long vlibc_ftell(VLIBC_FILE *);
|
||||
|
||||
extern int vlibc_remove(const char *);
|
||||
extern int vlibc_rename(const char *, const char *);
|
||||
extern void vlibc_rewind(VLIBC_FILE *);
|
||||
|
||||
extern void vlibc_setbuf(VLIBC_FILE *, char *);
|
||||
extern int vlibc_setvbuf(VLIBC_FILE *, char *, int, size_t);
|
||||
|
||||
extern VLIBC_FILE *vlibc_tmpfile(void);
|
||||
extern char *vlibc_tmpnam(char *);
|
||||
|
||||
extern int vlibc_fprintf(VLIBC_FILE *, const char *, ...);
|
||||
extern int vlibc_printf(const char *, ...);
|
||||
extern int vlibc_sprintf(char *, const char *, ...);
|
||||
extern int vlibc_snprintf(char *, size_t, const char *, ...);
|
||||
|
||||
extern int vlibc_vfprintf(VLIBC_FILE *, const char *, va_list);
|
||||
extern int vlibc_vprintf(const char *, va_list);
|
||||
extern int vlibc_vsprintf(char *, const char *, va_list);
|
||||
extern int vlibc_vsnprintf(char *, size_t, const char *, va_list);
|
||||
|
||||
extern int vlibc_fscanf(VLIBC_FILE *, const char *, ...);
|
||||
extern int vlibc_scanf(const char *, ...);
|
||||
extern int vlibc_sscanf(const char *, const char *, ...);
|
||||
|
||||
extern int vlibc_vfscanf(VLIBC_FILE *, const char *, va_list);
|
||||
extern int vlibc_vscanf(const char *, va_list);
|
||||
extern int vlibc_vsscanf(const char *, const char *, va_list);
|
||||
|
||||
extern int vlibc_fgetc(VLIBC_FILE *);
|
||||
extern char *vlibc_fgets(char *, int, VLIBC_FILE *);
|
||||
|
||||
extern int vlibc_fputc(int, VLIBC_FILE *);
|
||||
extern int vlibc_fputs(const char *, VLIBC_FILE *);
|
||||
|
||||
extern int vlibc_getc(VLIBC_FILE *);
|
||||
extern int vlibc_getchar(void);
|
||||
extern char *vlibc_gets(char *);
|
||||
|
||||
extern int vlibc_putc(int, VLIBC_FILE *);
|
||||
extern int vlibc_putchar(int);
|
||||
extern int vlibc_puts(const char *);
|
||||
|
||||
extern void vlibc_perror(const char *);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif
|
1504
components/utils/vlibc/vlibc_vsnprintf.c
Normal file
1504
components/utils/vlibc/vlibc_vsnprintf.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue