This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM5728: Unhandled fault: asynchronous external abort (0x1211)

Part Number: AM5728

Hi,

My customer reported "Unhandled fault: asynchronous external abort (0x1211)" when CPU executes strexd instruction.
The issue happens;
- On any boards.
- Whenever function SYS_ATOMIC_COMPARE_AND_SWAP64(pSrc, old_value, old_value, result); is executed.
- The above function accesses to MRAM mapped at 0x1600_0000 to 0x161F_4FFF (physical address).
- MRAM accesses with other functions are working fine. 
- RT-Linux SDK is used (kernel version is 4.19).

Here is DBG log.

Thread 17 "BlkDrvUdp" received signal SIGBUS, Bus error.
[Switching to Thread 0xb04fe460 (LWP 507)]
0x002fc384 in SysCpuReadInt64 (pResult=<optimized out>, pSrc=<optimized out>) at ../../../Components/SysCpuHandling/SysCpuHandling.c:340
340     ../../../Components/SysCpuHandling/SysCpuHandling.c: No such file or directory.
(gdb) bt
#0  0x002fc384 in SysCpuReadInt64 (pResult=<optimized out>, pSrc=<optimized out>) at ../../../Components/SysCpuHandling/SysCpuHandling.c:340
#1  SysCpuReadInt64 (pResult=<synthetic pointer>, pSrc=0xb1eb4018) at ../../../Components/SysCpuHandling/SysCpuHandling.c:309
#2  SysCpuReadValueAtomic (pSrc=pSrc@entry=0xb1eb4018, pDest=0xb04fcf98, nLen=<optimized out>) at ../../../Components/SysCpuHandling/SysCpuHandling.c:634
#3  0x0018d1a6 in ReadValueAtomic (pDst=pDst@entry=0xb04fcf98, pSrc=pSrc@entry=0xb1eb4018, nLen=8) at ../../../Components/CmpMonitor2/CmpMonitor2.c:640
#4  0x0018d29e in WriteReadValue (pData=0xb1eb4018 <error: Cannot access memory at address 0xb1eb4018>, pReadExp=0x0, pWriter=0xb04fd18c) at ../../../Components/CmpMonitor2/CmpMonitor2.c:702
#5  ExecuteReadExp (pApp=pApp@entry=0x420678 <s_StaticAppList+60>, pReadExp=pReadExp@entry=0xb04fd030, pWriter=pWriter@entry=0xb04fd18c) at ../../../Components/CmpMonitor2/CmpMonitor2.c:967
#6  0x0018d7e8 in ProcessReadExpList2 (pApp=<optimized out>, pWriter=0xb04fd18c, pReader=0xb04fd044) at ../../../Components/CmpMonitor2/CmpMonitor2.c:1030
#7  ProcessService (pduSendBuffer=..., pWriter=0xb04fd18c, pReader=0xb04fd044, pHeader=<optimized out>) at ../../../Components/CmpMonitor2/CmpMonitor2.c:1733
#8  Monitoring2ServiceHandler (ulChannelId=<optimized out>, pHeader=<optimized out>, pduData=..., pduSendBuffer=...) at ../../../Components/CmpMonitor2/CmpMonitor2.c:363
#9  0x002dba96 in ServerAppHandleRequest3 (ulChannelId=ulChannelId@entry=31296, pduRequest=..., pduReply=..., bFirstCall=1, bFirstCall@entry=1212875) at ../../../Components/CmpSrv/CmpSrv.c:612
#10 0x002d5682 in SecChServerHandleRequest (ui32ChannelHandle=ui32ChannelHandle@entry=31296, pduRequest=..., pduReply=..., bFirstCall=bFirstCall@entry=1) at ../../../Components/CmpSecureChannel/CmpSecureChannelServer.c:440
#11 0x001281ca in NetServerMessageReceived3 (pChBuffer=pChBuffer@entry=0xb490b010, pduData=..., bFirstCall=bFirstCall@entry=1) at ../../../Components/CmpChannelServer/CmpChannelServer.c:971
#12 0x0012736a in HandleL4DataPackage (pChBuffer=0xb490b010, nSize=256, pDataPkg=<optimized out>, addrSender=...) at ../../../Components/CmpChannelMgr/CmpChannelMgr.c:839
#13 HandleL4Data (byPkgType=<optimized out>, pduData=..., addrSender=...) at ../../../Components/CmpChannelMgr/CmpChannelMgr.c:937
#14 ChannelMgrHandleData (hRouter=hRouter@entry=0xb4a01718, hNetworkInterface=hNetworkInterface@entry=0xffff, byServiceId=<optimized out>, byMessageId=<optimized out>, addrSender=..., addrReceiver=..., pduData=..., nRouterError=0)
    at ../../../Components/CmpChannelMgr/CmpChannelMgr.c:1690
#15 0x002cd300 in HandleLocally (pRouter=pRouter@entry=0xb4a01718, pniSender=pniSender@entry=0xb4a01718, pnaSender=pnaSender@entry=0xb04fd9a0, pHeader=pHeader@entry=0xb04fda58, pduContent=..., addrSender=..., addrReceiver=...)
    at ../../../Components/CmpRouter/CmpRouter.c:785
#16 0x002cee38 in RoutePackage (pRouter=0xb4a01718, pNetworkSender=pNetworkSender@entry=0xb4a01718, addrReceiver=..., addrSender=..., naSender=..., pduData=..., nDataOffset=2, bUseQueue=-1263770880) at ../../../Components/CmpRouter/CmpRouter.c:1409
#17 0x002cf530 in RouterHandleData (hNetwork=<optimized out>, naSender=..., pduData=..., bIsBroadcast=bIsBroadcast@entry=0) at ../../../Components/CmpRouter/CmpRouter.c:2156
#18 0x000b7eba in UdpReceiveBlock (iDev=<optimized out>, iDev@entry=0, iCount=iCount@entry=2, pfdDataAvailable=pfdDataAvailable@entry=0xb04fdd14) at ../../../Components/CmpBlkDrvUdp/CmpBlkDrvUdp.c:563
#19 0x000b7f4a in UdpReceiveBlocks (pfdDataAvailable=pfdDataAvailable@entry=0xb04fdd14) at ../../../Components/CmpBlkDrvUdp/CmpBlkDrvUdp.c:583
#20 0x000b88f4 in CommunicationThread (ptp=0x51751c <s_StaticTaskList+3204>) at ../../../Components/CmpBlkDrvUdp/CmpBlkDrvUdp.c:393
#21 0x003137f8 in SysTaskFrame (pTask=0x517510 <s_StaticTaskList+3192>) at ../Sys/SysTaskLinux.c:439
#22 0xb4d5fb00 in start_thread (arg=0xaeeece45) at pthread_create.c:486
#23 0xb4cd42fc in ?? () at ../sysdeps/unix/sysv/linux/arm/clone.S:73 from /lib/libc.so.6
Backtrace stopped: previous frame identical to this frame (corrupt stack?)


The SYS_ATOMIC_COMPARE_AND_SWAP64() is at line 340 in SysCpuHandling.c.
#include "CmpStd.h"
#include "SysCpuHandlingDep.h"
#include "CmpAppItf.h"

/*#define SYSCPUHANDLING_MODULETEST*/

static RTS_HANDLE s_hRWLAtomicOperation = RTS_INVALID_HANDLE;

USE_STMT

#ifndef SYSCPU_EXTLIBCALL_GET_REGISTER_SAVE_AREA
	#define SYSCPU_EXTLIBCALL_GET_REGISTER_SAVE_AREA(sa)	sa
#endif

/* ------------- Component Manager functions --------------- */
#ifdef CPLUSPLUS
	static CSysCpuHandling *s_pCSysCpuHandling = NULL;
#endif

#ifndef RTS_COMPACT_MICRO

#ifdef SYSCPUHANDLING_MODULETEST
	static RTS_RESULT ModuleTest(void);
#endif

DLL_DECL int CDECL ComponentEntry(INIT_STRUCT *pInitStruct)
/*	Used to exchange function pointers between component manager and components.
	Called at startup for each component.
	pInitStruct:			IN	Pointer to structure with:
		pfExportFunctions	OUT Pointer to function that exports component functions
		pfImportFunctions	OUT Pointer to function that imports functions from other components
		pfGetVersion		OUT Pointer to function to get component version
		pfRegisterAPI		IN	Pointer to component manager function to register a API function
		pfGetAPI			IN	Pointer to component manager function to get a API function
		pfCallHook			IN	Pointer to component manager function to call a hook function
	Return					ERR_OK if library could be initialized, else error code
*/
{
	pInitStruct->CmpId = COMPONENT_ID;
	pInitStruct->pfExportFunctions = ExportFunctions;
	pInitStruct->pfImportFunctions = ImportFunctions;
	pInitStruct->pfGetVersion = CmpGetVersion;
	pInitStruct->pfHookFunction = HookFunction;
	pInitStruct->pfCreateInstance = CreateInstance;
	pInitStruct->pfDeleteInstance = DeleteInstance;

	SysCpuHandlingOSInit(pInitStruct);

	s_pfCMRegisterAPI = pInitStruct->pfCMRegisterAPI;
	s_pfCMRegisterAPI2 = pInitStruct->pfCMRegisterAPI2;
	s_pfCMGetAPI = pInitStruct->pfCMGetAPI;
	s_pfCMGetAPI2 = pInitStruct->pfCMGetAPI2;
	s_pfCMCallHook = pInitStruct->pfCMCallHook;
	s_pfCMRegisterClass = pInitStruct->pfCMRegisterClass;
	s_pfCMCreateInstance = pInitStruct->pfCMCreateInstance;

#ifdef CPLUSPLUS
	INIT_LOCALS_STMT;
	s_pCSysCpuHandling = NULL;

	if (pInitStruct->pfCMRegisterClass != NULL)
	{
		RTS_HANDLE hClass = pInitStruct->pfCMRegisterClass(COMPONENT_ID, CLASSID_CSysCpuHandling);
		if (hClass == RTS_INVALID_HANDLE)
			return ERR_FAILED;
	}
#endif
	return ERR_OK;
}

static IBase* CDECL CreateInstance(CLASSID cid, RTS_RESULT *pResult)
{
#ifdef CPLUSPLUS
	if (cid == CLASSID_CSysCpuHandling)
	{
		if (s_pCSysCpuHandling == NULL)
			s_pCSysCpuHandling = static_cast<CSysCpuHandling *>(new CSysCpuHandling());
		return (IBase*)s_pCSysCpuHandling->QueryInterface(s_pCSysCpuHandling, ITFID_IBase, pResult);
	}
#endif
	return NULL;
}

static RTS_RESULT CDECL DeleteInstance(IBase *pIBase)
{
#ifdef CPLUSPLUS
	if (pIBase->Release() == 0)
		s_pCSysCpuHandling = NULL;
	return ERR_OK;
#else
	return ERR_NOTIMPLEMENTED;
#endif
}

static int CDECL ExportFunctions()
{
	EXPORT_STMT;
	return ERR_OK;
}

static int CDECL ImportFunctions()
{
	unsigned char by = 0;

	IMPORT_STMT;

	/* If SysCpuTestAndSetBit() returns ERR_NOT_SUPPORTED, the used SysInt functions are not available, so stop loading this component */
	if (SysCpuTestAndSetBit(&by, 1, 1, 1) == ERR_NOT_SUPPORTED)
	{
		if (CHK_LogAdd)
		{
			(void)CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_ERROR, ERR_FAILED, 0, "Import of ApiFunction <api>SysIntEnableAll</api> failed\n");
			(void)CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_ERROR, ERR_FAILED, 0, "Import of ApiFunction <api>SysIntDisableAll</api> failed\n");
		}
		return ERR_FAILED;
	}
	return ERR_OK;
}

static RTS_UI32 CDECL CmpGetVersion(void)
{
	return CMP_VERSION;
}

#endif

static RTS_RESULT CDECL HookFunction(RTS_UI32 ulHook, RTS_UINTPTR ulParam1, RTS_UINTPTR ulParam2)
{
	RTS_RESULT Result = ERR_OK;
	switch (ulHook)
	{
		case CH_INIT2:
		{
			if (CHK_SysRWLCreate)
			{
				RTS_RESULT Res = ERR_FAILED;

				s_hRWLAtomicOperation = CAL_SysRWLCreate(&Res);
				if (Res != ERR_OK && CHK_LogAdd)
					(void)CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_ERROR, ERR_FAILED, 0, "Creating synchronization object for atomic 64bit access failed.\n");
			}
			break;
		}
		case CH_COMM_CYCLE:
		{
#ifdef RTS_COMPACT_MICRO
			return ERR_NO_COMM_CYCLE;
#else
#ifdef SYSCPUHANDLING_MODULETEST
			ModuleTest();
#endif
			break;
#endif
		}
		case CH_EXIT_SYSTEM:
		{
			EXIT_STMT;
			break;
		}
		case CH_EXIT2:
		{
			if (CHK_SysRWLDelete && s_hRWLAtomicOperation != RTS_INVALID_HANDLE)
			{
				CAL_SysRWLDelete(s_hRWLAtomicOperation);
				s_hRWLAtomicOperation = RTS_INVALID_HANDLE;
			}
			break;
		}
		default:
			break;
	}
	if(Result == ERR_OK)
		return SysCpuHandlingOSHookFunction(ulHook, ulParam1, ulParam2);
	return Result;
}

RTS_RESULT CDECL SysCpuTestAndSetBitBase(void* pAddress, int nLen, int iBit, int bSet)
{
	RTS_RESULT Result;
	SYSCPUTESTANDSETBIT_LOCK(pAddress, nLen, iBit, bSet, Result);
	return Result;
}

RTS_RESULT CDECL SysCpuTestAndSet(RTS_UI32* pul, int iBit)
{
	RTS_RESULT Result = SysCpuTestAndSetBit(pul, 4, iBit, 1);
	if (Result == ERR_NOT_SUPPORTED)
		return ERR_OK;
	return Result;
}

RTS_RESULT CDECL SysCpuTestAndReset(RTS_UI32* pul, int iBit)
{
	RTS_RESULT Result = SysCpuTestAndSetBit(pul, 4, iBit, 0);
	if (Result == ERR_NOT_SUPPORTED)
		return ERR_OK;
	return Result;
}

RTS_RESULT CDECL SysCpuGetCallstackEntry3(RTS_I32 bIecCode, RegContext *pContext, void **ppAddress)
{
	RTS_RESULT result = ERR_FAILED;
	RTS_UINTPTR *pSP;

	if (pContext == NULL || ppAddress == NULL)
	{
		if (ppAddress != NULL)
			*ppAddress = NULL;
		return ERR_PARAMETER;
	}
	
	/* Try to find investigate the callstack via IEC stack backtrace */
	if (bIecCode)
		return SysCpuGetCallstackEntry(&pContext->BP, ppAddress);

	/* Try to find the return address in IEC via OS stack backtrace */
	while (SysCpuGetCallstackEntry2(bIecCode, &pContext->BP, ppAddress) == ERR_OK)
	{
		if (!bIecCode)
		{
			if (CAL_SysMemIsValidPointer((void *)*ppAddress, sizeof(void *), 0) != ERR_OK)
				return ERR_NOMEMORY;

			if (!CHK_AppGetApplicationByAreaAddress)
				return ERR_NOT_SUPPORTED;

			if (CAL_AppGetApplicationByAreaAddress(*ppAddress, NULL) == NULL)
				continue;
		}
		return ERR_OK;
	}

	pSP = (RTS_UINTPTR *)pContext->SP;
	if (CAL_SysMemIsValidPointer((void *)pSP, sizeof(pSP), 0) != ERR_OK)
		return ERR_NOMEMORY;

	/* Try to find the return address in IEC via linear search backward on stack for the marker pattern */
	pSP = SysCpuSearchOnStack_(pSP, SYSCPU_STACK_MARKER, &result);
	if (result == ERR_OK && pSP != NULL && *pSP == SYSCPU_STACK_MARKER)
	{
		RTS_UINTPTR stackAlignment;
		RTS_UINTPTR offset = 1;
		RTS_UINTPTR adjOffset = 1;

		pContext->SP = (RTS_UINTPTR)pSP;

		/* The corresponding BP fom the caller in IEC is directly pushed before the marker on the stack! */
#if defined(TRG_DSP)
		pContext->BP = *(pSP - 1);
#else
		pContext->BP = *(pSP + 1);
#endif
		stackAlignment = SYSCPU_STACK_ALIGNMENT;

		for (;;)
		{
			/* The codegenerator always aligned the stack dependent on the processor width! */
			if (((RTS_UINTPTR)pSP % stackAlignment) != 0)
			{
				RTS_UINTPTR alignbytes = ((RTS_UINTPTR)pSP % stackAlignment);
				offset += (alignbytes % sizeof(pSP) + 1);
			}
			/* Before calling external library function, the codegenerator reserves register save area on stack! */
			offset += SYSCPU_EXTLIBCALL_GET_REGISTER_SAVE_AREA(SYSCPU_EXTLIBCALL_REGISTER_SAVE_AREA);

			/* Try to locate the return address of the external library call */			
			*ppAddress = (void *)*(pSP - offset);
			if (*ppAddress == NULL)
				*ppAddress = (void *)*(pSP - 1);
			
			if (*ppAddress == NULL)
				break;

			/* Return address found! It is a valid address in application area */
			if (CAL_AppGetApplicationByAreaAddress(*ppAddress, NULL) != NULL)
				return ERR_OK;

            /* Some processors ( e.g. SH ) can have variable C calling conventions = entries in stack */
			adjOffset = SYSCPU_EXTLIBCALL_ADJUST_OFFSET(offset);
            if ( adjOffset != offset)
            {
            	offset = adjOffset;
            	continue;
            }
 
			/* Some processors have a variable stack alignment of 4 or 8 bytes dependant on the Codegenerator setting in the DeviceDescription! */
			if (stackAlignment == 4)
			{
				stackAlignment = 8;
				offset = 1;
				continue;
			}
			break;
		}
	}
	return ERR_NOMEMORY;	
}

RTS_RESULT CDECL SysCpuSetRegisterValue(RTS_UINTPTR *pRegBuff, RTS_I32 nRegisterNumber, RTS_UINTPTR newValue)
{
	if (pRegBuff == NULL)
		return ERR_PARAMETER;

	pRegBuff[SYSCPU_REGISTER_OFFSET(nRegisterNumber)] = newValue;

	return ERR_OK;
}

RTS_I64 CDECL SysCpuReadInt64(RTS_I64 *pSrc, RTS_RESULT *pResult)
{
	if (pSrc == NULL)
	{
		RTS_SETRESULT(pResult, ERR_PARAMETER);
		return 0;
	}

#if SYSCPU_ALIGNMENT_CHECK_64 > 1
	/* Check alignment, atomic assignment is only possible if pSrc is aligned to allowed boundary */
	if (((RTS_UINTPTR)pSrc % SYSCPU_ALIGNMENT_CHECK_64) != 0)
	{
		RTS_SETRESULT(pResult, ERR_ALIGNMENT);
		return 0;
	}
#endif

#if defined(TRG_64BIT)
	/* on 64bit targets, the atomic assignment is always assured */
	RTS_SETRESULT(pResult, ERR_OK);
	return *pSrc;
#else
	#ifdef SYS_ATOMIC_COMPARE_AND_SWAP64
	{
		/* use operating system function if available */
		RTS_RESULT result;
		RTS_I64 old_value = 0;

		do
		{
			old_value = *pSrc;
			SYS_ATOMIC_COMPARE_AND_SWAP64(pSrc, old_value, old_value, result);
		} while (result != ERR_OK && result != ERR_NOT_SUPPORTED);

		RTS_SETRESULT(pResult, result);
		if (result != ERR_OK)
			return 0;
		return old_value;
	}
	#else
	{
		/* no atomic assignment possible, so use synchronization object to ensure consistency*/
		if (CHK_SysRWLReadLock && CHK_SysRWLReadUnlock && s_hRWLAtomicOperation != RTS_INVALID_HANDLE)
		{
			RTS_I64 iReturnValue;

			CAL_SysRWLReadLock(s_hRWLAtomicOperation);
			iReturnValue = *pSrc;
			CAL_SysRWLReadUnlock(s_hRWLAtomicOperation);

			RTS_SETRESULT(pResult, ERR_OK);
			return iReturnValue;
		}
		/* consistency cannot be assured, so return error */
		else
		{
			RTS_SETRESULT(pResult, ERR_NOT_SUPPORTED);
			return 0;
		}
	}
	#endif	/* SYS_ATOMIC_COMPARE_AND_SWAP64 */
#endif	/* TRG_64BIT */
}

RTS_RESULT CDECL SysCpuWriteInt64(RTS_I64 *pDest, RTS_I64 i64Value)
{
	if (pDest == NULL)
		return ERR_PARAMETER;

#if SYSCPU_ALIGNMENT_CHECK_64 > 1
	/* Check alignment, atomic assignment is only possible if pDest is aligned to allowed boundary */
	if (((RTS_UINTPTR)pDest % SYSCPU_ALIGNMENT_CHECK_64) != 0)
	{
		return ERR_ALIGNMENT;
	}
#endif

#if defined(TRG_64BIT)
	/* on 64bit targets, the atomic assignment is always assured */
	*pDest = i64Value;
	return ERR_OK;
#else
	#ifdef SYS_ATOMIC_COMPARE_AND_SWAP64
	{
		/* use operating system function if available */
		RTS_RESULT result;

		do
		{
			RTS_I64 old_value = *pDest;
			SYS_ATOMIC_COMPARE_AND_SWAP64(pDest, i64Value, old_value, result);
		} while (result != ERR_OK && result != ERR_NOT_SUPPORTED);

		return result;
	}
	#else
	{
		/* no atomic assignment possible, so use synchronization object to ensure consistency*/
		if (CHK_SysRWLWriteLock && CHK_SysRWLWriteUnlock && s_hRWLAtomicOperation != RTS_INVALID_HANDLE)
		{
			CAL_SysRWLWriteLock(s_hRWLAtomicOperation);
			*pDest = i64Value;
			CAL_SysRWLWriteUnlock(s_hRWLAtomicOperation);
			return ERR_OK;
		}
		/* consistency cannot be assured, so return error */
		else
		{
			return ERR_NOT_SUPPORTED;
		}
	}
	#endif	/* SYS_ATOMIC_COMPARE_AND_SWAP64 */
#endif	/* TRG_64BIT */
}

RTS_REAL64 CDECL SysCpuReadReal64(RTS_REAL64 *pSrc, RTS_RESULT *pResult)
{
	if (pSrc == NULL)
	{
		RTS_SETRESULT(pResult, ERR_PARAMETER);
		return 0;
	}

#if SYSCPU_ALIGNMENT_CHECK_64 > 1
	/* Check alignment, atomic assignment is only possible if pSrc is aligned to allowed boundary */
	if (((RTS_UINTPTR)pSrc % SYSCPU_ALIGNMENT_CHECK_64) != 0)
	{
		RTS_SETRESULT(pResult, ERR_ALIGNMENT);
		return 0;
	}
#endif

#if defined(TRG_64BIT)
	/* on 64bit targets, the atomic assignment is always assured */
	RTS_SETRESULT(pResult, ERR_OK);
	return *pSrc;
#else
	#ifdef SYS_ATOMIC_COMPARE_AND_SWAP64
	{
		/* use operating system function if available */
		RTS_RESULT result;
		RTS_REAL64 read_value;
		RTS_I64 old_value = 0;

		do
		{
			memcpy(&old_value, pSrc, sizeof(RTS_I64));
			SYS_ATOMIC_COMPARE_AND_SWAP64((RTS_I64 *)pSrc, old_value, old_value, result);
		} while (result != ERR_OK && result != ERR_NOT_SUPPORTED);

		RTS_SETRESULT(pResult, result);
		memcpy(&read_value, &old_value, sizeof(RTS_I64));
		return read_value;
	}
	#else
	{
		/* no atomic assignment possible, so use synchronization object to ensure consistency*/
		if (CHK_SysRWLReadLock && CHK_SysRWLReadUnlock && s_hRWLAtomicOperation != RTS_INVALID_HANDLE)
		{
			RTS_REAL64 rReturnValue;

			CAL_SysRWLReadLock(s_hRWLAtomicOperation);
			rReturnValue = *pSrc;
			CAL_SysRWLReadUnlock(s_hRWLAtomicOperation);

			RTS_SETRESULT(pResult, ERR_OK);
			return rReturnValue;
		}
		/* consistency cannot be assured, so return error */
		else
		{
			RTS_SETRESULT(pResult, ERR_NOT_SUPPORTED);
			return 0;
		}
	}
	#endif	/* SYS_ATOMIC_COMPARE_AND_SWAP64 */
#endif	/* TRG_64BIT */
}

RTS_RESULT CDECL SysCpuWriteReal64(RTS_REAL64 *pDest, RTS_REAL64 r64Value)
{
	if (pDest == NULL)
		return ERR_PARAMETER;

#if SYSCPU_ALIGNMENT_CHECK_64 > 1
	/* Check alignment, atomic assignment is only possible if pDest is aligned to allowed boundary */
	if (((RTS_UINTPTR)pDest % SYSCPU_ALIGNMENT_CHECK_64) != 0)
	{
		return ERR_ALIGNMENT;
	}
#endif

#if defined(TRG_64BIT)
	/* on 64bit targets, the atomic assignment is always assured */
	*pDest = r64Value;
	return ERR_OK;
#else
	#ifdef SYS_ATOMIC_COMPARE_AND_SWAP64
	{
		/* use operating system function if available */
		RTS_RESULT result;
		RTS_I64 old_value;
		RTS_I64 new_value;

		do
		{
			memcpy(&old_value, pDest, sizeof(RTS_I64));
			memcpy(&new_value, &r64Value, sizeof(RTS_I64));
			SYS_ATOMIC_COMPARE_AND_SWAP64((RTS_I64 *)pDest, new_value, old_value, result);
		} while (result != ERR_OK && result != ERR_NOT_SUPPORTED);
		return result;
	}
	#else
	{
		/* no atomic assignment possible, so use synchronization object to ensure consistency*/
		if (CHK_SysRWLWriteLock && CHK_SysRWLWriteUnlock && s_hRWLAtomicOperation != RTS_INVALID_HANDLE)
		{
			CAL_SysRWLWriteLock(s_hRWLAtomicOperation);
			*pDest = r64Value;
			CAL_SysRWLWriteUnlock(s_hRWLAtomicOperation);
			return ERR_OK;
		}
		/* consistency cannot be assured, so return error */
		else
		{
			return ERR_NOT_SUPPORTED;
		}
	}
	#endif	/* SYS_ATOMIC_COMPARE_AND_SWAP64 */
#endif	/* TRG_64BIT */
}


RTS_RESULT CDECL SysCpuWriteValueAtomic(void* pDest, void* pSrc, RTS_UI32 nLen)
{
	RTS_RESULT result = ERR_FAILED;

	if (pDest == NULL || pSrc == NULL)
		return ERR_PARAMETER;

	switch (nLen)
	{
		case 8:
		{
			RTS_I64 i64;
			memcpy(&i64, (RTS_I64 *)pSrc, sizeof(RTS_I64));
			result = SysCpuWriteInt64((RTS_I64*)pDest, i64);
			break;
		}
		case 4:
		{
#if SYSCPU_ALIGNMENT_CHECK_32 > 1
			if (((RTS_UINTPTR)pDest % SYSCPU_ALIGNMENT_CHECK_32) == 0)
			{
				if (((RTS_UINTPTR)pSrc % SYSCPU_ALIGNMENT_CHECK_32) != 0)
				{
					RTS_UI32 ui32;
					memcpy(&ui32, pSrc, sizeof(RTS_UI32));
					*(RTS_UI32 *)pDest = ui32;
				}
				else
					*(RTS_UI32 *)pDest = *(RTS_UI32 *)pSrc;
				result = ERR_OK;
			}
			else
			{
				result = ERR_ALIGNMENT;
			}
#else
			*(RTS_UI32 *)pDest = *(RTS_UI32 *)pSrc;
			result = ERR_OK;
#endif
			break;
		}
		case 2:
		{
#if SYSCPU_ALIGNMENT_CHECK_16 > 1
			if (((RTS_UINTPTR)pDest % SYSCPU_ALIGNMENT_CHECK_16) == 0)
			{
				if (((RTS_UINTPTR)pSrc % SYSCPU_ALIGNMENT_CHECK_16) != 0)
				{
					RTS_UI16 ui16;
					memcpy(&ui16, pSrc, sizeof(RTS_UI16));
					*(RTS_UI16 *)pDest = ui16;
				}
				else
					*(RTS_UI16 *)pDest = *(RTS_UI16 *)pSrc;
				result = ERR_OK;
			}
			else
			{
				result = ERR_ALIGNMENT;
			}
#else
			*(RTS_UI16 *)pDest = *(RTS_UI16 *)pSrc;
			result = ERR_OK;
#endif
			break;
		}
		case 1:
		{
			*(RTS_UI8 *)pDest = *(RTS_UI8 *)pSrc;
			result = ERR_OK;
			break;
		}
		default:
		{
			result = ERR_PARAMETER;
			break;
		}
	}
	return result;
}

RTS_RESULT CDECL SysCpuReadValueAtomic(void* pSrc, void* pDest, RTS_UI32 nLen)
{
	RTS_RESULT result = ERR_FAILED;
	if (pSrc == NULL || pDest == NULL)
		return ERR_PARAMETER;

	switch (nLen)
	{
		case 8:
		{
			RTS_I64 i64;
			i64 = SysCpuReadInt64((RTS_I64 *)pSrc, &result);
			if (result == ERR_OK)
				memcpy(pDest, &i64, sizeof(RTS_I64));
			break;
		}
		case 4:
		{
#if SYSCPU_ALIGNMENT_CHECK_32 > 1
			if (((RTS_UINTPTR)pSrc % SYSCPU_ALIGNMENT_CHECK_32) == 0)
			{
				if (((RTS_UINTPTR)pDest % SYSCPU_ALIGNMENT_CHECK_32) != 0)
				{
					RTS_UI32 ui32;
					ui32 = *(RTS_UI32 *)pSrc;
					memcpy(pDest, &ui32, sizeof(RTS_UI32));
				}
				else
					*(RTS_UI32 *)pDest = *(RTS_UI32 *)pSrc;
				result = ERR_OK;
			}
			else
			{
				result = ERR_ALIGNMENT;
			}
#else
			*(RTS_UI32 *)pDest = *(RTS_UI32 *)pSrc;
			result = ERR_OK;
#endif
			break;
		}
		case 2:
		{
#if SYSCPU_ALIGNMENT_CHECK_16 > 1
			if (((RTS_UINTPTR)pSrc % SYSCPU_ALIGNMENT_CHECK_16) == 0)
			{
				if (((RTS_UINTPTR)pDest % SYSCPU_ALIGNMENT_CHECK_16) != 0)
				{
					RTS_UI16 ui16;
					ui16 = *(RTS_UI16 *)pSrc;
					memcpy(pDest, &ui16, sizeof(RTS_UI16));
				}
				else
					*(RTS_UI16 *)pDest = *(RTS_UI16 *)pSrc;
				result = ERR_OK;
			}
			else
			{
				result = ERR_ALIGNMENT;
			}
#else
			*(RTS_UI16 *)pDest = *(RTS_UI16 *)pSrc;
			result = ERR_OK;
#endif
			break;
		}
		case 1:
		{
			*(RTS_UI8 *)pDest = *(RTS_UI8 *)pSrc;
			result = ERR_OK;
			break;
		}
		default:
		{
			result = ERR_PARAMETER;
			break;
		}
	}
	return result;
}

RTS_RESULT CDECL SysCpuAtomicCompareAndSwap(void *pAddress, void *pSwapValue, void *pCompareValue, RTS_UI8 valueSize)
{
	RTS_RESULT Result = ERR_NOT_SUPPORTED;

	if (pAddress == NULL || pSwapValue == NULL || pCompareValue == NULL)
		return ERR_PARAMETER;

	switch (valueSize)
	{
		case 4:
		{
#if SYSCPU_ALIGNMENT_CHECK_32 > 1
			if (((RTS_UINTPTR)pAddress % SYSCPU_ALIGNMENT_CHECK_32) != 0)
				return ERR_ALIGNMENT;
#endif

#ifdef  SYS_ATOMIC_COMPARE_AND_SWAP
			SYS_ATOMIC_COMPARE_AND_SWAP((RTS_I32 *)pAddress, (*(RTS_I32 *)pSwapValue), (*(RTS_I32 *)pCompareValue), Result);
#endif
			break;
		}
		case 8: 
		{
#if SYSCPU_ALIGNMENT_CHECK_64 > 1
			if (((RTS_UINTPTR)pAddress % SYSCPU_ALIGNMENT_CHECK_64) != 0)
				return ERR_ALIGNMENT;
#endif

#ifdef  SYS_ATOMIC_COMPARE_AND_SWAP64
			SYS_ATOMIC_COMPARE_AND_SWAP64((RTS_I64 *)pAddress, (*(RTS_I64 *)pSwapValue), (*(RTS_I64 *)pCompareValue), Result);
#endif
			break;
		}
		default:
		{
			Result = ERR_PARAMETER;
			break;
		}
	}
	return Result;
}

RTS_I64 CDECL SysCpuAtomicAdd64(RTS_I64 *pi64Value, RTS_I64 i64Sum, RTS_RESULT *pResult)
{
	RTS_I64 i64ReturnValue = 0;
	RTS_RESULT Result = ERR_NOT_SUPPORTED;

	if (pi64Value == NULL)
	{
		RTS_SETRESULT(pResult, ERR_PARAMETER);
		return 0;
	}
#if SYSCPU_ALIGNMENT_CHECK_64 > 1
	if (((RTS_UINTPTR)pi64Value % SYSCPU_ALIGNMENT_CHECK_64) != 0)
	{
		RTS_SETRESULT(pResult, ERR_ALIGNMENT);
		return 0;
	}
#endif

#if defined(SYS_ATOMIC_ADD64)
	SYS_ATOMIC_ADD64(pi64Value, i64Sum, i64ReturnValue, Result);
#else
	{
		RTS_I64 oldValue;
		RTS_I64 newValue;

		do
		{
			oldValue = *pi64Value;
			newValue = oldValue + i64Sum;
			Result = SysCpuAtomicCompareAndSwap(pi64Value, &newValue, &oldValue, sizeof(oldValue));
		} while (Result != ERR_OK && Result != ERR_NOT_SUPPORTED);

		if (Result == ERR_OK)
			i64ReturnValue = newValue;
	}
#endif
	RTS_SETRESULT(pResult, Result);
	return i64ReturnValue;
}


/* <SIL2/> */
void CDECL CDECL_EXT syscputestandset(syscputestandset_struct *p)
{
#ifdef RTS_SIL2
	if (CHK_SIL2CheckCallerContext && CAL_SIL2CheckCallerContext(RTS_SIL2_CALLERCTX_UNSAFE) != ERR_OK)
		return;
#endif
	p->SysCpuTestAndSet = SysCpuTestAndSet(p->pulValue, p->ulBit);
}

/* <SIL2/> */
void CDECL CDECL_EXT syscputestandreset(syscputestandreset_struct *p)
{
#ifdef RTS_SIL2
	if (CHK_SIL2CheckCallerContext && CAL_SIL2CheckCallerContext(RTS_SIL2_CALLERCTX_UNSAFE) != ERR_OK)
		return;
#endif
	p->SysCpuTestAndReset = SysCpuTestAndReset(p->pulValue, p->ulBit);
}

/* <SIL2/>
 * SysCpuTestAndSetBit() is certified and may therefore be used
 * within a safe context.
 */
void CDECL CDECL_EXT syscputestandsetbit(syscputestandsetbit_struct *p)
{
	p->SysCpuTestAndSetBit = SysCpuTestAndSetBit(p->pAddress, p->nLen, p->iBit, p->bSet);
}

/* <SIL2/> */
void CDECL CDECL_EXT syscpucalliecfuncwithparams(syscpucalliecfuncwithparams_struct *p)
{
	RTS_VOID_FCTPTR* ppfIECFunc;
#ifdef RTS_SIL2
	if (CHK_SIL2CheckCallerContext && CAL_SIL2CheckCallerContext(RTS_SIL2_CALLERCTX_UNSAFE) != ERR_OK)
		return;
#endif
	ppfIECFunc = (RTS_VOID_FCTPTR* )(p->pfIECFunc);
	p->SysCpuCallIecFuncWithParams = SysCpuCallIecFuncWithParams(*ppfIECFunc, p->pParam, p->ulSize);
}

/* <SIL2/>
 * SysCpuAtomicAdd() is certified and may therefore be used
 * within a safe context.
 */
void CDECL CDECL_EXT syscpuatomicadd(syscpuatomicadd_struct *p)
{
	p->SysCpuAtomicAdd = SysCpuAtomicAdd(p->piValue, p->nSum, p->pResult);
}

/* <SIL2/> */
void CDECL CDECL_EXT syscpuatomicadd64(syscpuatomicadd64_struct *p)
{
#ifdef RTS_SIL2
	if (CHK_SIL2CheckCallerContext && CAL_SIL2CheckCallerContext(RTS_SIL2_CALLERCTX_UNSAFE) != ERR_OK)
		return;
#endif
	p->SysCpuAtomicAdd64 = SysCpuAtomicAdd64(p->piValue, p->nSum, p->pResult);
}

/* <SIL2/> */
void CDECL CDECL_EXT syscpuatomiccompareandswap(syscpuatomiccompareandswap_struct *p)
{
#ifdef RTS_SIL2
	if (CHK_SIL2CheckCallerContext && CAL_SIL2CheckCallerContext(RTS_SIL2_CALLERCTX_UNSAFE) != ERR_OK)
		return;
#endif
	p->SysCpuAtomicCompareAndSwap = SysCpuAtomicCompareAndSwap(p->pAddress, p->pSwapValue, p->pCompareValue, p->valueSize);
}

#ifdef SYSCPUHANDLING_MODULETEST
static RTS_RESULT ModuleTest(void)
{
	RTS_I64 i64Value = 0;
	RTS_I64 i64ResultValue = 0;
	RTS_I64 i64ReadValue = 0;
	RTS_I64 i64WriteValue = 0;
	RTS_UI64 ui64Value = 0;
	RTS_UI64 ui64ReadValue = 0;
	RTS_UI64 ui64WriteValue = 0;

	RTS_REAL64 r64Value = 0;
	RTS_REAL64 r64ReadValue = 0;
	RTS_REAL64 r64WriteValue = 0;

	RTS_UI32 errors = 0;
	RTS_RESULT result;

	static RTS_BOOL s_bRunOnce = TRUE;

	if (s_bRunOnce)
	{
#define SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "%" PRI_UI32 ":SysCpuTestAndSetBit2 test:"

		RTS_UI16 ui16Result;
		RTS_UI32 ui32Result;
		RTS_UI32 ui32Expected;

#ifdef RTS_SIXTEENBITBYTES
		static RTS_UI32 aui32AlignedMem[2] = { 0 };
		static RTS_UI32 * const pui32Misaligned  = (RTS_UI32 *)((char *)&aui32AlignedMem[0] + 1); /* misaligned by 1 char */
		static char(*const pacUI32Misaligned)[2] = (char(*)[2])((char *)&aui32AlignedMem[0] + 1);

		SysCpuTestAndSetBit2(pui32Misaligned, sizeof(RTS_UI32), 0, TRUE);
		memcpy(&ui32Result, pui32Misaligned, sizeof(RTS_UI32));
		if (ui32Result == 0x00000001)
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_OK, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "PASS", __LINE__);
		else
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_FAILED, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "FAIL: Expected 0x00000001 Was %08" PRI_X32, __LINE__, ui32Result);

		SysCpuTestAndSetBit2(pui32Misaligned, sizeof(RTS_UI32), 0, FALSE);
		SysCpuTestAndSetBit2(pui32Misaligned, sizeof(RTS_UI32), 15, TRUE);
		memcpy(&ui32Result, pui32Misaligned, sizeof(RTS_UI32));
		if (ui32Result == 0x00008000)
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_OK, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "PASS", __LINE__);
		else
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_FAILED, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "FAIL: Expected 0x00008000 Was %08" PRI_X32, __LINE__, ui32Result);

		SysCpuTestAndSetBit2(pui32Misaligned, sizeof(RTS_UI32), 15, FALSE);
		SysCpuTestAndSetBit2(pui32Misaligned, sizeof(RTS_UI32), 16, TRUE);
		memcpy(&ui32Result, pui32Misaligned, sizeof(RTS_UI32));
		if (ui32Result == 0x00010000)
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_OK, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "PASS", __LINE__);
		else
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_FAILED, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "FAIL: Expected 0x00010000 Was %08" PRI_X32, __LINE__, ui32Result);

		SysCpuTestAndSetBit2(pui32Misaligned, sizeof(RTS_UI32), 16, FALSE);
		SysCpuTestAndSetBit2(pui32Misaligned, sizeof(RTS_UI32), 31, TRUE);
		memcpy(&ui32Result, pui32Misaligned, sizeof(RTS_UI32));
		if (ui32Result == 0x80000000)
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_OK, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "PASS", __LINE__);
		else
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_FAILED, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "FAIL: Expected 0x80000000 Was %08" PRI_X32, __LINE__, ui32Result);
#else
		static RTS_UI32 aui32AlignedMem[6] = { 0 };
		static RTS_UI16 * const pui16Misaligned        = (RTS_UI16 *)((char *)&aui32AlignedMem[0] + 3);
		static char(*const pacUI16Misaligned)[2]       = (char(*)[2])((char *)&aui32AlignedMem[0] + 3);
		static RTS_UI32 * const pui32Misaligned3Chars  = (RTS_UI32 *)((char *)&aui32AlignedMem[2] + 3);
		static char(*const pacUI32Misaligned3Chars)[4] = (char(*)[4])((char *)&aui32AlignedMem[2] + 3);
		static RTS_UI32 * const pui32Misaligned1Char   = (RTS_UI32 *)((char *)&aui32AlignedMem[4] + 1);
		static char(*const pacUI32Misaligned1Char)[4]  = (char(*)[4])((char *)&aui32AlignedMem[4] + 1);
		/* Assignment of the bit in the UINT32 value to the bit in the internal memory representation.
		   Bits in memory to test for pui32Misaligned3Chars: 0, 23, 24, 31
		   Bits in memory to test for pui32Misaligned1Char: 0, 7, 8, 31 */
#ifdef RTS_BIGENDIAN_BYTEORDER
		static const RTS_SIZE siBit0 = 0;
		static const RTS_SIZE siBit7 = 7;
		static const RTS_SIZE siBit8 = 8;
		static const RTS_SIZE siBit23 = 23;
		static const RTS_SIZE siBit24 = 24;
		static const RTS_SIZE siBit31 = 31;
#else
		static const RTS_SIZE siBit0 = 24;
		static const RTS_SIZE siBit7 = 31;
		static const RTS_SIZE siBit8 = 16;
		static const RTS_SIZE siBit23 = 15;
		static const RTS_SIZE siBit24 = 1;
		static const RTS_SIZE siBit31 = 7;
#endif
		SysCpuTestAndSetBit2(pui16Misaligned, sizeof(RTS_UI16), 0, TRUE);
		memcpy(&ui16Result, pui16Misaligned, sizeof(RTS_UI16));
		if (ui16Result == 0x0001)
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_OK, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "PASS", __LINE__);
		else
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_FAILED, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "FAIL: Expected 0x0001 Was %04" PRI_X16, __LINE__, ui16Result);

		SysCpuTestAndSetBit2(pui16Misaligned, sizeof(RTS_UI16), 0, FALSE);
		SysCpuTestAndSetBit2(pui16Misaligned, sizeof(RTS_UI16), 7, TRUE);
		memcpy(&ui16Result, pui16Misaligned, sizeof(RTS_UI16));
		if (ui16Result == 0x0080)
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_OK, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "PASS", __LINE__);
		else
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_FAILED, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "FAIL: Expected 0x0080 Was %04" PRI_X16, __LINE__, ui16Result);

		SysCpuTestAndSetBit2(pui16Misaligned, sizeof(RTS_UI16), 7, FALSE);
		SysCpuTestAndSetBit2(pui16Misaligned, sizeof(RTS_UI16), 8, TRUE);
		memcpy(&ui16Result, pui16Misaligned, sizeof(RTS_UI16));
		if (ui16Result == 0x0100)
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_OK, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "PASS", __LINE__);
		else
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_FAILED, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "FAIL: Expected 0x0100 Was %04" PRI_X16, __LINE__, ui16Result);

		SysCpuTestAndSetBit2(pui16Misaligned, sizeof(RTS_UI16), 8, FALSE);
		SysCpuTestAndSetBit2(pui16Misaligned, sizeof(RTS_UI16), 15, TRUE);
		memcpy(&ui16Result, pui16Misaligned, sizeof(RTS_UI16));
		if (ui16Result == 0x8000)
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_OK, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "PASS", __LINE__);
		else
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_FAILED, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "FAIL: Expected 0x8000 Was %04" PRI_X16, __LINE__, ui16Result);

		/* for pui32Misaligned3Chars:  Bits 0, 23, 24, 31 */
		SysCpuTestAndSetBit2(pui32Misaligned3Chars, sizeof(RTS_UI32), siBit0, TRUE);
		ui32Expected = (RTS_UI32)pow(2.0, siBit0);
		memcpy(&ui32Result, pui32Misaligned3Chars, sizeof(RTS_UI32));
		if (ui32Result == ui32Expected)
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_OK, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "PASS", __LINE__);
		else
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_FAILED, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "FAIL: Expected %08" PRI_X32 " Was %08" PRI_X32, __LINE__, ui32Expected, ui32Result);

		SysCpuTestAndSetBit2(pui32Misaligned3Chars, sizeof(RTS_UI32), siBit0, FALSE);
		SysCpuTestAndSetBit2(pui32Misaligned3Chars, sizeof(RTS_UI32), siBit23, TRUE);
		ui32Expected = (RTS_UI32)pow(2.0, siBit23);
		memcpy(&ui32Result, pui32Misaligned3Chars, sizeof(RTS_UI32));
		if (ui32Result == ui32Expected)
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_OK, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "PASS", __LINE__);
		else
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_FAILED, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "FAIL: Expected %08" PRI_X32 " Was %08" PRI_X32, __LINE__, ui32Expected, ui32Result);

		SysCpuTestAndSetBit2(pui32Misaligned3Chars, sizeof(RTS_UI32), siBit23, FALSE);
		SysCpuTestAndSetBit2(pui32Misaligned3Chars, sizeof(RTS_UI32), siBit24, TRUE);
		ui32Expected = (RTS_UI32)pow(2.0, siBit24);
		memcpy(&ui32Result, pui32Misaligned3Chars, sizeof(RTS_UI32));
		if (ui32Result == ui32Expected)
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_OK, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "PASS", __LINE__);
		else
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_FAILED, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "FAIL: Expected %08" PRI_X32 " Was %08" PRI_X32, __LINE__, ui32Expected, ui32Result);

		SysCpuTestAndSetBit2(pui32Misaligned3Chars, sizeof(RTS_UI32), siBit24, FALSE);
		SysCpuTestAndSetBit2(pui32Misaligned3Chars, sizeof(RTS_UI32), siBit31, TRUE);
		memcpy(&ui32Result, pui32Misaligned3Chars, sizeof(RTS_UI32));
		ui32Expected = (RTS_UI32)pow(2.0, siBit31);
		if (ui32Result == ui32Expected)
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_OK, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "PASS", __LINE__);
		else
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_FAILED, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "FAIL: Expected %08" PRI_X32 " Was %08" PRI_X32, __LINE__, ui32Expected, ui32Result);

		/* for pui32Misaligned1Char: Bits 0, 7, 8, 31 */
		SysCpuTestAndSetBit2(pui32Misaligned1Char, sizeof(RTS_UI32), siBit0, TRUE);
		ui32Expected = (RTS_UI32)pow(2.0, siBit0);
		memcpy(&ui32Result, pui32Misaligned1Char, sizeof(RTS_UI32));
		if (ui32Result == ui32Expected)
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_OK, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "PASS", __LINE__);
		else
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_FAILED, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "FAIL: Expected %08" PRI_X32 " Was %08" PRI_X32, __LINE__, ui32Expected, ui32Result);

		SysCpuTestAndSetBit2(pui32Misaligned1Char, sizeof(RTS_UI32), siBit0, FALSE);
		SysCpuTestAndSetBit2(pui32Misaligned1Char, sizeof(RTS_UI32), siBit7, TRUE);
		ui32Expected = (RTS_UI32)pow(2.0, siBit7);
		memcpy(&ui32Result, pui32Misaligned1Char, sizeof(RTS_UI32));
		if (ui32Result == ui32Expected)
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_OK, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "PASS", __LINE__);
		else
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_FAILED, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "FAIL: Expected %08" PRI_X32 " Was %08" PRI_X32, __LINE__, ui32Expected, ui32Result);

		SysCpuTestAndSetBit2(pui32Misaligned1Char, sizeof(RTS_UI32), siBit7, FALSE);
		SysCpuTestAndSetBit2(pui32Misaligned1Char, sizeof(RTS_UI32), siBit8, TRUE);
		ui32Expected = (RTS_UI32)pow(2.0, siBit8);
		memcpy(&ui32Result, pui32Misaligned1Char, sizeof(RTS_UI32));
		if (ui32Result == ui32Expected)
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_OK, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "PASS", __LINE__);
		else
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_FAILED, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "FAIL: Expected %08" PRI_X32 " Was %08" PRI_X32, __LINE__, ui32Expected, ui32Result);

		SysCpuTestAndSetBit2(pui32Misaligned1Char, sizeof(RTS_UI32), siBit8, FALSE);
		SysCpuTestAndSetBit2(pui32Misaligned1Char, sizeof(RTS_UI32), siBit31, TRUE);
		ui32Expected = (RTS_UI32)pow(2.0, siBit31);
		memcpy(&ui32Result, pui32Misaligned1Char, sizeof(RTS_UI32));
		if (ui32Result == ui32Expected)
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_OK, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "PASS", __LINE__);
		else
			CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_DEBUG, ERR_FAILED, 0, SYSCPUTESTANDSETBIT2_TEST_RESULT_BEGIN "FAIL: Expected %08" PRI_X32 " Was %08" PRI_X32, __LINE__, ui32Expected, ui32Result);
#endif

		s_bRunOnce = FALSE;
	}

#if defined(BASE64BITTYPES_DEFINED) && !defined(SYSINTERNAL_DISABLE_64BIT) && !defined(RTS_DISABLE_64BIT_SUPPORT)
	/**** RTS_I64 ****/
	i64Value = RTS_I64_MAX;
	i64ReadValue = SysCpuReadInt64(&i64Value, &result);
	if (i64ReadValue != i64Value || result != ERR_OK)
		errors += 1;

	i64WriteValue = 0;
	result = SysCpuWriteInt64(&i64WriteValue, i64Value);
	if (i64WriteValue != i64Value || result != ERR_OK)
		errors += 1;

	i64Value = 281474976710655;
	i64ReadValue = SysCpuReadInt64(&i64Value, &result);
	if (i64ReadValue != i64Value || result != ERR_OK)
		errors += 1;

	i64WriteValue = 0;
	result = SysCpuWriteInt64(&i64WriteValue, i64Value);
	if (i64WriteValue != i64Value || result != ERR_OK)
		errors += 1;

	i64ResultValue = SysCpuAtomicAdd64(&i64Value, 2, &result);
	if (result != ERR_OK || i64ResultValue != i64Value)
		errors += 1;

	i64WriteValue = 444;
	i64ReadValue = 123;
	result = SysCpuAtomicCompareAndSwap(&i64Value, &i64WriteValue, &i64ReadValue, sizeof(i64Value));
	if (result != ERR_FAILED)
		errors += 1;
	i64ReadValue = i64Value;
	result = SysCpuAtomicCompareAndSwap(&i64Value, &i64WriteValue, &i64ReadValue, sizeof(i64Value));
	if (result != ERR_OK)
		errors += 1;


	/**** RTS_UI64 ****/
	ui64Value = RTS_UI64_MAX;
	ui64ReadValue = SysCpuReadInt64((RTS_I64*)&ui64Value, &result);
	if (ui64ReadValue != ui64Value || result != ERR_OK)
		errors += 1;

	ui64WriteValue = 0;
	result = SysCpuWriteInt64((RTS_I64*)&ui64WriteValue, (RTS_I64)ui64Value);
	if (ui64WriteValue != ui64Value || result != ERR_OK)
		errors += 1;

	ui64Value = 281474976710655;
	ui64ReadValue = SysCpuReadInt64((RTS_I64*)&ui64Value, &result);
	if (ui64ReadValue != ui64Value || result != ERR_OK)
		errors += 1;

	ui64WriteValue = 0;
	result = SysCpuWriteInt64((RTS_I64*)&ui64WriteValue, (RTS_I64)ui64Value);
	if (ui64WriteValue != ui64Value || result != ERR_OK)
		errors += 1;
#endif

	/**** RTS_REAL64 ****/
	r64Value = RTS_REAL64_MAX;
	r64ReadValue = SysCpuReadReal64(&r64Value, &result);
	if (r64ReadValue != r64Value || result != ERR_OK)
		errors += 1;

	r64WriteValue = 0;
	result = SysCpuWriteReal64(&r64WriteValue, r64Value);
	if (r64WriteValue != r64Value || result != ERR_OK)
		errors += 1;

	r64Value = 1.23456789;
	r64ReadValue = SysCpuReadReal64(&r64Value, &result);
	if (r64ReadValue != r64Value || result != ERR_OK)
		errors += 1;

	r64WriteValue = 0;
	result = SysCpuWriteReal64(&r64WriteValue, r64Value);
	if (r64WriteValue != r64Value || result != ERR_OK)
		errors += 1;

	if (errors == 0)
		return ERR_OK;
	return ERR_FAILED;
}
#endif

RTS_RESULT CDECL SysCpuTestAndSetBit2(
	void *pMemory,
	RTS_SIZE siLen, /* Size in chars of the value pMemory points to. */
	RTS_SIZE siBit, /* Zero-based position of the bit to test within the memory pointed to by pMemory. */
	RTS_BOOL bSet) /* TRUE=Set bit, FALSE=Clear bit. */
{
	RTS_INT *piAlign;
	RTS_SIZE siBitAligned;

	SysCpuTestAndSetBit_AlignPtrInt(pMemory, siLen, siBit, &piAlign, &siBitAligned);

	return SysCpuTestAndSetBit(piAlign, sizeof(RTS_INT), siBitAligned, bSet);
}


Disassembly code:
(gdb) disassemble/m
Dump of assembler code for function SysCpuReadValueAtomic:
309     RTS_I64 CDECL SysCpuReadInt64(RTS_I64 *pSrc, RTS_RESULT *pResult)

310     {
311             if (pSrc == NULL)

312             {
313                     RTS_SETRESULT(pResult, ERR_PARAMETER);
314                     return 0;
315             }
316
317     #if SYSCPU_ALIGNMENT_CHECK_64 > 1
318             /* Check alignment, atomic assignment is only possible if pSrc is aligned to allowed boundary */
319             if (((RTS_UINTPTR)pSrc % SYSCPU_ALIGNMENT_CHECK_64) != 0)

320             {
321                     RTS_SETRESULT(pResult, ERR_ALIGNMENT);
322                     return 0;
323             }
324     #endif
325
326     #if defined(TRG_64BIT)
327             /* on 64bit targets, the atomic assignment is always assured */
328             RTS_SETRESULT(pResult, ERR_OK);
329             return *pSrc;
330     #else
331             #ifdef SYS_ATOMIC_COMPARE_AND_SWAP64
332             {
333                     /* use operating system function if available */
334                     RTS_RESULT result;
335                     RTS_I64 old_value = 0;
336
337                     do

338                     {
339                             old_value = *pSrc;
   0x002fc370 <+44>:    ldrd    r6, r7, [r0]

340                             SYS_ATOMIC_COMPARE_AND_SWAP64(pSrc, old_value, old_value, result);
   0x002fc374 <+48>:    dmb     ish
   0x002fc378 <+52>:    ldrexd  r4, r5, [r0]
   0x002fc37c <+56>:    cmp     r5, r7
   0x002fc37e <+58>:    it      eq
   0x002fc380 <+60>:    cmpeq   r4, r6
   0x002fc382 <+62>:    bne.n   0x2fc38c <SysCpuReadValueAtomic+72>
=> 0x002fc384 <+64>:    strexd  r1, r6, r7, [r0]
   0x002fc388 <+68>:    cmp     r1, #0
   0x002fc38a <+70>:    bne.n   0x2fc378 <SysCpuReadValueAtomic+52>
   0x002fc38c <+72>:    dmb     ish
   0x002fc390 <+76>:    bne.n   0x2fc370 <SysCpuReadValueAtomic+44>
   0x002fc392 <+78>:    mov     r4, sp
   0x002fc394 <+80>:    strd    r6, r7, [sp]


Information registers:
r0 value is 0xb1eb4018. 
(gdb) info registers
r0             0xb1eb4018          2984984600
r1             0xb04fcf98          2958020504
r2             0x0                 0
r3             0xb04fcf98          2958020504
r4             0x0                 0
r5             0x0                 0
r6             0x0                 0
r7             0x0                 0
r8             0x366fa8            3567528
r9             0xf095d44e          4036351054
r10            0xb04fd0d8          2958020824
r11            0x3a88              14984
r12            0x3f6178            4153720
sp             0xb04fcda0          0xb04fcda0
lr             0x18d1a7            1626535
pc             0x2fc384            0x2fc384 <SysCpuReadValueAtomic+64>
cpsr           0x60010030          1610678320
fpscr          0x0                 0


memory map: 
0xb1eb_4000 is mapped at 0x1600_1000(physical address)
root@HX-SDC:/proc/2030# cat maps | grep mem
b0e0c000-b0e0d000 rwxs 4a002000 00:06 8957       /dev/mem
b1eb4000-b20a8000 rwxs 16001000 00:06 8957       /dev/mem
b20c9000-b20ca000 rwxs 16000000 00:06 8957       /dev/mem
b20ca000-b20cb000 rwxs 16000000 00:06 8957       /dev/mem
b419a000-b421a000 rwxs 18100000 00:06 8957       /dev/mem
b4b07000-b4b08000 rwxs 17001000 00:06 8957       /dev/mem
b4b08000-b4b09000 r-xs 17001000 00:06 8957       /dev/mem
b4b09000-b4b0b000 r-xs 1801c000 00:06 8957       /dev/mem
b4b0b000-b4b0d000 r-xs 1800c000 00:06 8957       /dev/mem
b4b0d000-b4b0f000 rwxs 1801e000 00:06 8957       /dev/mem
b4b0f000-b4b11000 rwxs 1800e000 00:06 8957       /dev/mem
b4b11000-b4b13000 rwxs 18014000 00:06 8957       /dev/mem
b4b13000-b4b15000 rwxs 18004000 00:06 8957       /dev/mem
b6f22000-b6f24000 rwxs 18016000 00:06 8957       /dev/mem
b6f24000-b6f26000 rwxs 18006000 00:06 8957       /dev/mem


Questions:
- What does "Unhandled fault: asynchronous external abort (0x1211)" mean?
- What is potential cause of the issue?

Thanks and regards,
Koichiro Tashiro

  • Hi,

    Any updates for this item?

    FYI. The customer tested if atomic accesses are the reason of the issue.
    Here is test code they used. It does 32bit and 64bit atomic accesses to DDR or GPMC(MRAM is connected).

    #include <stdio.h>
    
    #include <stdlib.h>
    
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    #include <sys/mman.h>
    
    #define handle_error(msg) \
    	do { perror(msg); exit(EXIT_FAILURE); } while (0)
    
    void atomic_write32(unsigned long* ptr, unsigned long new_value)
    {
    	unsigned long old_value = *ptr;
    	printf("old_value=%08lx\n", old_value);
    
    	__sync_bool_compare_and_swap((unsigned long *)ptr, (unsigned long)old_value, (unsigned long)new_value);
    
    	unsigned long read_value = *ptr;
    	printf("read_value=%08lx\n", read_value);
    }
    
    void normal_write32(unsigned long* ptr, unsigned long new_value)
    {
    	unsigned long old_value = *ptr;
    	printf("old_value=%08lx\n", old_value);
    
    	*ptr = new_value;
    
    	unsigned long read_value = *ptr;
    	printf("read_value=%08lx\n", read_value);
    }
    
    void atomic_write64(unsigned long long* ptr, unsigned long long new_value)
    {
    	unsigned long long old_value = *ptr;
    	printf("old_value=%016llx\n", old_value);
    
    	__sync_bool_compare_and_swap((unsigned long long *)ptr, (unsigned long long)old_value, (unsigned long long)new_value);
    
    	unsigned long long read_value = *ptr;
    	printf("read_value=%016llx\n", read_value);
    }
    
    void normal_write64(unsigned long long* ptr, unsigned long long new_value)
    {
    	unsigned long long old_value = *ptr;
    	printf("old_value=%016llx\n", old_value);
    
    	*ptr = new_value;
    
    	unsigned long long read_value = *ptr;
    	printf("read_value=%016llx\n", read_value);
    }
    
    int main()
    {
    	int fd = open("/dev/mem", O_RDWR);
    	if (fd == -1) {
    		handle_error("open");
    	}
    
    	char *addr;
    	addr = mmap(NULL, 0x1000, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x16001000);
    	if (addr == MAP_FAILED) {
    		handle_error("mmap");
    	}
    
    	unsigned long val32 = 0x0;
    	unsigned long long val64 = 0x0;
    
    	printf("\nnormal 32-bit write on DDR\n");
    	normal_write32(&val32, 0x12345678);
    
    	printf("\natomic 32-bit write on DDR\n");
    	atomic_write32(&val32, 0x9abcdef0);
    
    	printf("\nnormal 64-bit write on DDR\n");
    	normal_write64(&val64, 0x123456789abcdef0);
    
    	printf("\natomic 64-bit write on DDR\n");
    	atomic_write64(&val64, 0x0fedcba987654321);
    
    	unsigned long *ptr32 = (unsigned long*)(addr + 0x18);
    	unsigned long long *ptr64 = (unsigned long long*)(addr + 0x18);
    
    	printf("\nnormal 32-bit write on MRAM\n");
    	normal_write32(ptr32, 0x12345678);
    
    	printf("\natomic 32-bit write on MRAM\n");
    	atomic_write32(ptr32, 0x9abcdef0);
    
    	printf("\nnormal 64-bit write on MRAM\n");
    	normal_write64(ptr64, 0x123456789abcdef0);
    
    	printf("\natomic 64-bit write on MRAM\n");
    	atomic_write64(ptr64, 0x0fedcba987654321);
    
    	return 0;
    }
    

    And its disassembly code:
    int64:     file format elf32-littlearm
    
    
    Disassembly of section .init:
    
    00010394 <_init>:
       10394:	e92d4008 	push	{r3, lr}
       10398:	eb00002f 	bl	1045c <call_weak_fn>
       1039c:	e8bd8008 	pop	{r3, pc}
    
    Disassembly of section .plt:
    
    000103a0 <.plt>:
       103a0:	e52de004 	push	{lr}		; (str lr, [sp, #-4]!)
       103a4:	e59fe004 	ldr	lr, [pc, #4]	; 103b0 <.plt+0x10>
       103a8:	e08fe00e 	add	lr, pc, lr
       103ac:	e5bef008 	ldr	pc, [lr, #8]!
       103b0:	00010c50 	.word	0x00010c50
    
    000103b4 <printf@plt>:
       103b4:	e28fc600 	add	ip, pc, #0, 12
       103b8:	e28cca10 	add	ip, ip, #16, 20	; 0x10000
       103bc:	e5bcfc50 	ldr	pc, [ip, #3152]!	; 0xc50
    
    000103c0 <perror@plt>:
       103c0:	e28fc600 	add	ip, pc, #0, 12
       103c4:	e28cca10 	add	ip, ip, #16, 20	; 0x10000
       103c8:	e5bcfc48 	ldr	pc, [ip, #3144]!	; 0xc48
    
    000103cc <puts@plt>:
       103cc:	e28fc600 	add	ip, pc, #0, 12
       103d0:	e28cca10 	add	ip, ip, #16, 20	; 0x10000
       103d4:	e5bcfc40 	ldr	pc, [ip, #3136]!	; 0xc40
    
    000103d8 <__libc_start_main@plt>:
       103d8:	e28fc600 	add	ip, pc, #0, 12
       103dc:	e28cca10 	add	ip, ip, #16, 20	; 0x10000
       103e0:	e5bcfc38 	ldr	pc, [ip, #3128]!	; 0xc38
    
    000103e4 <__gmon_start__@plt>:
       103e4:	e28fc600 	add	ip, pc, #0, 12
       103e8:	e28cca10 	add	ip, ip, #16, 20	; 0x10000
       103ec:	e5bcfc30 	ldr	pc, [ip, #3120]!	; 0xc30
    
    000103f0 <open@plt>:
       103f0:	e28fc600 	add	ip, pc, #0, 12
       103f4:	e28cca10 	add	ip, ip, #16, 20	; 0x10000
       103f8:	e5bcfc28 	ldr	pc, [ip, #3112]!	; 0xc28
    
    000103fc <exit@plt>:
       103fc:	e28fc600 	add	ip, pc, #0, 12
       10400:	e28cca10 	add	ip, ip, #16, 20	; 0x10000
       10404:	e5bcfc20 	ldr	pc, [ip, #3104]!	; 0xc20
    
    00010408 <mmap@plt>:
       10408:	e28fc600 	add	ip, pc, #0, 12
       1040c:	e28cca10 	add	ip, ip, #16, 20	; 0x10000
       10410:	e5bcfc18 	ldr	pc, [ip, #3096]!	; 0xc18
    
    00010414 <abort@plt>:
       10414:	e28fc600 	add	ip, pc, #0, 12
       10418:	e28cca10 	add	ip, ip, #16, 20	; 0x10000
       1041c:	e5bcfc10 	ldr	pc, [ip, #3088]!	; 0xc10
    
    Disassembly of section .text:
    
    00010420 <_start>:
       10420:	e3a0b000 	mov	fp, #0
       10424:	e3a0e000 	mov	lr, #0
       10428:	e49d1004 	pop	{r1}		; (ldr r1, [sp], #4)
       1042c:	e1a0200d 	mov	r2, sp
       10430:	e52d2004 	push	{r2}		; (str r2, [sp, #-4]!)
       10434:	e52d0004 	push	{r0}		; (str r0, [sp, #-4]!)
       10438:	e59fc010 	ldr	ip, [pc, #16]	; 10450 <_start+0x30>
       1043c:	e52dc004 	push	{ip}		; (str ip, [sp, #-4]!)
       10440:	e59f000c 	ldr	r0, [pc, #12]	; 10454 <_start+0x34>
       10444:	e59f300c 	ldr	r3, [pc, #12]	; 10458 <_start+0x38>
       10448:	ebffffe2 	bl	103d8 <__libc_start_main@plt>
       1044c:	ebfffff0 	bl	10414 <abort@plt>
       10450:	0001084c 	.word	0x0001084c
       10454:	00010675 	.word	0x00010675
       10458:	000107e8 	.word	0x000107e8
    
    0001045c <call_weak_fn>:
       1045c:	e59f3014 	ldr	r3, [pc, #20]	; 10478 <call_weak_fn+0x1c>
       10460:	e59f2014 	ldr	r2, [pc, #20]	; 1047c <call_weak_fn+0x20>
       10464:	e08f3003 	add	r3, pc, r3
       10468:	e7932002 	ldr	r2, [r3, r2]
       1046c:	e3520000 	cmp	r2, #0
       10470:	012fff1e 	bxeq	lr
       10474:	eaffffda 	b	103e4 <__gmon_start__@plt>
       10478:	00010b94 	.word	0x00010b94
       1047c:	00000030 	.word	0x00000030
    
    00010480 <deregister_tm_clones>:
       10480:	e301003c 	movw	r0, #4156	; 0x103c
       10484:	e3400002 	movt	r0, #2
       10488:	e301303c 	movw	r3, #4156	; 0x103c
       1048c:	e3403002 	movt	r3, #2
       10490:	e1530000 	cmp	r3, r0
       10494:	012fff1e 	bxeq	lr
       10498:	e3003000 	movw	r3, #0
       1049c:	e3403000 	movt	r3, #0
       104a0:	e3530000 	cmp	r3, #0
       104a4:	012fff1e 	bxeq	lr
       104a8:	e12fff13 	bx	r3
    
    000104ac <register_tm_clones>:
       104ac:	e301003c 	movw	r0, #4156	; 0x103c
       104b0:	e3400002 	movt	r0, #2
       104b4:	e301103c 	movw	r1, #4156	; 0x103c
       104b8:	e3401002 	movt	r1, #2
       104bc:	e0411000 	sub	r1, r1, r0
       104c0:	e1a01141 	asr	r1, r1, #2
       104c4:	e0811fa1 	add	r1, r1, r1, lsr #31
       104c8:	e1b010c1 	asrs	r1, r1, #1
       104cc:	012fff1e 	bxeq	lr
       104d0:	e3003000 	movw	r3, #0
       104d4:	e3403000 	movt	r3, #0
       104d8:	e3530000 	cmp	r3, #0
       104dc:	012fff1e 	bxeq	lr
       104e0:	e12fff13 	bx	r3
    
    000104e4 <__do_global_dtors_aux>:
       104e4:	e92d4010 	push	{r4, lr}
       104e8:	e301403c 	movw	r4, #4156	; 0x103c
       104ec:	e3404002 	movt	r4, #2
       104f0:	e5d43000 	ldrb	r3, [r4]
       104f4:	e3530000 	cmp	r3, #0
       104f8:	18bd8010 	popne	{r4, pc}
       104fc:	ebffffdf 	bl	10480 <deregister_tm_clones>
       10500:	e3a03001 	mov	r3, #1
       10504:	e5c43000 	strb	r3, [r4]
       10508:	e8bd8010 	pop	{r4, pc}
    
    0001050c <frame_dummy>:
       1050c:	eaffffe6 	b	104ac <register_tm_clones>
    
    00010510 <atomic_write32>:
       10510:	b580      	push	{r7, lr}
       10512:	b084      	sub	sp, #16
       10514:	af00      	add	r7, sp, #0
       10516:	6078      	str	r0, [r7, #4]
       10518:	6039      	str	r1, [r7, #0]
       1051a:	687b      	ldr	r3, [r7, #4]
       1051c:	681b      	ldr	r3, [r3, #0]
       1051e:	60fb      	str	r3, [r7, #12]
       10520:	68f9      	ldr	r1, [r7, #12]
       10522:	f640 005c 	movw	r0, #2140	; 0x85c
       10526:	f2c0 0001 	movt	r0, #1
       1052a:	f7ff ef44 	blx	103b4 <printf@plt>
       1052e:	687b      	ldr	r3, [r7, #4]
       10530:	68fa      	ldr	r2, [r7, #12]
       10532:	6839      	ldr	r1, [r7, #0]
       10534:	f3bf 8f5b 	dmb	ish
       10538:	e853 0f00 	ldrex	r0, [r3]
       1053c:	4290      	cmp	r0, r2
       1053e:	d106      	bne.n	1054e <atomic_write32+0x3e>
       10540:	e843 1c00 	strex	ip, r1, [r3]
       10544:	f1bc 0f00 	cmp.w	ip, #0
       10548:	f1bc 0f00 	cmp.w	ip, #0
       1054c:	d1f4      	bne.n	10538 <atomic_write32+0x28>
       1054e:	f3bf 8f5b 	dmb	ish
       10552:	687b      	ldr	r3, [r7, #4]
       10554:	681b      	ldr	r3, [r3, #0]
       10556:	60bb      	str	r3, [r7, #8]
       10558:	68b9      	ldr	r1, [r7, #8]
       1055a:	f640 0070 	movw	r0, #2160	; 0x870
       1055e:	f2c0 0001 	movt	r0, #1
       10562:	f7ff ef28 	blx	103b4 <printf@plt>
       10566:	bf00      	nop
       10568:	3710      	adds	r7, #16
       1056a:	46bd      	mov	sp, r7
       1056c:	bd80      	pop	{r7, pc}
    
    0001056e <normal_write32>:
       1056e:	b580      	push	{r7, lr}
       10570:	b084      	sub	sp, #16
       10572:	af00      	add	r7, sp, #0
       10574:	6078      	str	r0, [r7, #4]
       10576:	6039      	str	r1, [r7, #0]
       10578:	687b      	ldr	r3, [r7, #4]
       1057a:	681b      	ldr	r3, [r3, #0]
       1057c:	60fb      	str	r3, [r7, #12]
       1057e:	68f9      	ldr	r1, [r7, #12]
       10580:	f640 005c 	movw	r0, #2140	; 0x85c
       10584:	f2c0 0001 	movt	r0, #1
       10588:	f7ff ef14 	blx	103b4 <printf@plt>
       1058c:	687b      	ldr	r3, [r7, #4]
       1058e:	683a      	ldr	r2, [r7, #0]
       10590:	601a      	str	r2, [r3, #0]
       10592:	687b      	ldr	r3, [r7, #4]
       10594:	681b      	ldr	r3, [r3, #0]
       10596:	60bb      	str	r3, [r7, #8]
       10598:	68b9      	ldr	r1, [r7, #8]
       1059a:	f640 0070 	movw	r0, #2160	; 0x870
       1059e:	f2c0 0001 	movt	r0, #1
       105a2:	f7ff ef08 	blx	103b4 <printf@plt>
       105a6:	bf00      	nop
       105a8:	3710      	adds	r7, #16
       105aa:	46bd      	mov	sp, r7
       105ac:	bd80      	pop	{r7, pc}
    
    000105ae <atomic_write64>:
       105ae:	b5f0      	push	{r4, r5, r6, r7, lr}
       105b0:	b089      	sub	sp, #36	; 0x24
       105b2:	af00      	add	r7, sp, #0
       105b4:	60f8      	str	r0, [r7, #12]
       105b6:	e9c7 2300 	strd	r2, r3, [r7]
       105ba:	68fb      	ldr	r3, [r7, #12]
       105bc:	e9d3 3400 	ldrd	r3, r4, [r3]
       105c0:	e9c7 3406 	strd	r3, r4, [r7, #24]
       105c4:	e9d7 2306 	ldrd	r2, r3, [r7, #24]
       105c8:	f640 0084 	movw	r0, #2180	; 0x884
       105cc:	f2c0 0001 	movt	r0, #1
       105d0:	f7ff eef0 	blx	103b4 <printf@plt>
       105d4:	68f8      	ldr	r0, [r7, #12]
       105d6:	e9d7 3406 	ldrd	r3, r4, [r7, #24]
       105da:	e9d7 1200 	ldrd	r1, r2, [r7]
       105de:	f3bf 8f5b 	dmb	ish
       105e2:	e8d0 567f 	ldrexd	r5, r6, [r0]
       105e6:	42a6      	cmp	r6, r4
       105e8:	bf08      	it	eq
       105ea:	429d      	cmpeq	r5, r3
       105ec:	d106      	bne.n	105fc <atomic_write64+0x4e>
       105ee:	e8c0 127c 	strexd	ip, r1, r2, [r0]
       105f2:	f1bc 0f00 	cmp.w	ip, #0
       105f6:	f1bc 0f00 	cmp.w	ip, #0
       105fa:	d1f2      	bne.n	105e2 <atomic_write64+0x34>
       105fc:	f3bf 8f5b 	dmb	ish
       10600:	68fb      	ldr	r3, [r7, #12]
       10602:	e9d3 3400 	ldrd	r3, r4, [r3]
       10606:	e9c7 3404 	strd	r3, r4, [r7, #16]
       1060a:	e9d7 2304 	ldrd	r2, r3, [r7, #16]
       1060e:	f640 0098 	movw	r0, #2200	; 0x898
       10612:	f2c0 0001 	movt	r0, #1
       10616:	f7ff eece 	blx	103b4 <printf@plt>
       1061a:	bf00      	nop
       1061c:	3724      	adds	r7, #36	; 0x24
       1061e:	46bd      	mov	sp, r7
       10620:	bdf0      	pop	{r4, r5, r6, r7, pc}
    
    00010622 <normal_write64>:
       10622:	b590      	push	{r4, r7, lr}
       10624:	b089      	sub	sp, #36	; 0x24
       10626:	af00      	add	r7, sp, #0
       10628:	60f8      	str	r0, [r7, #12]
       1062a:	e9c7 2300 	strd	r2, r3, [r7]
       1062e:	68fb      	ldr	r3, [r7, #12]
       10630:	e9d3 3400 	ldrd	r3, r4, [r3]
       10634:	e9c7 3406 	strd	r3, r4, [r7, #24]
       10638:	e9d7 2306 	ldrd	r2, r3, [r7, #24]
       1063c:	f640 0084 	movw	r0, #2180	; 0x884
       10640:	f2c0 0001 	movt	r0, #1
       10644:	f7ff eeb6 	blx	103b4 <printf@plt>
       10648:	68fa      	ldr	r2, [r7, #12]
       1064a:	e9d7 3400 	ldrd	r3, r4, [r7]
       1064e:	e9c2 3400 	strd	r3, r4, [r2]
       10652:	68fb      	ldr	r3, [r7, #12]
       10654:	e9d3 3400 	ldrd	r3, r4, [r3]
       10658:	e9c7 3404 	strd	r3, r4, [r7, #16]
       1065c:	e9d7 2304 	ldrd	r2, r3, [r7, #16]
       10660:	f640 0098 	movw	r0, #2200	; 0x898
       10664:	f2c0 0001 	movt	r0, #1
       10668:	f7ff eea4 	blx	103b4 <printf@plt>
       1066c:	bf00      	nop
       1066e:	3724      	adds	r7, #36	; 0x24
       10670:	46bd      	mov	sp, r7
       10672:	bd90      	pop	{r4, r7, pc}
    
    00010674 <main>:
       10674:	b580      	push	{r7, lr}
       10676:	b08a      	sub	sp, #40	; 0x28
       10678:	af02      	add	r7, sp, #8
       1067a:	2102      	movs	r1, #2
       1067c:	f640 00ac 	movw	r0, #2220	; 0x8ac
       10680:	f2c0 0001 	movt	r0, #1
       10684:	f7ff eeb4 	blx	103f0 <open@plt>
       10688:	61f8      	str	r0, [r7, #28]
       1068a:	69fb      	ldr	r3, [r7, #28]
       1068c:	f1b3 3fff 	cmp.w	r3, #4294967295	; 0xffffffff
       10690:	d108      	bne.n	106a4 <main+0x30>
       10692:	f640 00b8 	movw	r0, #2232	; 0x8b8
       10696:	f2c0 0001 	movt	r0, #1
       1069a:	f7ff ee92 	blx	103c0 <perror@plt>
       1069e:	2001      	movs	r0, #1
       106a0:	f7ff eeac 	blx	103fc <exit@plt>
       106a4:	f44f 5380 	mov.w	r3, #4096	; 0x1000
       106a8:	f2c1 6300 	movt	r3, #5632	; 0x1600
       106ac:	9301      	str	r3, [sp, #4]
       106ae:	69fb      	ldr	r3, [r7, #28]
       106b0:	9300      	str	r3, [sp, #0]
       106b2:	2301      	movs	r3, #1
       106b4:	2203      	movs	r2, #3
       106b6:	f44f 5180 	mov.w	r1, #4096	; 0x1000
       106ba:	2000      	movs	r0, #0
       106bc:	f7ff eea4 	blx	10408 <mmap@plt>
       106c0:	61b8      	str	r0, [r7, #24]
       106c2:	69bb      	ldr	r3, [r7, #24]
       106c4:	f1b3 3fff 	cmp.w	r3, #4294967295	; 0xffffffff
       106c8:	d108      	bne.n	106dc <main+0x68>
       106ca:	f640 00c0 	movw	r0, #2240	; 0x8c0
       106ce:	f2c0 0001 	movt	r0, #1
       106d2:	f7ff ee76 	blx	103c0 <perror@plt>
       106d6:	2001      	movs	r0, #1
       106d8:	f7ff ee90 	blx	103fc <exit@plt>
       106dc:	2300      	movs	r3, #0
       106de:	60fb      	str	r3, [r7, #12]
       106e0:	efc0 0010 	vmov.i32	d16, #0	; 0x00000000
       106e4:	edc7 0b00 	vstr	d16, [r7]
       106e8:	f640 00c8 	movw	r0, #2248	; 0x8c8
       106ec:	f2c0 0001 	movt	r0, #1
       106f0:	f7ff ee6c 	blx	103cc <puts@plt>
       106f4:	f107 030c 	add.w	r3, r7, #12
       106f8:	f245 6178 	movw	r1, #22136	; 0x5678
       106fc:	f2c1 2134 	movt	r1, #4660	; 0x1234
       10700:	4618      	mov	r0, r3
       10702:	f7ff ff34 	bl	1056e <normal_write32>
       10706:	f640 00e4 	movw	r0, #2276	; 0x8e4
       1070a:	f2c0 0001 	movt	r0, #1
       1070e:	f7ff ee5e 	blx	103cc <puts@plt>
       10712:	f107 030c 	add.w	r3, r7, #12
       10716:	f64d 61f0 	movw	r1, #57072	; 0xdef0
       1071a:	f6c9 21bc 	movt	r1, #39612	; 0x9abc
       1071e:	4618      	mov	r0, r3
       10720:	f7ff fef6 	bl	10510 <atomic_write32>
       10724:	f640 1000 	movw	r0, #2304	; 0x900
       10728:	f2c0 0001 	movt	r0, #1
       1072c:	f7ff ee4e 	blx	103cc <puts@plt>
       10730:	4639      	mov	r1, r7
       10732:	a329      	add	r3, pc, #164	; (adr r3, 107d8 <main+0x164>)
       10734:	e9d3 2300 	ldrd	r2, r3, [r3]
       10738:	4608      	mov	r0, r1
       1073a:	f7ff ff72 	bl	10622 <normal_write64>
       1073e:	f640 101c 	movw	r0, #2332	; 0x91c
       10742:	f2c0 0001 	movt	r0, #1
       10746:	f7ff ee42 	blx	103cc <puts@plt>
       1074a:	4639      	mov	r1, r7
       1074c:	a324      	add	r3, pc, #144	; (adr r3, 107e0 <main+0x16c>)
       1074e:	e9d3 2300 	ldrd	r2, r3, [r3]
       10752:	4608      	mov	r0, r1
       10754:	f7ff ff2b 	bl	105ae <atomic_write64>
       10758:	69bb      	ldr	r3, [r7, #24]
       1075a:	3318      	adds	r3, #24
       1075c:	617b      	str	r3, [r7, #20]
       1075e:	69bb      	ldr	r3, [r7, #24]
       10760:	3318      	adds	r3, #24
       10762:	613b      	str	r3, [r7, #16]
       10764:	f640 1038 	movw	r0, #2360	; 0x938
       10768:	f2c0 0001 	movt	r0, #1
       1076c:	f7ff ee2e 	blx	103cc <puts@plt>
       10770:	f245 6178 	movw	r1, #22136	; 0x5678
       10774:	f2c1 2134 	movt	r1, #4660	; 0x1234
       10778:	6978      	ldr	r0, [r7, #20]
       1077a:	f7ff fef8 	bl	1056e <normal_write32>
       1077e:	f640 1058 	movw	r0, #2392	; 0x958
       10782:	f2c0 0001 	movt	r0, #1
       10786:	f7ff ee22 	blx	103cc <puts@plt>
       1078a:	f64d 61f0 	movw	r1, #57072	; 0xdef0
       1078e:	f6c9 21bc 	movt	r1, #39612	; 0x9abc
       10792:	6978      	ldr	r0, [r7, #20]
       10794:	f7ff febc 	bl	10510 <atomic_write32>
       10798:	f640 1078 	movw	r0, #2424	; 0x978
       1079c:	f2c0 0001 	movt	r0, #1
       107a0:	f7ff ee14 	blx	103cc <puts@plt>
       107a4:	a30c      	add	r3, pc, #48	; (adr r3, 107d8 <main+0x164>)
       107a6:	e9d3 2300 	ldrd	r2, r3, [r3]
       107aa:	6938      	ldr	r0, [r7, #16]
       107ac:	f7ff ff39 	bl	10622 <normal_write64>
       107b0:	f640 1098 	movw	r0, #2456	; 0x998
       107b4:	f2c0 0001 	movt	r0, #1
       107b8:	f7ff ee08 	blx	103cc <puts@plt>
       107bc:	a308      	add	r3, pc, #32	; (adr r3, 107e0 <main+0x16c>)
       107be:	e9d3 2300 	ldrd	r2, r3, [r3]
       107c2:	6938      	ldr	r0, [r7, #16]
       107c4:	f7ff fef3 	bl	105ae <atomic_write64>
       107c8:	2300      	movs	r3, #0
       107ca:	4618      	mov	r0, r3
       107cc:	3720      	adds	r7, #32
       107ce:	46bd      	mov	sp, r7
       107d0:	bd80      	pop	{r7, pc}
       107d2:	bf00      	nop
       107d4:	f3af 8000 	nop.w
       107d8:	9abcdef0 	.word	0x9abcdef0
       107dc:	12345678 	.word	0x12345678
       107e0:	87654321 	.word	0x87654321
       107e4:	0fedcba9 	.word	0x0fedcba9
    
    000107e8 <__libc_csu_init>:
       107e8:	e92d47f0 	push	{r4, r5, r6, r7, r8, r9, sl, lr}
       107ec:	e1a07000 	mov	r7, r0
       107f0:	e59f604c 	ldr	r6, [pc, #76]	; 10844 <__libc_csu_init+0x5c>
       107f4:	e1a08001 	mov	r8, r1
       107f8:	e59f5048 	ldr	r5, [pc, #72]	; 10848 <__libc_csu_init+0x60>
       107fc:	e1a09002 	mov	r9, r2
       10800:	e08f6006 	add	r6, pc, r6
       10804:	ebfffee2 	bl	10394 <_init>
       10808:	e08f5005 	add	r5, pc, r5
       1080c:	e0466005 	sub	r6, r6, r5
       10810:	e1b06146 	asrs	r6, r6, #2
       10814:	08bd87f0 	popeq	{r4, r5, r6, r7, r8, r9, sl, pc}
       10818:	e2455004 	sub	r5, r5, #4
       1081c:	e3a04000 	mov	r4, #0
       10820:	e2844001 	add	r4, r4, #1
       10824:	e5b53004 	ldr	r3, [r5, #4]!
       10828:	e1a02009 	mov	r2, r9
       1082c:	e1a01008 	mov	r1, r8
       10830:	e1a00007 	mov	r0, r7
       10834:	e12fff33 	blx	r3
       10838:	e1560004 	cmp	r6, r4
       1083c:	1afffff7 	bne	10820 <__libc_csu_init+0x38>
       10840:	e8bd87f0 	pop	{r4, r5, r6, r7, r8, r9, sl, pc}
       10844:	00010704 	.word	0x00010704
       10848:	000106f8 	.word	0x000106f8
    
    0001084c <__libc_csu_fini>:
       1084c:	e12fff1e 	bx	lr
    
    Disassembly of section .fini:
    
    00010850 <_fini>:
       10850:	e92d4008 	push	{r3, lr}
       10854:	e8bd8008 	pop	{r3, pc}
    


    The test results are here:
    ■AM437
    root@HX-SDC:~# ./int64
    
    normal 32-bit write on DDR
    old_value=00000000
    read_value=12345678
    
    atomic 32-bit write on DDR
    old_value=12345678
    read_value=9abcdef0
    
    normal 64-bit write on DDR
    old_value=0000000000000000
    read_value=123456789abcdef0
    
    atomic 64-bit write on DDR
    old_value=123456789abcdef0
    read_value=0fedcba987654321
    
    normal 32-bit write on MRAM
    old_value=87654321
    read_value=12345678
    
    atomic 32-bit write on MRAM
    old_value=12345678
    read_value=9abcdef0
    
    normal 64-bit write on MRAM
    old_value=0fedcba99abcdef0
    read_value=123456789abcdef0
    
    atomic 64-bit write on MRAM
    old_value=123456789abcdef0
    read_value=0fedcba987654321
    
    ■AM572
    root@HX-SDC:~# ./int64
    
    normal 32-bit write on DDR
    old_value=00000000
    read_value=12345678
    
    atomic 32-bit write on DDR
    old_value=12345678
    read_value=9abcdef0
    
    normal 64-bit write on DDR
    old_value=0000000000000000
    read_value=123456789abcdef0
    
    atomic 64-bit write on DDR
    old_value=123456789abcdef0
    read_value=0fedcba987654321
    
    normal 32-bit write on MRAM
    old_value=12345678
    read_value=12345678
    
    atomic 32-bit write on MRAM
    old_value=12345678
    <13>Feb  2 17:20:14 core_filter(2241): "int64" (PID 2241) was terminated by signal 7.
    <13>Feb  2 17:20:14 core_filter(2241): Since ulimit for core file size (ulimit -c) is set to 0, no core dump file was created.
    Bus error (core dumped)
    
    *** kernel output generated hereafter ***
    2000-02-02T17:20:14.744203+00:00 HX-SDC kernel: [ 3907.899248] Unhandled fault: asynchronous external abort (0x1211) at 0x00000000
    2000-02-02T17:20:14.744292+00:00 HX-SDC kernel: [ 3907.899255] pgd = 2c9b0766
    2000-02-02T17:20:14.744302+00:00 HX-SDC kernel: [ 3907.899258] [00000000] *pgd=ad19d003, *pmd=be2eb003
    

    Please note that the customer has very similar products using AM437x and AM572x.
    As you can see in result.txt, atomic accesses on AM437x are all fine.
    On AM572x, atomic accesses to DDR are fine, but accesses to GPMC caused a bus error.

    Thanks and regards,
    Koichiro Tashiro 

  • Hello,

    ARM exclusive operations like strex/ldrex/... (and other operations like VFP and alignment fix ups) are only defined when used on address ranges defined with the MMU memory attributes of the 'normal' type.   If a customer tries to execute user level code against an MMU attribute of 'strongly ordered, DEVICE' the result is undefined.  This is part of the ARMv7 arch standard.  Different ARM core implementations behave differently against these 'undefined' regions.  For example a Cortex-A8 u-boot using neon or vfp usually just return the wrong answers where a Cortex-A9 or A15 will throw an abort.

    It is not safe to use exclusives (and some other common opcodes/instructions) on non-normal memory.

    In the case of exclusive operations, they only behavior to the ARM TRM when used against 'normal-non-cached-copy-back-shared' attributed memory.  This is the type of memory needed to be used when executing 'SMP' Linux code.  The A15 cache implements a local-monitor  which provides the safe-locking between the 2 A15 inner shared CPUs.    The exclusive function will not happen for other memory types and will be converted to normal loads/stores for normal-non-cached types.   For DEVICE or Strongly-Ordered types the result is unpredictable (it might be a wrong operation or an abort).

    Regards,
    Richard W.
  • Dear Mr. Woodruff, 

    Thank you for your post.

     

    We have 3 questions to your post.

    Would you please answer to the followings?

    1.

    asynchronous external abort occurs when executing atomic instruction (strex) to MRAM.

    The MRAM is MR4A16BCMA35 manufactured by Everspin (MR4A16BCMA35 Everspin Technologies | Mouser Japan).

    The MRAM is connected to GPMC via FPGA.

    Is it possible to set 'normal' to the MMU memory attribute?

    2.

    Is our following understanding correct?

    - The MMU memory attribute is set by Linux.

    - 'strongly ordered' or 'DEVICE' is set for the memory devices other than Linux managed RAM area.

    3.

    What is the meaning of "'normal-non-cached-copy-back-shared' attributed memory"?

    We suppose that the MMU attributes are listed in the following URL.

    https://developer.arm.com/documentation/den0013/d/The-Memory-Management-Unit/Memory-attributes/Memory-types

    Which one does 'normal-non-cached-copy-back-shared' correspond to?

    Best regards, 
    Masayoshi SUDOH

  • Hello,

    For questions:

    -1-

    The setting of the MMU memory attributes is largely independent of the backing memory type.  The setting of these needs to be done via Linux MM APIs.  Generally I check the actual attributes using an MMU decoder which is part of the Lauterbach debugger.  Using the debugger command 'mmu.info <virtual address> + scan will fully decode the assigned ARM attributes.

    For any backing memory (in your case GPMC + FPGA -> MRMAM) to execute ARM instructions it must be able to process bus transactions which the ARM may direct at it.  For example, for the device to work properly for ARM cache accesses, but wrapping and incrementing burst types must be supported.  If the GPMC-FPGA mating doesn't allow this you will have to restrict the types of mappings used from the ARM, further you may have to restrict some of the ARM instructions/opcodes used in conjunction with the memory. 

    -2-

    Correct, the MMU attribute is assigned by Linux.  How it is assigned will vary depending on your BSP's implementation details.

    Strongly-ordered or DEVICE and used by Linux for IO regions.  These regions have ARM generic usage constraints as defined in the ARM Arch manual.  A CPU might typically do reads and writes of fixes sizes but will not execute cached (instruction or data) operations.  Other common ARM methods like reordering may be suppressed to these memory types.  They are not generic and do not offer full user instruction usage like 'normal' memory provides.

    -3-

    The table you reference is showing individual properties.  'normal-on-cached-copy-back-shared' is a concatenation of a valid grouping of these attributes. You can expand the summary provided in the programmers reference guide with the details in the ARM Architecture reference guide.  Understanding how Linux maps to these (which it does at various API levels) can be difficult to follow as there are many (sometimes changing) layers of abstractions and not all ARM options are exported.   As I mention, I use the TRACE32 debugger by Lauterbach as a way to get a trusted decode of end states.  Doing this by hand can take a long time and is error prone.  By hand requires a lot of consultation with the ARM Arch reference manual.  Doing this is out of scope for a TI-E2E.

    Regards,
    Richard W.