Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions dmod-config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#define DMOD_USE_DIRENT @DMOD_USE_DIRENT@
#define DMOD_USE_ASSERT @DMOD_USE_ASSERT@
#define DMOD_USE_PTHREAD @DMOD_USE_PTHREAD@
#define DMOD_USE_NANOSLEEP @DMOD_USE_NANOSLEEP@
#define DMOD_USE_MMAN @DMOD_USE_MMAN@
#define DMOD_USE_ALIGNED_ALLOC @DMOD_USE_ALIGNED_ALLOC@
#define DMOD_USE_ALIGNED_MALLOC_MOCK @DMOD_USE_ALIGNED_MALLOC_MOCK@
Expand Down
3 changes: 3 additions & 0 deletions dmod-defaults.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ endif()
if (NOT DEFINED DMOD_USE_PTHREAD)
set(DMOD_USE_PTHREAD ON)
endif()
if (NOT DEFINED DMOD_USE_NANOSLEEP)
set(DMOD_USE_NANOSLEEP ON)
endif()
if (NOT DEFINED DMOD_USE_MMAN)
set(DMOD_USE_MMAN ON)
endif()
Expand Down
7 changes: 7 additions & 0 deletions inc/dmod_sal.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ DMOD_BUILTIN_API(Dmod, 1.0, void*, _AlignedMallocEx, ( size_t Size, size_t Al
DMOD_BUILTIN_API(Dmod, 1.0, void, _FreeModule, ( const char* ModuleName ) );
DMOD_BUILTIN_API(Dmod, 1.0, size_t, _ReadMemory, ( uintptr_t Address, void* Buffer, size_t Size ) );
DMOD_BUILTIN_API(Dmod, 1.0, size_t, _WriteMemory, ( uintptr_t Address, const void* Buffer, size_t Size ) );
DMOD_BUILTIN_API(Dmod, 1.0, bool, _IsRam, ( const void* Address ) );
DMOD_BUILTIN_API(Dmod, 1.0, bool, _IsRom, ( const void* Address ) );
DMOD_BUILTIN_API(Dmod, 1.0, bool, _IsDma, ( const void* Address ) );
DMOD_BUILTIN_API(Dmod, 1.0, bool, _IsExt, ( const void* Address ) );
DMOD_BUILTIN_API(Dmod, 1.0, bool, _IsAddressValid, ( const void* Address ) );
//! @}

/**
Expand Down Expand Up @@ -266,6 +271,8 @@ DMOD_BUILTIN_API(Dmod, 1.0, void*, _Mutex_New, ( bool Recursive ) );
DMOD_BUILTIN_API(Dmod, 1.0, int , _Mutex_Lock, ( void* Mutex ) );
DMOD_BUILTIN_API(Dmod, 1.0, int , _Mutex_Unlock, ( void* Mutex ) );
DMOD_BUILTIN_API(Dmod, 1.0, void , _Mutex_Delete, ( void* Mutex ) );
DMOD_BUILTIN_API(Dmod, 1.0, bool , _DelayUs, ( uint64_t Microseconds ) );
DMOD_BUILTIN_API(Dmod, 1.0, bool , _SleepMs, ( uint64_t Milliseconds ) );

//! @}

Expand Down
163 changes: 163 additions & 0 deletions src/system/if/dmod_if_rawmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,3 +207,166 @@ DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, size_t, _WriteMemory, ( uintptr_t Add
memcpy((void*)Address, Buffer, Size);
return Size;
}

/**
* @brief Helper function to parse address from environment variable
*
* @param EnvName Environment variable name
*
* @return Parsed address or 0 if not set or invalid
*/
static uintptr_t Dmod_GetEnvAddress(const char* EnvName)
{
const char* value = Dmod_GetEnv(EnvName);
if (value == NULL || value[0] == '\0')
{
return 0;
}

// Parse hex or decimal address
uintptr_t addr = 0;
if (value[0] == '0' && value[1] != '\0' && (value[1] == 'x' || value[1] == 'X'))
{
// Hex format
for (int i = 2; value[i] != '\0'; i++)
{
char c = value[i];
addr <<= 4;
if (c >= '0' && c <= '9')
addr |= (c - '0');
else if (c >= 'a' && c <= 'f')
addr |= (c - 'a' + 10);
else if (c >= 'A' && c <= 'F')
addr |= (c - 'A' + 10);
else
return 0; // Invalid character
}
}
else
{
// Decimal format
for (int i = 0; value[i] != '\0'; i++)
{
char c = value[i];
if (c >= '0' && c <= '9')
{
addr = addr * 10 + (c - '0');
}
else
{
return 0; // Invalid character
}
}
}

return addr;
}

/**
* @brief Helper function to check if address is in a memory region
*
* @param Address Address to check
* @param pStart Pointer to static variable for region start address
* @param pEnd Pointer to static variable for region end address
* @param envStart Name of environment variable for start address
* @param envEnd Name of environment variable for end address
*
* @return true if address is in the region, false otherwise
*/
static bool Dmod_IsAddressInRegion(const void* Address, uintptr_t* pStart, uintptr_t* pEnd,
const char* envStart, const char* envEnd)
{
if (Address == NULL)
{
return false;
}

// Read environment variables on first call (cache the values)
*pStart = *pStart != 0 ? *pStart : Dmod_GetEnvAddress(envStart);
*pEnd = *pEnd != 0 ? *pEnd : Dmod_GetEnvAddress(envEnd);

// If not configured, just check if address is not NULL
if (*pEnd == 0)
{
return true; // Address is not NULL, consider it potentially valid
}

uintptr_t addr = (uintptr_t)Address;
return (addr >= *pStart && addr < *pEnd);
}

/**
* @brief Check if address is in RAM
*
* @param Address Address to check
*
* @return true if address is in RAM, false otherwise
*/
DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, bool, _IsRam, ( const void* Address ))
{
static uintptr_t ramStart = 0;
static uintptr_t ramEnd = 0;
return Dmod_IsAddressInRegion(Address, &ramStart, &ramEnd, "DMOD_RAM_START", "DMOD_RAM_END");
}

/**
* @brief Check if address is in ROM
*
* @param Address Address to check
*
* @return true if address is in ROM, false otherwise
*/
DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, bool, _IsRom, ( const void* Address ))
{
static uintptr_t romStart = 0;
static uintptr_t romEnd = 0;
return Dmod_IsAddressInRegion(Address, &romStart, &romEnd, "DMOD_ROM_START", "DMOD_ROM_END");
}

/**
* @brief Check if address is in DMA region
*
* @param Address Address to check
*
* @return true if address is in DMA region, false otherwise
*/
DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, bool, _IsDma, ( const void* Address ))
{
static uintptr_t dmaStart = 0;
static uintptr_t dmaEnd = 0;
return Dmod_IsAddressInRegion(Address, &dmaStart, &dmaEnd, "DMOD_DMA_START", "DMOD_DMA_END");
}

/**
* @brief Check if address is in External memory
*
* @param Address Address to check
*
* @return true if address is in External memory, false otherwise
*/
DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, bool, _IsExt, ( const void* Address ))
{
static uintptr_t extStart = 0;
static uintptr_t extEnd = 0;
return Dmod_IsAddressInRegion(Address, &extStart, &extEnd, "DMOD_EXT_START", "DMOD_EXT_END");
}

/**
* @brief Check if address is valid (in any known memory region)
*
* @param Address Address to check
*
* @return true if address is valid (RAM || ROM || DMA || EXT), false otherwise
*/
DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, bool, _IsAddressValid, ( const void* Address ))
{
if (Address == NULL)
{
return false;
}

return Dmod_IsRam(Address) ||
Dmod_IsRom(Address) ||
Dmod_IsDma(Address) ||
Dmod_IsExt(Address);
}
80 changes: 80 additions & 0 deletions src/system/if/dmod_if_rtos.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
# define __USE_UNIX98
# include <pthread.h>
#endif
#if DMOD_USE_NANOSLEEP
# include <unistd.h>
# include <time.h>
#endif

//==============================================================================
// FUNCTIONS DECLARATIONS
Expand Down Expand Up @@ -173,3 +177,79 @@ DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, void, _Mutex_Delete, ( void* Mutex ))
}
#endif
}

/**
* @brief Delay execution for a specified number of microseconds
*
* @param Microseconds Number of microseconds to delay
*
* @return true if delay was successful, false otherwise
*/
DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, bool, _DelayUs, ( uint64_t Microseconds ))
{
#if DMOD_USE_NANOSLEEP
if (Microseconds == 0)
{
return true;
}

// Use nanosleep for precision
struct timespec ts;
ts.tv_sec = Microseconds / 1000000;
ts.tv_nsec = (Microseconds % 1000000) * 1000;

while (nanosleep(&ts, &ts) == -1)
{
// Continue if interrupted by signal
if (errno != EINTR)
{
return false;
}
}

return true;
#else
// Platform not supported
(void)Microseconds;
DMOD_LOG_WARN("Dmod_DelayUs interface not implemented for this platform\n");
return false;
#endif
}

/**
* @brief Sleep for a specified number of milliseconds
*
* @param Milliseconds Number of milliseconds to sleep
*
* @return true if sleep was successful, false otherwise
*/
DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, bool, _SleepMs, ( uint64_t Milliseconds ))
{
#if DMOD_USE_NANOSLEEP
if (Milliseconds == 0)
{
return true;
}

// Use nanosleep for better precision
struct timespec ts;
ts.tv_sec = Milliseconds / 1000;
ts.tv_nsec = (Milliseconds % 1000) * 1000000;

while (nanosleep(&ts, &ts) == -1)
{
// Continue if interrupted by signal
if (errno != EINTR)
{
return false;
}
}

return true;
#else
// Platform not supported
(void)Milliseconds;
DMOD_LOG_WARN("Dmod_SleepMs interface not implemented for this platform\n");
return false;
#endif
}
2 changes: 2 additions & 0 deletions tests/system/if/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@ set(TEST_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/tests_dmod_dir.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tests_dmod_snprintf.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tests_dmod_env.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tests_dmod_memregion.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tests_dmod_delay.cpp
PARENT_SCOPE
)
Loading
Loading