mirror of
https://github.com/pvvx/RTL00_WEB.git
synced 2026-07-10 04:55:38 +00:00
update
This commit is contained in:
parent
34d3652711
commit
39f77eb92b
1844 changed files with 899433 additions and 7 deletions
64
USDK/component/os/os_dep/device_lock.c
Normal file
64
USDK/component/os/os_dep/device_lock.c
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Routines to access hardware
|
||||
*
|
||||
* Copyright (c) 2013 Realtek Semiconductor Corp.
|
||||
*
|
||||
* This module is a confidential and proprietary property of RealTek and
|
||||
* possession or use of this module requires written permission of RealTek.
|
||||
*/
|
||||
|
||||
#include "osdep_service.h"
|
||||
#include "device_lock.h"
|
||||
|
||||
//------------------------------------------------------
|
||||
#define DEVICE_MUTEX_IS_INIT(device) (mutex_init & (1<<device))
|
||||
#define DEVICE_MUTEX_SET_INIT(device) (mutex_init |= (1<<device))
|
||||
#define DEVICE_MUTEX_CLR_INIT(device) (mutex_init &= (~(1<<device)))
|
||||
|
||||
static u32 mutex_init = 0;
|
||||
static _mutex device_mutex[RT_DEV_LOCK_MAX];
|
||||
|
||||
//======================================================
|
||||
static void device_mutex_init(RT_DEV_LOCK_E device)
|
||||
{
|
||||
if(!DEVICE_MUTEX_IS_INIT(device)){
|
||||
_lock lock;
|
||||
_irqL irqL;
|
||||
rtw_enter_critical(&lock, &irqL);
|
||||
if(!DEVICE_MUTEX_IS_INIT(device)){
|
||||
rtw_mutex_init(&device_mutex[device]);
|
||||
DEVICE_MUTEX_SET_INIT(device);
|
||||
}
|
||||
rtw_exit_critical(&lock, &irqL);
|
||||
}
|
||||
}
|
||||
|
||||
//======================================================
|
||||
static void device_mutex_free(RT_DEV_LOCK_E device)
|
||||
{
|
||||
if(DEVICE_MUTEX_IS_INIT(device)){
|
||||
_lock lock;
|
||||
_irqL irqL;
|
||||
rtw_enter_critical(&lock, &irqL);
|
||||
if(!DEVICE_MUTEX_IS_INIT(device)){
|
||||
rtw_mutex_free(&device_mutex[device]);
|
||||
DEVICE_MUTEX_CLR_INIT(device);
|
||||
}
|
||||
rtw_exit_critical(&lock, &irqL);
|
||||
}
|
||||
}
|
||||
|
||||
//======================================================
|
||||
void device_mutex_lock(RT_DEV_LOCK_E device)
|
||||
{
|
||||
device_mutex_init(device);
|
||||
while(rtw_mutex_get_timeout(&device_mutex[device], 10000)<0)
|
||||
printf("device lock timeout: %d\n", device);
|
||||
}
|
||||
|
||||
//======================================================
|
||||
void device_mutex_unlock(RT_DEV_LOCK_E device)
|
||||
{
|
||||
device_mutex_init(device);
|
||||
rtw_mutex_put(&device_mutex[device]);
|
||||
}
|
||||
25
USDK/component/os/os_dep/include/device_lock.h
Normal file
25
USDK/component/os/os_dep/include/device_lock.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Routines to access hardware
|
||||
*
|
||||
* Copyright (c) 2013 Realtek Semiconductor Corp.
|
||||
*
|
||||
* This module is a confidential and proprietary property of RealTek and
|
||||
* possession or use of this module requires written permission of RealTek.
|
||||
*/
|
||||
|
||||
#ifndef _DEVICE_LOCK_H_
|
||||
#define _DEVICE_LOCK_H_
|
||||
|
||||
typedef enum _RT_DEV_LOCK_E
|
||||
{
|
||||
RT_DEV_LOCK_EFUSE = 0,
|
||||
RT_DEV_LOCK_FLASH = 1,
|
||||
RT_DEV_LOCK_CRYPTO = 2,
|
||||
RT_DEV_LOCK_PTA = 3,
|
||||
RT_DEV_LOCK_MAX = 4
|
||||
}RT_DEV_LOCK_E;
|
||||
|
||||
void device_mutex_lock(RT_DEV_LOCK_E device);
|
||||
void device_mutex_unlock(RT_DEV_LOCK_E device);
|
||||
|
||||
#endif //_DEVICE_LOCK_H_
|
||||
343
USDK/component/os/os_dep/include/os_support.h
Normal file
343
USDK/component/os/os_dep/include/os_support.h
Normal file
|
|
@ -0,0 +1,343 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Name: sys-support.h - System type support for Linux
|
||||
* $Revision: 1.1.1.1 $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __OS_SUPPORT_H__
|
||||
#define __OS_SUPPORT_H__
|
||||
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <basic_types.h>
|
||||
#include "os_support.h"
|
||||
//#include "diag.h"
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
#define __init
|
||||
#define __exit
|
||||
#define __devinit
|
||||
#define __devexit
|
||||
#endif
|
||||
#define RTL_HZ 100
|
||||
|
||||
#define SemaInit(sem, value) vSemaphoreCreateBinary(sem)
|
||||
#define SemaPost(sem) xSemaphoreGive(sem)
|
||||
#define SemaWait(sem, block_time) xSemaphoreTake(sem, block_time)
|
||||
//#define printk DiagPrintf
|
||||
|
||||
#define SpinLockInit(lock) do { } while (0)
|
||||
#define SpinLock(x) do { } while (0)
|
||||
#define SpinUnlock(x) do { } while (0)
|
||||
#define SpinLockBh(x) do { } while (0)
|
||||
#define SpinUnlockBh(x) do { } while (0)
|
||||
#ifdef PLATFORM_FREERTOS
|
||||
#define RestoreFlags() portEXIT_CRITICAL()
|
||||
#define SaveAndCli() portENTER_CRITICAL()
|
||||
#define SpinLockIrqSave(lock, flags) SaveAndCli()
|
||||
#define SpinUnlockIrqRestore(l, f) RestoreFlags()
|
||||
#else
|
||||
#define RestoreFlags(x) portENABLE_INTERRUPTS()
|
||||
#define SaveAndCli(x) portDISABLE_INTERRUPTS()
|
||||
#define SpinLockIrqSave(lock, flags) SaveAndCli(flags)
|
||||
#define SpinUnlockIrqRestore(l, f) RestoreFlags(f)
|
||||
#endif
|
||||
|
||||
|
||||
//#define RtlKmalloc(size, flag) pvPortMallocAligned(size, 0)
|
||||
#define RtlKmalloc(size, flag) pvPortMalloc(size)
|
||||
#define RtlKfree(pv) vPortFreeAligned(pv)
|
||||
|
||||
|
||||
|
||||
#ifdef CONFIG_TIMER_MODULE
|
||||
#define __Delay(t) HalDelayUs(t)
|
||||
#else
|
||||
static __inline__ u32 __Delay(u32 us)
|
||||
{
|
||||
DBG_8195A("No Delay: please enable hardware Timer\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define Mdelay(t) __Delay(t*1000)
|
||||
#define Udelay(t) __Delay(t)
|
||||
|
||||
|
||||
#define ASSERT(_bool_) do { } while (0)
|
||||
|
||||
//#define panic_printk DiagPrintf
|
||||
//#define sprintf DiagPrintf
|
||||
//#define diag_sprintf DiagPrintf
|
||||
|
||||
|
||||
//1TODO: Need check again; the below just for compile ok ; chris
|
||||
|
||||
/*
|
||||
* ATOMIC_READ - read atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically reads the value of @v. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
//#define AtomicRead(v) ((*v))
|
||||
|
||||
static __inline__ u32
|
||||
AtomicRead(
|
||||
IN atomic_t * v
|
||||
)
|
||||
{
|
||||
#ifdef PLATFORM_FREERTOS
|
||||
u32 Temp;
|
||||
|
||||
SaveAndCli();
|
||||
Temp = v->counter;
|
||||
RestoreFlags();
|
||||
|
||||
return Temp;
|
||||
|
||||
#else
|
||||
u32 Temp, Flags;
|
||||
|
||||
SaveAndCli(Flags);
|
||||
Temp = v->counter;
|
||||
RestoreFlags(Flags);
|
||||
|
||||
return Temp;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* ATOMIC_SET - set atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
* @i: required value
|
||||
*
|
||||
* Atomically sets the value of @v to @i. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
//#define AtomicSet(v,i) ((v)->counter = (i))
|
||||
|
||||
static __inline__ VOID
|
||||
AtomicSet(
|
||||
IN u32 i,
|
||||
IN atomic_t * v
|
||||
)
|
||||
{
|
||||
#ifdef PLATFORM_FREERTOS
|
||||
SaveAndCli();
|
||||
v->counter = i;
|
||||
RestoreFlags();
|
||||
#else
|
||||
u32 Flags;
|
||||
|
||||
SaveAndCli(Flags);
|
||||
v->counter = i;
|
||||
RestoreFlags(Flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* The MIPS I implementation is only atomic with respect to
|
||||
* interrupts. R3000 based multiprocessor machines are rare anyway ...
|
||||
*
|
||||
* AtomicAdd - add integer to atomic variable
|
||||
* @i: integer value to add
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically adds @i to @v. Note that the guaranteed useful range
|
||||
* of an atomic_t is only 24 bits.
|
||||
*/
|
||||
static __inline__ VOID
|
||||
AtomicAdd(
|
||||
IN u32 i,
|
||||
IN atomic_t * v
|
||||
)
|
||||
{
|
||||
#ifdef PLATFORM_FREERTOS
|
||||
SaveAndCli();
|
||||
v->counter += i;
|
||||
RestoreFlags();
|
||||
#else
|
||||
u32 Flags;
|
||||
|
||||
SaveAndCli(Flags);
|
||||
v->counter += i;
|
||||
RestoreFlags(Flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* AtomicSub - subtract the atomic variable
|
||||
* @i: integer value to subtract
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically subtracts @i from @v. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
static __inline__ void
|
||||
AtomicSub(
|
||||
IN u32 i,
|
||||
IN atomic_t * v
|
||||
)
|
||||
{
|
||||
#ifdef PLATFORM_FREERTOS
|
||||
SaveAndCli();
|
||||
v->counter -= i;
|
||||
RestoreFlags();
|
||||
#else
|
||||
u32 Flags;
|
||||
|
||||
SaveAndCli(Flags);
|
||||
v->counter -= i;
|
||||
RestoreFlags(Flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline__ u32
|
||||
AtomicAddReturn(
|
||||
IN u32 i,
|
||||
IN atomic_t * v
|
||||
)
|
||||
{
|
||||
#ifdef PLATFORM_FREERTOS
|
||||
u32 Temp;
|
||||
|
||||
SaveAndCli();
|
||||
Temp = v->counter;
|
||||
Temp += i;
|
||||
v->counter = Temp;
|
||||
RestoreFlags();
|
||||
|
||||
return Temp;
|
||||
|
||||
#else
|
||||
u32 Temp, Flags;
|
||||
|
||||
SaveAndCli(Flags);
|
||||
Temp = v->counter;
|
||||
Temp += i;
|
||||
v->counter = Temp;
|
||||
RestoreFlags(Flags);
|
||||
|
||||
return Temp;
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline__ u32
|
||||
AtomicSubReturn(
|
||||
IN u32 i,
|
||||
IN atomic_t * v
|
||||
)
|
||||
{
|
||||
#ifdef PLATFORM_FREERTOS
|
||||
u32 Temp;
|
||||
|
||||
SaveAndCli();
|
||||
Temp = v->counter;
|
||||
Temp -= i;
|
||||
v->counter = Temp;
|
||||
RestoreFlags();
|
||||
|
||||
return Temp;
|
||||
|
||||
#else
|
||||
|
||||
u32 Temp, Flags;
|
||||
|
||||
SaveAndCli(Flags);
|
||||
Temp = v->counter;
|
||||
Temp -= i;
|
||||
v->counter = Temp;
|
||||
RestoreFlags(Flags);
|
||||
|
||||
return Temp;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* ATOMIC_INC - increment atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically increments @v by 1. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
#define AtomicInc(v) AtomicAdd(1,(v))
|
||||
|
||||
#define AtomicIncReturn(v) AtomicAddReturn(1,(v))
|
||||
|
||||
/*
|
||||
* ATOMIC_DEC - decrement and test
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically decrements @v by 1. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
#define AtomicDec(v) AtomicSub(1,(v))
|
||||
|
||||
#define AtomicDecReturn(v) AtomicSubReturn(1,(v))
|
||||
|
||||
/*
|
||||
* ATOMIC_DEC_AND_TEST - decrement by 1 and test
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically decrements @v by 1 and
|
||||
* returns true if the result is 0, or false for all other
|
||||
* cases. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
#define AtomicDecAndTest(v) (AtomicSubReturn(1, (v)) == 0)
|
||||
|
||||
/* Not needed on 64bit architectures */
|
||||
static __inline__ u32
|
||||
__Div64_32(
|
||||
IN __uint64_t *n,
|
||||
IN u32 base
|
||||
)
|
||||
{
|
||||
__uint64_t rem = *n;
|
||||
__uint64_t b = base;
|
||||
__uint64_t res, d = 1;
|
||||
u32 high = rem >> 32;
|
||||
|
||||
/* Reduce the thing a bit first */
|
||||
res = 0;
|
||||
if (high >= base) {
|
||||
high /= base;
|
||||
res = (__uint64_t) high << 32;
|
||||
rem -= (__uint64_t) (high*base) << 32;
|
||||
}
|
||||
|
||||
while ((__int64_t)b > 0 && b < rem) {
|
||||
b = b+b;
|
||||
d = d+d;
|
||||
}
|
||||
|
||||
do {
|
||||
if (rem >= b) {
|
||||
rem -= b;
|
||||
res += d;
|
||||
}
|
||||
b >>= 1;
|
||||
d >>= 1;
|
||||
} while (d);
|
||||
|
||||
*n = res;
|
||||
return rem;
|
||||
}
|
||||
|
||||
#define DO_DIV(n,base) ({ \
|
||||
unsigned int __base = (base); \
|
||||
unsigned int __rem; \
|
||||
(void)(((typeof((n)) *)0) == ((__uint64_t *)0)); \
|
||||
if (((n) >> 32) == 0) { \
|
||||
__rem = (unsigned int)(n) % __base; \
|
||||
(n) = (unsigned int)(n) / __base; \
|
||||
} else \
|
||||
__rem = __Div64_32(&(n), __base); \
|
||||
__rem; \
|
||||
})
|
||||
|
||||
#endif /* __SYS_SUPPORT_H__ */
|
||||
1354
USDK/component/os/os_dep/include/osdep_service.h
Normal file
1354
USDK/component/os/os_dep/include/osdep_service.h
Normal file
File diff suppressed because it is too large
Load diff
74
USDK/component/os/os_dep/include/tcm_heap.h
Normal file
74
USDK/component/os/os_dep/include/tcm_heap.h
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#ifndef STRUCT_HEAP_H
|
||||
#define STRUCT_HEAP_H
|
||||
|
||||
//#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <osdep_service.h>
|
||||
|
||||
|
||||
|
||||
#define TCM_HEAP_SIZE (42*1024) // min size
|
||||
|
||||
// MAX_BACKUP_SIZE in hal_soc_ps_monitor = 129*4, 0x1FFFFFFC - 129*4 = 0x1FFFFD18 !
|
||||
#define tcm_heap_size ((0x20000000 - (u32)&tcm_heap - 768 + sizeof(heap_buf_t) - 1)/sizeof(heap_buf_t))*sizeof(heap_buf_t)
|
||||
|
||||
/* NOTE: struct size must be a 2's power! */
|
||||
typedef struct _MemChunk
|
||||
{
|
||||
struct _MemChunk *next;
|
||||
int size;
|
||||
} MemChunk;
|
||||
|
||||
typedef MemChunk heap_buf_t;
|
||||
|
||||
/// A heap
|
||||
typedef struct Heap
|
||||
{
|
||||
struct _MemChunk *FreeList; ///< Head of the free list
|
||||
} Heap;
|
||||
|
||||
/**
|
||||
* Utility macro to allocate a heap of size \a size.
|
||||
*
|
||||
* \param name Variable name for the heap.
|
||||
* \param size Heap size in bytes.
|
||||
*/
|
||||
#define HEAP_DEFINE_BUF(name, size) \
|
||||
heap_buf_t name[((size) + sizeof(heap_buf_t) - 1) / sizeof(heap_buf_t)]
|
||||
|
||||
/// Initialize \a heap within the buffer pointed by \a memory which is of \a size bytes
|
||||
void tcm_heap_init(void);
|
||||
|
||||
/// Allocate a chunk of memory of \a size bytes from the heap
|
||||
// void *tcm_heap_allocmem(int size);
|
||||
|
||||
/// Free a chunk of memory of \a size bytes from the heap
|
||||
// void tcm_heap_freemem(void *mem, int size);
|
||||
|
||||
int tcm_heap_freeSpace(void);
|
||||
|
||||
#define HNEW(heap, type) \
|
||||
(type*)tcm_heap_allocmem(heap, sizeof(type))
|
||||
|
||||
#define HNEWVEC(heap, type, nelem) \
|
||||
(type*)tcm_heap_allocmem(heap, sizeof(type) * (nelem))
|
||||
|
||||
#define HDELETE(heap, type, mem) \
|
||||
tcm_heap_freemem(heap, mem, sizeof(type))
|
||||
|
||||
#define HDELETEVEC(heap, type, nelem, mem) \
|
||||
tcm_heap_freemem(heap, mem, sizeof(type) * (nelem))
|
||||
|
||||
extern HEAP_DEFINE_BUF(tcm_heap, TCM_HEAP_SIZE);
|
||||
|
||||
/**
|
||||
* \name Compatibility interface with C standard library
|
||||
* \{
|
||||
*/
|
||||
void *tcm_heap_malloc(int size);
|
||||
void *tcm_heap_calloc(int size);
|
||||
void tcm_heap_free(void * mem);
|
||||
void tcm_heap_dump(void);
|
||||
/** \} */
|
||||
|
||||
#endif /* STRUCT_HEAP_H */
|
||||
1308
USDK/component/os/os_dep/osdep_service.c
Normal file
1308
USDK/component/os/os_dep/osdep_service.c
Normal file
File diff suppressed because it is too large
Load diff
347
USDK/component/os/os_dep/tcm_heap.c
Normal file
347
USDK/component/os/os_dep/tcm_heap.c
Normal file
|
|
@ -0,0 +1,347 @@
|
|||
//#include <autoconf.h>
|
||||
#include "tcm_heap.h"
|
||||
|
||||
#include <string.h> // memset()
|
||||
|
||||
#include <osdep_service.h>
|
||||
|
||||
//#define _DEBUG
|
||||
|
||||
#if CONFIG_USE_TCM_HEAP
|
||||
#define FREE_FILL_CODE 0xDEAD
|
||||
#define ALLOC_FILL_CODE 0xBEEF
|
||||
|
||||
#define ROUND_UP2(x, pad) (((x) + ((pad) - 1)) & ~((pad) - 1))
|
||||
|
||||
//static
|
||||
struct Heap g_tcm_heap;
|
||||
|
||||
#if defined (__ICCARM__)
|
||||
#pragma location=".tcm.heap"
|
||||
#else
|
||||
__attribute__((section(".tcm.heap")))
|
||||
#endif
|
||||
HEAP_DEFINE_BUF(tcm_heap, TCM_HEAP_SIZE);
|
||||
//unsigned char tcm_heap[TCM_HEAP_SIZE];
|
||||
|
||||
static int g_heap_inited = 0;
|
||||
static _lock tcm_lock;
|
||||
|
||||
extern void vPortSetExtFree( void (*free)( void *p ), uint32_t upper, uint32_t lower );
|
||||
|
||||
void tcm_heap_init(void)
|
||||
{
|
||||
//#ifdef _DEBUG
|
||||
//memset(memory, FREE_FILL_CODE, size);
|
||||
//#endif
|
||||
|
||||
//ASSERT2(((int)memory % alignof(heap_buf_t)) == 0,
|
||||
//"memory buffer is unaligned, please use the HEAP_DEFINE_BUF() macro to declare heap buffers!\n");
|
||||
|
||||
/* Initialize heap with a single big chunk */
|
||||
g_tcm_heap.FreeList = (MemChunk *)&tcm_heap;
|
||||
g_tcm_heap.FreeList->next = NULL;
|
||||
// g_tcm_heap.FreeList->size = sizeof(tcm_heap);
|
||||
g_tcm_heap.FreeList->size = tcm_heap_size; // ((0x20000000 - (u32)&tcm_heap - 520 + sizeof(heap_buf_t) - 1)/sizeof(heap_buf_t))*sizeof(heap_buf_t);
|
||||
|
||||
g_heap_inited = 1;
|
||||
rtw_spinlock_init(&tcm_lock);
|
||||
|
||||
#if PLATFORM_FREERTOS
|
||||
// let RTOS know how to free memory if using as task stack
|
||||
vPortSetExtFree(tcm_heap_free, 0x20000000, 0x1fff0000);
|
||||
#endif
|
||||
}
|
||||
|
||||
void tcm_heap_dump(void)
|
||||
{
|
||||
#if CONFIG_DEBUG_LOG > 1
|
||||
if(!g_heap_inited) tcm_heap_init();
|
||||
MemChunk *chunk, *prev;
|
||||
struct Heap* h = &g_tcm_heap;
|
||||
int count = 0;
|
||||
int free_mem;
|
||||
|
||||
DBG_8195A("TCM Free Heap Memory List:\n");
|
||||
for (chunk = h->FreeList; chunk; chunk = chunk->next) {
|
||||
DBG_8195A(" [%d]=%p, %d\n", ++count, chunk, chunk->size);
|
||||
}
|
||||
|
||||
/*
|
||||
for (prev = (MemChunk *)&h->FreeList, chunk = h->FreeList;
|
||||
chunk;
|
||||
prev = chunk, chunk = chunk->next)
|
||||
{
|
||||
DBG_8195A(" [%d]=%p, %d\n", ++count, chunk, chunk->size);
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
|
||||
static void *tcm_heap_allocmem(int size)
|
||||
{
|
||||
MemChunk *chunk, *prev;
|
||||
struct Heap* h = &g_tcm_heap;
|
||||
_irqL irqL;
|
||||
|
||||
rtw_enter_critical(&tcm_lock, &irqL);
|
||||
|
||||
if(!g_heap_inited) tcm_heap_init();
|
||||
|
||||
/* Round size up to the allocation granularity */
|
||||
size = ROUND_UP2(size, sizeof(MemChunk));
|
||||
|
||||
/* Handle allocations of 0 bytes */
|
||||
if (!size)
|
||||
size = sizeof(MemChunk);
|
||||
|
||||
/* Walk on the free list looking for any chunk big enough to
|
||||
* fit the requested block size.
|
||||
*/
|
||||
for (prev = (MemChunk *)&h->FreeList, chunk = h->FreeList;
|
||||
chunk;
|
||||
prev = chunk, chunk = chunk->next)
|
||||
{
|
||||
if (chunk->size >= size)
|
||||
{
|
||||
if (chunk->size == size)
|
||||
{
|
||||
/* Just remove this chunk from the free list */
|
||||
prev->next = chunk->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate from the END of an existing chunk */
|
||||
chunk->size -= size;
|
||||
chunk = (MemChunk *)((uint8_t *)chunk + chunk->size);
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
memset(chunk, ALLOC_FILL_CODE, size);
|
||||
#endif
|
||||
|
||||
rtw_exit_critical(&tcm_lock, &irqL);
|
||||
DBG_TCM_HEAP_INFO("tcm_alloc:%p[%d]\n", chunk, size);
|
||||
return (void *)chunk;
|
||||
}
|
||||
}
|
||||
rtw_exit_critical(&tcm_lock, &irqL);
|
||||
DBG_TCM_HEAP_WARN("tcm_alloc(%d) - freeSpace(%d)!\n", size, tcm_heap_freeSpace());
|
||||
return NULL; /* fail */
|
||||
}
|
||||
|
||||
static void tcm_heap_freemem(void *mem, int size)
|
||||
{
|
||||
MemChunk *prev;
|
||||
//ASSERT(mem);
|
||||
struct Heap* h = &g_tcm_heap;
|
||||
_irqL irqL;
|
||||
|
||||
rtw_enter_critical(&tcm_lock, &irqL);
|
||||
|
||||
// if(!g_heap_inited) tcm_heap_init();
|
||||
|
||||
#ifdef _DEBUG
|
||||
memset(mem, FREE_FILL_CODE, size);
|
||||
#endif
|
||||
|
||||
/* Round size up to the allocation granularity */
|
||||
size = ROUND_UP2(size, sizeof(MemChunk));
|
||||
|
||||
/* Handle allocations of 0 bytes */
|
||||
if (!size)
|
||||
size = sizeof(MemChunk);
|
||||
|
||||
/* Special cases: first chunk in the free list or memory completely full */
|
||||
//ASSERT((uint8_t*)mem != (uint8_t*)h->FreeList);
|
||||
if (((uint8_t *)mem) < ((uint8_t *)h->FreeList) || !h->FreeList)
|
||||
{
|
||||
/* Insert memory block before the current free list head */
|
||||
prev = (MemChunk *)mem;
|
||||
prev->next = h->FreeList;
|
||||
prev->size = size;
|
||||
h->FreeList = prev;
|
||||
}
|
||||
else /* Normal case: not the first chunk in the free list */
|
||||
{
|
||||
/*
|
||||
* Walk on the free list. Stop at the insertion point (when mem
|
||||
* is between prev and prev->next)
|
||||
*/
|
||||
prev = h->FreeList;
|
||||
while (prev->next < (MemChunk *)mem && prev->next)
|
||||
prev = prev->next;
|
||||
|
||||
/* Make sure mem is not *within* prev */
|
||||
//ASSERT((uint8_t*)mem >= (uint8_t*)prev + prev->size);
|
||||
|
||||
/* Should it be merged with previous block? */
|
||||
if (((uint8_t *)prev) + prev->size == ((uint8_t *)mem))
|
||||
{
|
||||
/* Yes */
|
||||
prev->size += size;
|
||||
}
|
||||
else /* not merged with previous chunk */
|
||||
{
|
||||
MemChunk *curr = (MemChunk*)mem;
|
||||
|
||||
/* insert it after the previous node
|
||||
* and move the 'prev' pointer forward
|
||||
* for the following operations
|
||||
*/
|
||||
curr->next = prev->next;
|
||||
curr->size = size;
|
||||
prev->next = curr;
|
||||
|
||||
/* Adjust for the following test */
|
||||
prev = curr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Also merge with next chunk? */
|
||||
if (((uint8_t *)prev) + prev->size == ((uint8_t *)prev->next))
|
||||
{
|
||||
prev->size += prev->next->size;
|
||||
prev->next = prev->next->next;
|
||||
|
||||
/* There should be only one merge opportunity, becuase we always merge on free */
|
||||
//ASSERT((uint8_t*)prev + prev->size != (uint8_t*)prev->next);
|
||||
}
|
||||
|
||||
rtw_exit_critical(&tcm_lock, &irqL);
|
||||
DBG_TCM_HEAP_INFO("tcm_free:%p[%d]\n", mem, size);
|
||||
}
|
||||
|
||||
int tcm_heap_freeSpace(void)
|
||||
{
|
||||
int free_mem = 0;
|
||||
struct Heap* h = &g_tcm_heap;
|
||||
_irqL irqL;
|
||||
MemChunk *chunk;
|
||||
|
||||
rtw_enter_critical(&tcm_lock, &irqL);
|
||||
|
||||
if(!g_heap_inited) tcm_heap_init();
|
||||
|
||||
for (chunk = h->FreeList; chunk; chunk = chunk->next)
|
||||
free_mem += chunk->size;
|
||||
|
||||
rtw_exit_critical(&tcm_lock, &irqL);
|
||||
return free_mem;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Standard malloc interface
|
||||
*/
|
||||
void *tcm_heap_malloc(int size)
|
||||
{
|
||||
int *mem;
|
||||
|
||||
size += sizeof(int);
|
||||
if ((mem = (int*)tcm_heap_allocmem(size))){
|
||||
*mem++ = size;
|
||||
}
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard calloc interface
|
||||
*/
|
||||
void *tcm_heap_calloc(int size)
|
||||
{
|
||||
void *mem;
|
||||
|
||||
if ((mem = tcm_heap_malloc(size)))
|
||||
memset(mem, 0, size);
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free a block of memory, determining its size automatically.
|
||||
*
|
||||
* \param h Heap from which the block was allocated.
|
||||
* \param mem Pointer to a block of memory previously allocated with
|
||||
* either heap_malloc() or heap_calloc().
|
||||
*
|
||||
* \note If \a mem is a NULL pointer, no operation is performed.
|
||||
*
|
||||
* \note Freeing the same memory block twice has undefined behavior.
|
||||
*
|
||||
* \note This function works like the ANSI C free().
|
||||
*/
|
||||
void tcm_heap_free(void *mem)
|
||||
{
|
||||
int *_mem = (int *)mem;
|
||||
|
||||
if (_mem)
|
||||
{
|
||||
--_mem;
|
||||
tcm_heap_freemem(_mem, *_mem);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
//----------- Tests -------------
|
||||
static void alloc_test(int size, int test_len)
|
||||
{
|
||||
//Simple test
|
||||
uint8_t *a[100];
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < test_len; i++)
|
||||
{
|
||||
a[i] = tcm_heap_allocmem(size);
|
||||
//ASSERT(a[i]);
|
||||
for (j = 0; j < size; j++)
|
||||
a[i][j] = i;
|
||||
}
|
||||
|
||||
//ASSERT(heap_freeSpace(&h) == HEAP_SIZE - test_len * ROUND_UP2(size, sizeof(MemChunk)));
|
||||
|
||||
for (i = 0; i < test_len; i++)
|
||||
{
|
||||
for (j = 0; j < size; j++)
|
||||
{
|
||||
DBG_8195A("a[%d][%d] = %d\n", i, j, a[i][j]);
|
||||
//ASSERT(a[i][j] == i);
|
||||
}
|
||||
tcm_heap_freemem(a[i], size);
|
||||
}
|
||||
//ASSERT(heap_freeSpace(&h) == HEAP_SIZE);
|
||||
}
|
||||
|
||||
#define ALLOC_SIZE 256
|
||||
#define ALLOC_SIZE2 1024
|
||||
#define TEST_LEN 20
|
||||
#define TEST_LEN2 10
|
||||
#define HEAP_SIZE 59*1024
|
||||
int tcm_heap_testRun(void)
|
||||
{
|
||||
alloc_test(ALLOC_SIZE, TEST_LEN);
|
||||
alloc_test(ALLOC_SIZE2, TEST_LEN2);
|
||||
/* Try to allocate the whole heap */
|
||||
uint8_t *b = tcm_heap_allocmem(HEAP_SIZE);
|
||||
int i, j;
|
||||
//ASSERT(b);
|
||||
//ASSERT(heap_freeSpace(&h) == 0);
|
||||
|
||||
//ASSERT(!heap_allocmem(&h, HEAP_SIZE));
|
||||
|
||||
for (j = 0; j < HEAP_SIZE; j++)
|
||||
b[j] = j;
|
||||
|
||||
for (j = 0; j < HEAP_SIZE; j++)
|
||||
{
|
||||
DBG_8195A("b[%d] = %d\n", j, j);
|
||||
//ASSERT(b[j] == (j & 0xff));
|
||||
}
|
||||
tcm_heap_freemem(b, HEAP_SIZE);
|
||||
//ASSERT(heap_freeSpace(&h) == HEAP_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif // tests
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue