MotorControlModuleSDFM_TMS3.../Projects/EFC_Communication/Platform/device/memcfg.c
2024-06-07 11:12:56 +03:00

656 lines
21 KiB
C

//###########################################################################
//
// FILE: memcfg.c
//
// TITLE: CM SRAM config driver.
//
//###########################################################################
// $TI Release: F2838x Support Library v3.04.00.00 $
// $Release Date: Fri Feb 12 19:08:49 IST 2021 $
// $Copyright:
// Copyright (C) 2021 Texas Instruments Incorporated - http://www.ti.com/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the
// distribution.
//
// Neither the name of Texas Instruments Incorporated nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// $
//###########################################################################
#include "memcfg.h"
//*****************************************************************************
//
// MemCfg_lockConfig
//
//*****************************************************************************
void
MemCfg_lockConfig(uint32_t memSections)
{
//
// Check the arguments.
//
ASSERT(((memSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_CX) ||
((memSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_SX) ||
((memSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_ROM) ||
((memSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_PERIMEM)||
((memSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_CMMSGX) ||
(memSections == MEMCFG_SECT_ALL));
//
// Set the bit that blocks writes to the sections' configuration registers.
//
switch(memSections & MEMCFG_SECT_TYPE_MASK)
{
case MEMCFG_SECT_TYPE_CX:
HWREG(CMMEMCFG_BASE + MEMCFG_O_CXLOCK) |= (MEMCFG_SECT_NUM_MASK &
memSections);
break;
case MEMCFG_SECT_TYPE_CMMSGX:
HWREG(CMMEMCFG_BASE + MEMCFG_O_CMMSGXLOCK) |= (MEMCFG_SECT_NUM_MASK
& memSections);
break;
case MEMCFG_SECT_TYPE_SX:
HWREG(CMMEMCFG_BASE + MEMCFG_O_SXGROUP1_LOCK) |=
(MEMCFG_SECT_NUM_MASK & memSections);
break;
case MEMCFG_SECT_TYPE_ROM:
HWREG(CMMEMCFG_BASE + MEMCFG_O_ROM_LOCK) |= (MEMCFG_SECT_NUM_MASK &
memSections);
break;
case MEMCFG_SECT_TYPE_PERIMEM:
HWREG(CMMEMCFG_BASE + MEMCFG_O_PERI_MEM_TEST_LOCK) |=
(MEMCFG_SECT_NUM_MASK & memSections);
break;
case MEMCFG_SECT_TYPE_MASK:
//
// Lock configuration for all sections.
//
HWREG(CMMEMCFG_BASE + MEMCFG_O_CXLOCK) |=
(MEMCFG_SECT_NUM_MASK & MEMCFG_SECT_CX_ALL);
HWREG(CMMEMCFG_BASE + MEMCFG_O_CMMSGXLOCK) |=
(MEMCFG_SECT_NUM_MASK & MEMCFG_SECT_CMMSGX_ALL);
HWREG(CMMEMCFG_BASE + MEMCFG_O_SXGROUP1_LOCK) |=
(MEMCFG_SECT_NUM_MASK & MEMCFG_SECT_SX_ALL);
HWREG(CMMEMCFG_BASE + MEMCFG_O_ROM_LOCK) |=
(MEMCFG_SECT_NUM_MASK & MEMCFG_SECT_ROM);
HWREG(CMMEMCFG_BASE + MEMCFG_O_PERI_MEM_TEST_LOCK) |=
(MEMCFG_SECT_NUM_MASK & MEMCFG_SECT_PERIMEM_ALL);
break;
default:
//
// Do nothing. Invalid memSections. Make sure you aren't OR-ing
// values for two different types of RAM.
//
break;
}
}
//*****************************************************************************
//
// MemCfg_unlockConfig
//
//*****************************************************************************
void
MemCfg_unlockConfig(uint32_t memSections)
{
//
// Check the arguments.
//
ASSERT(((memSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_CX) ||
((memSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_SX) ||
((memSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_ROM) ||
((memSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_PERIMEM)||
((memSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_CMMSGX) ||
(memSections == MEMCFG_SECT_ALL));
//
// Clear the bit that blocks writes to the sections' configuration
// registers.
//
switch(memSections & MEMCFG_SECT_TYPE_MASK)
{
case MEMCFG_SECT_TYPE_CX:
HWREG(CMMEMCFG_BASE + MEMCFG_O_CXLOCK) &=
~(MEMCFG_SECT_NUM_MASK & memSections);
break;
case MEMCFG_SECT_TYPE_CMMSGX:
HWREG(CMMEMCFG_BASE + MEMCFG_O_CMMSGXLOCK) &=
~(MEMCFG_SECT_NUM_MASK & memSections);
break;
case MEMCFG_SECT_TYPE_SX:
HWREG(CMMEMCFG_BASE + MEMCFG_O_SXGROUP1_LOCK) &=
~(MEMCFG_SECT_NUM_MASK & memSections);
break;
case MEMCFG_SECT_TYPE_ROM:
HWREG(CMMEMCFG_BASE + MEMCFG_O_ROM_LOCK) &=
~(MEMCFG_SECT_NUM_MASK & memSections);
break;
case MEMCFG_SECT_TYPE_PERIMEM:
HWREG(CMMEMCFG_BASE + MEMCFG_O_PERI_MEM_TEST_LOCK) &=
~(MEMCFG_SECT_NUM_MASK & memSections);
break;
case MEMCFG_SECT_TYPE_MASK:
//
// Lock configuration for all sections.
//
HWREG(CMMEMCFG_BASE + MEMCFG_O_CXLOCK) &= ~((uint32_t)
(MEMCFG_SECT_NUM_MASK & MEMCFG_SECT_CX_ALL));
HWREG(CMMEMCFG_BASE + MEMCFG_O_CMMSGXLOCK) &= ~((uint32_t)
(MEMCFG_SECT_NUM_MASK & MEMCFG_SECT_CMMSGX_ALL));
HWREG(CMMEMCFG_BASE + MEMCFG_O_SXGROUP1_LOCK) &= ~((uint32_t)
(MEMCFG_SECT_NUM_MASK & MEMCFG_SECT_SX_ALL));
HWREG(CMMEMCFG_BASE + MEMCFG_O_ROM_LOCK) &= ~((uint32_t)
(MEMCFG_SECT_NUM_MASK & MEMCFG_SECT_ROM));
HWREG(CMMEMCFG_BASE + MEMCFG_O_PERI_MEM_TEST_LOCK) &= ~((uint32_t)
(MEMCFG_SECT_NUM_MASK & MEMCFG_SECT_PERIMEM_ALL));
break;
default:
//
// Do nothing. Invalid memSections. Make sure you aren't OR-ing
// values for two different types of RAM.
//
break;
}
}
//*****************************************************************************
//
// MemCfg_setTestMode
//
//*****************************************************************************
void
MemCfg_setTestMode(uint32_t memSection, MemCfg_TestMode testMode)
{
uint32_t shiftVal = 0U;
uint32_t maskVal;
uint32_t regVal;
uint32_t sectionNum;
//
// Check the arguments.
//
ASSERT(((memSection & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_CX) ||
((memSection & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_SX) ||
((memSection & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_ROM) ||
((memSection & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_CMMSGX));
//
// Calculate how far the protect mode value needs to be shifted. Each
// section number is represented by a bit in the lower word of memSection
// and 2 bits in the corresponding TEST register.
//
sectionNum = memSection & MEMCFG_SECT_NUM_MASK;
while(sectionNum != 1U)
{
sectionNum = sectionNum >> 1U;
shiftVal += 2U;
}
maskVal = (uint32_t)MEMCFG_TESTMODE_M << shiftVal;
regVal = ((uint32_t)testMode) << shiftVal;
//
// Write the test mode into the appropriate field
//
switch(memSection & MEMCFG_SECT_TYPE_MASK)
{
case MEMCFG_SECT_TYPE_CX:
HWREG(CMMEMCFG_BASE + MEMCFG_O_CXTEST) =
((HWREG(CMMEMCFG_BASE + MEMCFG_O_CXTEST) & ~maskVal) | regVal);
break;
case MEMCFG_SECT_TYPE_CMMSGX:
HWREG(CMMEMCFG_BASE + MEMCFG_O_CMMSGXTEST) =
((HWREG(CMMEMCFG_BASE + MEMCFG_O_CMMSGXTEST) & ~maskVal) | regVal);
break;
case MEMCFG_SECT_TYPE_SX:
HWREG(CMMEMCFG_BASE + MEMCFG_O_SXGROUP1_TEST) =
((HWREG(CMMEMCFG_BASE + MEMCFG_O_CXTEST) & ~maskVal) | regVal);
break;
case MEMCFG_SECT_TYPE_ROM:
HWREG(CMMEMCFG_BASE + MEMCFG_O_ROM_TEST) =
((HWREG(CMMEMCFG_BASE + MEMCFG_O_ROM_TEST) & ~maskVal) | regVal);
break;
default:
//
// Do nothing. Invalid memSection.
//
break;
}
}
//*****************************************************************************
//
// MemCfg_initSections
//
//*****************************************************************************
void
MemCfg_initSections(uint32_t ramSections)
{
//
// Check the arguments.
//
ASSERT(((ramSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_CX) ||
((ramSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_SX) ||
((ramSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_CMMSGX) ||
(ramSections == MEMCFG_SECT_ALL));
//
// Set the bit in the various initialization registers that starts
// initialization.
//
switch(ramSections & MEMCFG_SECT_TYPE_MASK)
{
case MEMCFG_SECT_TYPE_CX:
HWREG(CMMEMCFG_BASE + MEMCFG_O_CXINIT) |=
(MEMCFG_SECT_NUM_MASK & ramSections);
break;
case MEMCFG_SECT_TYPE_CMMSGX:
HWREG(CMMEMCFG_BASE + MEMCFG_O_CMMSGXINIT) |=
(MEMCFG_SECT_NUM_MASK & ramSections);
break;
case MEMCFG_SECT_TYPE_SX:
HWREG(CMMEMCFG_BASE + MEMCFG_O_SXGROUP1_INIT) |=
(MEMCFG_SECT_NUM_MASK & ramSections);
break;
case MEMCFG_SECT_TYPE_MASK:
//
// Initialize all sections.
//
HWREG(CMMEMCFG_BASE + MEMCFG_O_CXINIT) |=
(MEMCFG_SECT_NUM_MASK & MEMCFG_SECT_CX_ALL);
HWREG(CMMEMCFG_BASE + MEMCFG_O_CMMSGXINIT) |=
(MEMCFG_SECT_NUM_MASK & MEMCFG_SECT_CMMSGX_ALL);
HWREG(CMMEMCFG_BASE + MEMCFG_O_SXGROUP1_INIT) |=
(MEMCFG_SECT_NUM_MASK & MEMCFG_SECT_SX_ALL);
break;
default:
//
// Do nothing. Invalid ramSections. Make sure you aren't OR-ing
// values for two different types of RAM.
//
break;
}
}
//*****************************************************************************
//
// MemCfg_getInitStatus
//
//*****************************************************************************
bool
MemCfg_getInitStatus(uint32_t ramSections)
{
uint32_t status;
//
// Check the arguments.
//
ASSERT(((ramSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_CX) ||
((ramSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_SX) ||
((ramSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_CMMSGX) ||
(ramSections == MEMCFG_SECT_ALL));
//
// Read registers containing the initialization complete status.
//
switch(ramSections & MEMCFG_SECT_TYPE_MASK)
{
case MEMCFG_SECT_TYPE_CX:
status = HWREG(CMMEMCFG_BASE + MEMCFG_O_CXINITDONE);
break;
case MEMCFG_SECT_TYPE_CMMSGX:
status = HWREG(CMMEMCFG_BASE + MEMCFG_O_CMMSGXINITDONE);
break;
case MEMCFG_SECT_TYPE_SX:
status = HWREG(CMMEMCFG_BASE + MEMCFG_O_SXGROUP1_INITDONE);
break;
case MEMCFG_SECT_TYPE_MASK:
//
// Return the overall status.
//
if((HWREG(CMMEMCFG_BASE + MEMCFG_O_CXINITDONE) ==
MEMCFG_SECT_CX_ALL) &&
(HWREG(CMMEMCFG_BASE + MEMCFG_O_CMMSGXINITDONE) ==
MEMCFG_SECT_CMMSGX_ALL) &&
(HWREG(CMMEMCFG_BASE + MEMCFG_O_SXGROUP1_INITDONE) ==
MEMCFG_SECT_SX_ALL))
{
status = MEMCFG_SECT_NUM_MASK;
}
else
{
status = 0x0U;
}
break;
default:
//
// Invalid ramSections. Make sure you aren't OR-ing values for two
// different types of RAM.
//
status = 0x0U;
break;
}
return((ramSections & status) == (ramSections & MEMCFG_SECT_NUM_MASK));
}
//*****************************************************************************
//
// MemCfg_forceMemError
//
//*****************************************************************************
void
MemCfg_forceMemError(uint32_t memTypes)
{
//
// Check the arguments.
//
ASSERT((memTypes == MEMCFG_SECT_ROM) ||
(memTypes == MEMCFG_SECT_PERIMEM_EMAC) ||
(memTypes == MEMCFG_SECT_PERIMEM_ETHERCAT) ||
(memTypes == MEMCFG_SECT_ALL));
//
// Forces error in the selected memory.
//
switch(memTypes)
{
case MEMCFG_SECT_ROM:
HWREG(CMMEMCFG_BASE + MEMCFG_O_ROM_FORCE_ERROR) |=
MEMCFG_ROM_FORCE_ERROR_FORCE_BOOTROM_ERROR;
break;
case MEMCFG_SECT_PERIMEM_EMAC:
HWREG(CMMEMCFG_BASE + MEMCFG_O_PERI_MEM_TEST_CONTROL) |=
MEMCFG_PERI_MEM_TEST_CONTROL_EMAC_MEM_FORCE_ERROR;
break;
case MEMCFG_SECT_PERIMEM_ETHERCAT:
HWREG(CMMEMCFG_BASE + MEMCFG_O_PERI_MEM_TEST_CONTROL) |=
MEMCFG_PERI_MEM_TEST_CONTROL_ETHERCAT_MEM_FORCE_ERROR;
break;
case MEMCFG_SECT_ALL:
HWREG(CMMEMCFG_BASE + MEMCFG_O_ROM_FORCE_ERROR) |=
MEMCFG_ROM_FORCE_ERROR_FORCE_BOOTROM_ERROR;
HWREG(CMMEMCFG_BASE + MEMCFG_O_PERI_MEM_TEST_CONTROL) |=
MEMCFG_PERI_MEM_TEST_CONTROL_EMAC_MEM_FORCE_ERROR;
HWREG(CMMEMCFG_BASE + MEMCFG_O_PERI_MEM_TEST_CONTROL) |=
MEMCFG_PERI_MEM_TEST_CONTROL_ETHERCAT_MEM_FORCE_ERROR;
break;
default:
//
// Do nothing. Invalid memory.
//
break;
}
}
//*****************************************************************************
//
// MemCfg_enablePeriMemTestMode
//
//*****************************************************************************
void
MemCfg_enablePeriMemTestMode(uint32_t memTypes)
{
//
// Check the arguments.
//
ASSERT((memTypes == MEMCFG_SECT_PERIMEM_EMAC) ||
(memTypes == MEMCFG_SECT_PERIMEM_ETHERCAT) ||
(memTypes == MEMCFG_SECT_PERIMEM_ALL));
//
// Enables test mode for selected memory type.
//
switch(memTypes)
{
case MEMCFG_SECT_PERIMEM_EMAC:
HWREG(CMMEMCFG_BASE + MEMCFG_O_PERI_MEM_TEST_CONTROL) |=
MEMCFG_PERI_MEM_TEST_CONTROL_EMAC_TEST_ENABLE;
break;
case MEMCFG_SECT_PERIMEM_ETHERCAT:
HWREG(CMMEMCFG_BASE + MEMCFG_O_PERI_MEM_TEST_CONTROL) |=
MEMCFG_PERI_MEM_TEST_CONTROL_ETHERCAT_TEST_ENABLE;
break;
case MEMCFG_SECT_PERIMEM_ALL:
HWREG(CMMEMCFG_BASE + MEMCFG_O_PERI_MEM_TEST_CONTROL) |=
MEMCFG_PERI_MEM_TEST_CONTROL_EMAC_TEST_ENABLE;
HWREG(CMMEMCFG_BASE + MEMCFG_O_PERI_MEM_TEST_CONTROL) |=
MEMCFG_PERI_MEM_TEST_CONTROL_ETHERCAT_TEST_ENABLE;
break;
default:
//
// Do nothing. Invalid memory type.
//
break;
}
}
//*****************************************************************************
//
// MemCfg_disablePeriMemTestMode
//
//*****************************************************************************
void
MemCfg_disablePeriMemTestMode(uint32_t memTypes)
{
//
// Check the arguments.
//
ASSERT((memTypes == MEMCFG_SECT_PERIMEM_EMAC) ||
(memTypes == MEMCFG_SECT_PERIMEM_ETHERCAT) ||
(memTypes == MEMCFG_SECT_PERIMEM_ALL));
//
// Disables test mode for selected memory type.
//
switch(memTypes)
{
case MEMCFG_SECT_PERIMEM_EMAC:
HWREG(CMMEMCFG_BASE + MEMCFG_O_PERI_MEM_TEST_CONTROL) &=
~MEMCFG_PERI_MEM_TEST_CONTROL_EMAC_TEST_ENABLE;
break;
case MEMCFG_SECT_PERIMEM_ETHERCAT:
HWREG(CMMEMCFG_BASE + MEMCFG_O_PERI_MEM_TEST_CONTROL) &=
~MEMCFG_PERI_MEM_TEST_CONTROL_ETHERCAT_TEST_ENABLE;
break;
case MEMCFG_SECT_PERIMEM_ALL:
HWREG(CMMEMCFG_BASE + MEMCFG_O_PERI_MEM_TEST_CONTROL) &=
~MEMCFG_PERI_MEM_TEST_CONTROL_EMAC_TEST_ENABLE;
HWREG(CMMEMCFG_BASE + MEMCFG_O_PERI_MEM_TEST_CONTROL) &=
~MEMCFG_PERI_MEM_TEST_CONTROL_ETHERCAT_TEST_ENABLE;
break;
default:
//
// Do nothing. Invalid memory type.
//
break;
}
}
//*****************************************************************************
//
// MemCfg_getUncorrErrorAddress
//
//*****************************************************************************
uint32_t
MemCfg_getUncorrErrorAddress(uint32_t stsFlag)
{
uint32_t errAddress;
//
// Gets address location of selected uncorrectable read/write error.
//
switch(stsFlag)
{
case MEMCFG_UCERR_M4READ:
case MEMCFG_UCERR_M4WRITE:
errAddress = HWREG(CMMEMORYERROR_BASE + MEMCFG_O_UCM4EADDR);
break;
case MEMCFG_UCERR_EMACREAD:
errAddress = HWREG(CMMEMORYERROR_BASE + MEMCFG_O_UCEMACEADDR);
break;
case MEMCFG_UCERR_UDMAREAD:
case MEMCFG_UCERR_UDMAWRITE:
errAddress = HWREG(CMMEMORYERROR_BASE + MEMCFG_O_UCUDMAEADDR);
break;
case MEMCFG_UCERR_ETHERCATMEMREAD:
errAddress = HWREG(CMMEMORYERROR_BASE + MEMCFG_O_UCETHERCATMEMREADDR);
break;
case MEMCFG_UCERR_EMACMEMREAD:
errAddress = HWREG(CMMEMORYERROR_BASE + MEMCFG_O_UCEMACMEMREADDR);
break;
default:
//
// Invalid stsFlag.
//
errAddress = 0x0U;
break;
}
return(errAddress);
}
//*****************************************************************************
//
// MemCfg_getCorrErrorAddress
//
//*****************************************************************************
uint32_t
MemCfg_getCorrErrorAddress(uint32_t stsFlag)
{
uint32_t errAddress;
//
// Gets address location of selected uncorrectable read/write error.
//
switch(stsFlag)
{
case MEMCFG_CERR_M4READ:
case MEMCFG_CERR_M4WRITE:
errAddress = HWREG(CMMEMORYERROR_BASE + MEMCFG_O_CM4EADDR);
break;
case MEMCFG_CERR_EMACREAD:
errAddress = HWREG(CMMEMORYERROR_BASE + MEMCFG_O_CEMACEADDR);
break;
case MEMCFG_CERR_UDMAREAD:
case MEMCFG_CERR_UDMAWRITE:
errAddress = HWREG(CMMEMORYERROR_BASE + MEMCFG_O_CUDMAEADDR);
break;
default:
//
// Invalid stsFlag.
//
errAddress = 0x0U;
break;
}
return(errAddress);
}
//*****************************************************************************
//
// MemCfg_getBusFaultAddress
//
//*****************************************************************************
uint32_t
MemCfg_getBusFaultAddress(uint32_t busMaster)
{
uint32_t offset, temp;
//
// Calculate the address offset for selected bus master.
//
offset = 0U;
temp = busMaster;
while(temp > 1U)
{
temp = temp >> 1U;
offset += (uint32_t)(MEMCFG_O_UDMABUSFAULTADDR -
MEMCFG_O_M4BUSFAULTADDR);
}
//
// Read and return the bus fault address at the calculated offset.
//
return(HWREG(CMMEMORYERROR_BASE + (uint32_t)MEMCFG_O_M4BUSFAULTADDR +
offset));
}