mirror of
https://github.com/dimoniche/solarium.git
synced 2026-01-30 09:53:30 +03:00
463 lines
20 KiB
C
463 lines
20 KiB
C
/*
|
||
*********************************************************************************************************
|
||
* uC/LIB
|
||
* CUSTOM LIBRARY MODULES
|
||
*
|
||
* (c) Copyright 2004-2007; Micrium, Inc.; Weston, FL
|
||
*
|
||
* All rights reserved. Protected by international copyright laws.
|
||
*
|
||
* uC/LIB is provided in source form for FREE evaluation, for educational
|
||
* use or peaceful research. If you plan on using uC/LIB in a commercial
|
||
* product you need to contact Micrium to properly license its use in your
|
||
* product. We provide ALL the source code for your convenience and to
|
||
* help you experience uC/LIB. The fact that the source code is provided
|
||
* does NOT mean that you can use it without paying a licensing fee.
|
||
*
|
||
* Knowledge of the source code may NOT be used to develop a similar product.
|
||
*
|
||
* Please help us continue to provide the Embedded community with the finest
|
||
* software available. Your honesty is greatly appreciated.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
*
|
||
* STANDARD MEMORY OPERATIONS
|
||
*
|
||
* Filename : lib_mem.c
|
||
* Version : V1.24
|
||
* Programmer(s) : ITJ
|
||
*********************************************************************************************************
|
||
* Note(s) : (1) NO compiler-supplied standard library functions are used in library or product software.
|
||
*
|
||
* (a) ALL standard library functions are implemented in the custom library modules :
|
||
*
|
||
* (1) \<Custom Library Directory>\lib*.*
|
||
*
|
||
* (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.*
|
||
*
|
||
* where
|
||
* <Custom Library Directory> directory path for custom library software
|
||
* <cpu> directory name for specific processor (CPU)
|
||
* <compiler> directory name for specific compiler
|
||
*
|
||
* (b) Product-specific library functions are implemented in individual products.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* INCLUDE FILES
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
#define LIB_MEM_MODULE
|
||
#include <lib_mem.h>
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* LOCAL DEFINES
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* LOCAL CONSTANTS
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* LOCAL DATA TYPES
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* LOCAL TABLES
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* LOCAL GLOBAL VARIABLES
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* LOCAL FUNCTION PROTOTYPES
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* LOCAL CONFIGURATION ERRORS
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* Mem_Clr()
|
||
*
|
||
* Description : Clear data buffer (see Note #2).
|
||
*
|
||
* Argument(s) : pmem Pointer to memory buffer to clear.
|
||
*
|
||
* size Number of data buffer octets to clear.
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : various.
|
||
*
|
||
* Note(s) : (1) Null clears allowed (i.e. 0-octet size).
|
||
*
|
||
* See also 'Mem_Set() Note #1'.
|
||
*
|
||
* (2) Clear data by setting each data octet to 0.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
void Mem_Clr (void *pmem,
|
||
CPU_SIZE_T size)
|
||
{
|
||
Mem_Set((void *)pmem,
|
||
(CPU_INT08U)0, /* See Note #2. */
|
||
(CPU_SIZE_T)size);
|
||
}
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* Mem_Set()
|
||
*
|
||
* Description : Fill data buffer with specified data octet.
|
||
*
|
||
* Argument(s) : pmem Pointer to memory buffer to fill with specified data octet.
|
||
*
|
||
* data_val Data fill octet value.
|
||
*
|
||
* size Number of data buffer octets to fill.
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : various.
|
||
*
|
||
* Note(s) : (1) Null sets allowed (i.e. 0-octet size).
|
||
*
|
||
* (2) For best CPU performance, optimized to fill data buffer using 'CPU_ALIGN'-sized data words.
|
||
*
|
||
* (a) Since many word-aligned processors REQUIRE that multi-octet words be accessed on
|
||
* word-aligned addresses, 'CPU_ALIGN'd words MUST be accessed on 'CPU_ALIGN'd addresses.
|
||
*
|
||
* (3) Modulo arithmetic is used to determine whether a memory buffer starts on a 'CPU_ALIGN'
|
||
* address boundary.
|
||
*
|
||
* Modulo arithmetic in ANSI-C REQUIREs operations performed on integer values. Thus,
|
||
* address values MUST be cast to an appropriately-sized integer value PRIOR to any
|
||
* mem_align_modulo arithmetic operation.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
void Mem_Set (void *pmem,
|
||
CPU_INT08U data_val,
|
||
CPU_SIZE_T size)
|
||
{
|
||
CPU_SIZE_T size_rem;
|
||
CPU_ALIGN data_align;
|
||
CPU_ALIGN *pmem_align;
|
||
CPU_INT08U *pmem_08;
|
||
CPU_INT08U mem_align_modulo;
|
||
CPU_INT08U i;
|
||
|
||
|
||
if (size < 1) { /* See Note #1. */
|
||
return;
|
||
}
|
||
if (pmem == (void *)0) {
|
||
return;
|
||
}
|
||
|
||
|
||
data_align = 0;
|
||
for (i = 0; i < sizeof(CPU_ALIGN); i++) { /* Fill each data_align octet with data val. */
|
||
data_align <<= DEF_OCTET_NBR_BITS;
|
||
data_align |= (CPU_ALIGN)data_val;
|
||
}
|
||
|
||
size_rem = (CPU_SIZE_T)size;
|
||
mem_align_modulo = (CPU_INT08U)((CPU_ADDR)pmem % sizeof(CPU_ALIGN)); /* See Note #3. */
|
||
|
||
pmem_08 = (CPU_INT08U *)pmem;
|
||
if (mem_align_modulo != 0) { /* If leading octets avail, ... */
|
||
i = mem_align_modulo;
|
||
while ((size_rem > 0) && /* ... start mem buf fill with leading octets ... */
|
||
(i < sizeof(CPU_ALIGN ))) { /* ... until next CPU_ALIGN word boundary. */
|
||
*pmem_08++ = data_val;
|
||
size_rem -= sizeof(CPU_INT08U);
|
||
i++;
|
||
}
|
||
}
|
||
|
||
pmem_align = (CPU_ALIGN *)pmem_08; /* See Note #2a. */
|
||
while (size_rem >= sizeof(CPU_ALIGN)) { /* While mem buf aligned on CPU_ALIGN word boundaries, */
|
||
*pmem_align++ = data_align; /* ... fill mem buf with CPU_ALIGN-sized data. */
|
||
size_rem -= sizeof(CPU_ALIGN);
|
||
}
|
||
|
||
pmem_08 = (CPU_INT08U *)pmem_align;
|
||
while (size_rem > 0) { /* Finish mem buf fill with trailing octets. */
|
||
*pmem_08++ = data_val;
|
||
size_rem -= sizeof(CPU_INT08U);
|
||
}
|
||
}
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* Mem_Copy()
|
||
*
|
||
* Description : Copy data octets from one buffer to another buffer.
|
||
*
|
||
* Argument(s) : pdest Pointer to destination memory buffer.
|
||
*
|
||
* psrc Pointer to source memory buffer.
|
||
*
|
||
* size Number of data buffer octets to copy.
|
||
*
|
||
* Return(s) : none.
|
||
*
|
||
* Caller(s) : various.
|
||
*
|
||
* Note(s) : (1) Null copies allowed (i.e. 0-octet size).
|
||
*
|
||
* (2) Memory buffers NOT checked for overlapping.
|
||
*
|
||
* (3) For best CPU performance, optimized to fill data buffer using 'CPU_ALIGN'-sized data words.
|
||
*
|
||
* (a) Since many word-aligned processors REQUIRE that multi-octet words be accessed on
|
||
* word-aligned addresses, 'CPU_ALIGN'd words MUST be accessed on 'CPU_ALIGN'd addresses.
|
||
*
|
||
* (4) Modulo arithmetic is used to determine whether a memory buffer starts on a 'CPU_ALIGN'
|
||
* address boundary.
|
||
*
|
||
* Modulo arithmetic in ANSI-C REQUIREs operations performed on integer values. Thus,
|
||
* address values MUST be cast to an appropriately-sized integer value PRIOR to any
|
||
* mem_align_modulo arithmetic operation.
|
||
*********************************************************************************************************
|
||
*/
|
||
/*$PAGE*/
|
||
#if ((!defined(uC_CFG_OPTIMIZE_ASM_EN)) || \
|
||
((defined(uC_CFG_OPTIMIZE_ASM_EN)) && \
|
||
(uC_CFG_OPTIMIZE_ASM_EN != DEF_ENABLED)))
|
||
void Mem_Copy (void *pdest,
|
||
void *psrc,
|
||
CPU_SIZE_T size)
|
||
{
|
||
CPU_SIZE_T size_rem;
|
||
CPU_ALIGN *pmem_align_dest;
|
||
CPU_ALIGN *pmem_align_src;
|
||
CPU_INT08U *pmem_08_dest;
|
||
CPU_INT08U *pmem_08_src;
|
||
CPU_INT08U i;
|
||
CPU_INT08U mem_align_modulo_dest;
|
||
CPU_INT08U mem_align_modulo_src;
|
||
CPU_BOOLEAN mem_aligned;
|
||
|
||
|
||
if (size < 1) { /* See Note #1. */
|
||
return;
|
||
}
|
||
if (pdest == (void *)0) {
|
||
return;
|
||
}
|
||
if (psrc == (void *)0) {
|
||
return;
|
||
}
|
||
|
||
|
||
size_rem = (CPU_SIZE_T )size;
|
||
|
||
pmem_08_dest = (CPU_INT08U *)pdest;
|
||
pmem_08_src = (CPU_INT08U *)psrc;
|
||
/* See Note #4. */
|
||
mem_align_modulo_dest = (CPU_INT08U )((CPU_ADDR)pmem_08_dest % sizeof(CPU_ALIGN));
|
||
mem_align_modulo_src = (CPU_INT08U )((CPU_ADDR)pmem_08_src % sizeof(CPU_ALIGN));
|
||
|
||
mem_aligned = (mem_align_modulo_dest == mem_align_modulo_src) ? DEF_YES : DEF_NO;
|
||
|
||
if (mem_aligned == DEF_YES) { /* If mem bufs' alignment offset equal, ... */
|
||
/* ... optimize copy for mem buf alignment. */
|
||
if (mem_align_modulo_dest != 0) { /* If leading octets avail, ... */
|
||
i = mem_align_modulo_dest;
|
||
while ((size_rem > 0) && /* ... start mem buf copy with leading octets ... */
|
||
(i < sizeof(CPU_ALIGN ))) { /* ... until next CPU_ALIGN word boundary. */
|
||
*pmem_08_dest++ = *pmem_08_src++;
|
||
size_rem -= sizeof(CPU_INT08U);
|
||
i++;
|
||
}
|
||
}
|
||
|
||
pmem_align_dest = (CPU_ALIGN *)pmem_08_dest; /* See Note #3a. */
|
||
pmem_align_src = (CPU_ALIGN *)pmem_08_src;
|
||
while (size_rem >= sizeof(CPU_ALIGN)) { /* While mem bufs aligned on CPU_ALIGN word boundaries, */
|
||
*pmem_align_dest++ = *pmem_align_src++; /* ... copy psrc to pdest with CPU_ALIGN-sized words. */
|
||
size_rem -= sizeof(CPU_ALIGN);
|
||
}
|
||
|
||
pmem_08_dest = (CPU_INT08U *)pmem_align_dest;
|
||
pmem_08_src = (CPU_INT08U *)pmem_align_src;
|
||
}
|
||
|
||
while (size_rem > 0) { /* For unaligned mem bufs or trailing octets, ... */
|
||
*pmem_08_dest++ = *pmem_08_src++; /* ... copy psrc to pdest by octets. */
|
||
size_rem -= sizeof(CPU_INT08U);
|
||
}
|
||
}
|
||
#endif
|
||
|
||
|
||
/*$PAGE*/
|
||
/*
|
||
*********************************************************************************************************
|
||
* Mem_Cmp()
|
||
*
|
||
* Description : Verify that ALL data octets in two memory buffers are identical in sequence.
|
||
*
|
||
* Argument(s) : p1_mem Pointer to first memory buffer.
|
||
*
|
||
* p2_mem Pointer to second memory buffer.
|
||
*
|
||
* size Number of data buffer octets to compare.
|
||
*
|
||
* Return(s) : DEF_YES, if 'size' number of data octets are identical in both memory buffers.
|
||
*
|
||
* DEF_NO, otherwise.
|
||
*
|
||
* Caller(s) : various.
|
||
*
|
||
* Note(s) : (1) Null compares allowed (i.e. 0-octet size); 'DEF_YES' returned to indicate identical
|
||
* null compare.
|
||
*
|
||
* (2) Many memory buffer comparisons vary ONLY in the least significant octets -- e.g.
|
||
* network address buffers. Consequently, memory buffer comparison is more efficient
|
||
* if the comparison starts from the end of the memory buffers which will abort sooner
|
||
* on dissimilar memory buffers that vary only in the least significant octets.
|
||
*
|
||
* (3) For best CPU performance, optimized to fill data buffer using 'CPU_ALIGN'-sized data words.
|
||
*
|
||
* (a) Since many word-aligned processors REQUIRE that multi-octet words be accessed on
|
||
* word-aligned addresses, 'CPU_ALIGN'd words MUST be accessed on 'CPU_ALIGN'd addresses.
|
||
*
|
||
* (4) Modulo arithmetic is used to determine whether a memory buffer starts on a 'CPU_ALIGN'
|
||
* address boundary.
|
||
*
|
||
* Modulo arithmetic in ANSI-C REQUIREs operations performed on integer values. Thus,
|
||
* address values MUST be cast to an appropriately-sized integer value PRIOR to any
|
||
* mem_align_modulo arithmetic operation.
|
||
********************************************************************************************************
|
||
*/
|
||
/*$PAGE*/
|
||
CPU_BOOLEAN Mem_Cmp (void *p1_mem,
|
||
void *p2_mem,
|
||
CPU_SIZE_T size)
|
||
{
|
||
CPU_SIZE_T size_rem;
|
||
CPU_ALIGN *p1_mem_align;
|
||
CPU_ALIGN *p2_mem_align;
|
||
CPU_INT08U *p1_mem_08;
|
||
CPU_INT08U *p2_mem_08;
|
||
CPU_INT08U i;
|
||
CPU_INT08U mem_align_modulo_1;
|
||
CPU_INT08U mem_align_modulo_2;
|
||
CPU_BOOLEAN mem_aligned;
|
||
CPU_BOOLEAN mem_cmp;
|
||
|
||
|
||
if (size < 1) { /* See Note #1. */
|
||
return (DEF_YES);
|
||
}
|
||
if (p1_mem == (void *)0) {
|
||
return (DEF_NO);
|
||
}
|
||
if (p2_mem == (void *)0) {
|
||
return (DEF_NO);
|
||
}
|
||
|
||
|
||
mem_cmp = DEF_YES;
|
||
size_rem = size;
|
||
/* Start @ end of mem bufs (see Note #2). */
|
||
p1_mem_08 = (CPU_INT08U *)p1_mem + size;
|
||
p2_mem_08 = (CPU_INT08U *)p2_mem + size;
|
||
/* See Note #4. */
|
||
mem_align_modulo_1 = (CPU_INT08U )((CPU_ADDR)p1_mem_08 % sizeof(CPU_ALIGN));
|
||
mem_align_modulo_2 = (CPU_INT08U )((CPU_ADDR)p2_mem_08 % sizeof(CPU_ALIGN));
|
||
|
||
mem_aligned = (mem_align_modulo_1 == mem_align_modulo_2) ? DEF_YES : DEF_NO;
|
||
|
||
if (mem_aligned == DEF_YES) { /* If mem bufs' alignment offset equal, ... */
|
||
/* ... optimize cmp for mem buf alignment. */
|
||
if (mem_align_modulo_1 != 0) { /* If trailing octets avail, ... */
|
||
i = mem_align_modulo_1;
|
||
while ((mem_cmp == DEF_YES) && /* ... cmp mem bufs while identical & ... */
|
||
(size_rem > 0) && /* ... start mem buf cmp with trailing octets ... */
|
||
(i > 0)) { /* ... until next CPU_ALIGN word boundary. */
|
||
p1_mem_08--;
|
||
p2_mem_08--;
|
||
if (*p1_mem_08 != *p2_mem_08) { /* If ANY data octet(s) NOT identical, cmp fails. */
|
||
mem_cmp = DEF_NO;
|
||
}
|
||
size_rem -= sizeof(CPU_INT08U);
|
||
i--;
|
||
}
|
||
}
|
||
|
||
if (mem_cmp == DEF_YES) { /* If cmp still identical, cmp aligned mem bufs. */
|
||
p1_mem_align = (CPU_ALIGN *)p1_mem_08; /* See Note #3a. */
|
||
p2_mem_align = (CPU_ALIGN *)p2_mem_08;
|
||
|
||
while ((mem_cmp == DEF_YES) && /* Cmp mem bufs while identical & ... */
|
||
(size_rem >= sizeof(CPU_ALIGN))) { /* ... mem bufs aligned on CPU_ALIGN word boundaries. */
|
||
p1_mem_align--;
|
||
p2_mem_align--;
|
||
if (*p1_mem_align != *p2_mem_align) { /* If ANY data octet(s) NOT identical, cmp fails. */
|
||
mem_cmp = DEF_NO;
|
||
}
|
||
size_rem -= sizeof(CPU_ALIGN);
|
||
}
|
||
|
||
p1_mem_08 = (CPU_INT08U *)p1_mem_align;
|
||
p2_mem_08 = (CPU_INT08U *)p2_mem_align;
|
||
}
|
||
}
|
||
|
||
while ((mem_cmp == DEF_YES) && /* Cmp mem bufs while identical ... */
|
||
(size_rem > 0)) { /* ... for unaligned mem bufs or trailing octets. */
|
||
p1_mem_08--;
|
||
p2_mem_08--;
|
||
if (*p1_mem_08 != *p2_mem_08) { /* If ANY data octet(s) NOT identical, cmp fails. */
|
||
mem_cmp = DEF_NO;
|
||
}
|
||
size_rem -= sizeof(CPU_INT08U);
|
||
}
|
||
|
||
return (mem_cmp);
|
||
}
|
||
|