empty_project_28377D/device/driverlib/memcfg.c

700 lines
22 KiB
C

//###########################################################################
//
// FILE: memcfg.c
//
// TITLE: C28x RAM config driver.
//
//###########################################################################
// $Copyright:
// Copyright (C) 2022 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_D) ||
((memSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_LS) ||
((memSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_GS) ||
(memSections == MEMCFG_SECT_ALL));
//
// Set the bit that blocks writes to the sections' configuration registers.
//
EALLOW;
switch(memSections & MEMCFG_SECT_TYPE_MASK)
{
case MEMCFG_SECT_TYPE_D:
HWREG(MEMCFG_BASE + MEMCFG_O_DXLOCK) |= MEMCFG_SECT_NUM_MASK &
memSections;
break;
case MEMCFG_SECT_TYPE_LS:
HWREG(MEMCFG_BASE + MEMCFG_O_LSXLOCK) |= MEMCFG_SECT_NUM_MASK &
memSections;
break;
case MEMCFG_SECT_TYPE_GS:
HWREG(MEMCFG_BASE + MEMCFG_O_GSXLOCK) |= MEMCFG_SECT_NUM_MASK &
memSections;
break;
case MEMCFG_SECT_TYPE_MASK:
//
// Lock configuration for all sections.
//
HWREG(MEMCFG_BASE + MEMCFG_O_DXLOCK) |= MEMCFG_SECT_NUM_MASK &
MEMCFG_SECT_DX_ALL;
HWREG(MEMCFG_BASE + MEMCFG_O_LSXLOCK) |= MEMCFG_SECT_NUM_MASK &
MEMCFG_SECT_LSX_ALL;
HWREG(MEMCFG_BASE + MEMCFG_O_GSXLOCK) |= MEMCFG_SECT_NUM_MASK &
MEMCFG_SECT_GSX_ALL;
break;
default:
//
// Do nothing. Invalid memSections. Make sure you aren't OR-ing
// values for two different types of memory sections.
//
break;
}
EDIS;
}
//*****************************************************************************
//
// MemCfg_unlockConfig
//
//*****************************************************************************
void
MemCfg_unlockConfig(uint32_t memSections)
{
//
// Check the arguments.
//
ASSERT(((memSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_D) ||
((memSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_LS) ||
((memSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_GS) ||
(memSections == MEMCFG_SECT_ALL));
//
// Clear the bit that blocks writes to the sections' configuration
// registers.
//
EALLOW;
switch(memSections & MEMCFG_SECT_TYPE_MASK)
{
case MEMCFG_SECT_TYPE_D:
HWREG(MEMCFG_BASE + MEMCFG_O_DXLOCK) &= ~(MEMCFG_SECT_NUM_MASK &
memSections);
break;
case MEMCFG_SECT_TYPE_LS:
HWREG(MEMCFG_BASE + MEMCFG_O_LSXLOCK) &= ~(MEMCFG_SECT_NUM_MASK &
memSections);
break;
case MEMCFG_SECT_TYPE_GS:
HWREG(MEMCFG_BASE + MEMCFG_O_GSXLOCK) &= ~(MEMCFG_SECT_NUM_MASK &
memSections);
break;
case MEMCFG_SECT_TYPE_MASK:
//
// Unlock configuration for all sections.
//
HWREG(MEMCFG_BASE + MEMCFG_O_DXLOCK) &=
~((uint32_t)(MEMCFG_SECT_NUM_MASK & MEMCFG_SECT_DX_ALL));
HWREG(MEMCFG_BASE + MEMCFG_O_LSXLOCK) &=
~((uint32_t)(MEMCFG_SECT_NUM_MASK & MEMCFG_SECT_LSX_ALL));
HWREG(MEMCFG_BASE + MEMCFG_O_GSXLOCK) &=
~((uint32_t)(MEMCFG_SECT_NUM_MASK & MEMCFG_SECT_GSX_ALL));
break;
default:
//
// Do nothing. Invalid memSections. Make sure you aren't OR-ing
// values for two different types of memory sections.
//
break;
}
EDIS;
}
//*****************************************************************************
//
// MemCfg_commitConfig
//
//*****************************************************************************
void
MemCfg_commitConfig(uint32_t memSections)
{
//
// Check the arguments.
//
ASSERT(((memSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_D) ||
((memSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_LS) ||
((memSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_GS) ||
(memSections == MEMCFG_SECT_ALL));
//
// Set the bit that permanently blocks writes to the sections'
// configuration registers.
//
EALLOW;
switch(memSections & MEMCFG_SECT_TYPE_MASK)
{
case MEMCFG_SECT_TYPE_D:
HWREG(MEMCFG_BASE + MEMCFG_O_DXCOMMIT) |= MEMCFG_SECT_NUM_MASK &
memSections;
break;
case MEMCFG_SECT_TYPE_LS:
HWREG(MEMCFG_BASE + MEMCFG_O_LSXCOMMIT) |= MEMCFG_SECT_NUM_MASK &
memSections;
break;
case MEMCFG_SECT_TYPE_GS:
HWREG(MEMCFG_BASE + MEMCFG_O_GSXCOMMIT) |= MEMCFG_SECT_NUM_MASK &
memSections;
break;
case MEMCFG_SECT_TYPE_MASK:
//
// Commit configuration for all sections.
//
HWREG(MEMCFG_BASE + MEMCFG_O_DXCOMMIT) |= MEMCFG_SECT_NUM_MASK &
MEMCFG_SECT_DX_ALL;
HWREG(MEMCFG_BASE + MEMCFG_O_LSXCOMMIT) |= MEMCFG_SECT_NUM_MASK &
MEMCFG_SECT_LSX_ALL;
HWREG(MEMCFG_BASE + MEMCFG_O_GSXCOMMIT) |= MEMCFG_SECT_NUM_MASK &
MEMCFG_SECT_GSX_ALL;
break;
default:
//
// Do nothing. Invalid memSections. Make sure you aren't OR-ing
// values for two different types of RAM.
//
break;
}
EDIS;
}
//*****************************************************************************
//
// MemCfg_setProtection
//
//*****************************************************************************
void
MemCfg_setProtection(uint32_t memSection, uint32_t protectMode)
{
uint32_t shiftVal = 0U;
uint32_t maskVal;
uint32_t regVal;
uint32_t sectionNum;
uint32_t regOffset;
//
// Check the arguments.
//
ASSERT(((memSection & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_LS) ||
((memSection & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_D) ||
((memSection & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_GS));
//
// 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 8 bits in the corresponding ACCPROT register.
//
sectionNum = memSection & MEMCFG_SECT_NUM_MASK;
while(sectionNum != 1U)
{
sectionNum = sectionNum >> 1U;
shiftVal += 8U;
}
//
// Calculate register offset. Also, make sure the shift value is no greater
// than 31.
//
regOffset = (shiftVal & ~(0x1FU)) >> 4U;
shiftVal &= 0x0001FU;
maskVal = (uint32_t)MEMCFG_XACCPROTX_M << shiftVal;
regVal = protectMode << shiftVal;
//
// Write the access protection mode into the appropriate field
//
EALLOW;
switch(memSection & MEMCFG_SECT_TYPE_MASK)
{
case MEMCFG_SECT_TYPE_D:
HWREG(MEMCFG_BASE + MEMCFG_O_DXACCPROT0 + regOffset) &= ~maskVal;
HWREG(MEMCFG_BASE + MEMCFG_O_DXACCPROT0 + regOffset) |= regVal;
break;
case MEMCFG_SECT_TYPE_LS:
HWREG(MEMCFG_BASE + MEMCFG_O_LSXACCPROT0 + regOffset) &= ~maskVal;
HWREG(MEMCFG_BASE + MEMCFG_O_LSXACCPROT0 + regOffset) |= regVal;
break;
case MEMCFG_SECT_TYPE_GS:
HWREG(MEMCFG_BASE + MEMCFG_O_GSXACCPROT0 + regOffset) &= ~maskVal;
HWREG(MEMCFG_BASE + MEMCFG_O_GSXACCPROT0 + regOffset) |= regVal;
break;
default:
//
// Do nothing. Invalid memSection.
//
break;
}
EDIS;
}
//*****************************************************************************
//
// MemCfg_setLSRAMControllerSel
//
//*****************************************************************************
void
MemCfg_setLSRAMControllerSel(uint32_t ramSection,
MemCfg_LSRAMControllerSel controllerSel)
{
uint32_t shiftVal;
uint32_t temp;
//
// Check the arguments.
//
ASSERT((ramSection & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_LS);
//
// Calculate how far the controller select value needs to be shifted. Each
// section number is represented by a bit in the lower word of ramSection
// and 2 bits in the corresponding MSEL register.
//
shiftVal = 0U;
temp = MEMCFG_SECT_NUM_MASK & ramSection;
while(temp != 1U)
{
temp = temp >> 1U;
shiftVal += 2U;
}
//
// Write the controller select setting into the appropriate field
//
EALLOW;
HWREG(MEMCFG_BASE + MEMCFG_O_LSXMSEL) =
(HWREG(MEMCFG_BASE + MEMCFG_O_LSXMSEL) &
~((uint32_t)MEMCFG_LSXMSEL_MSEL_LS0_M << shiftVal)) |
((uint32_t)controllerSel << shiftVal);
EDIS;
}
//*****************************************************************************
//
// MemCfg_setGSRAMControllerSel
//
//*****************************************************************************
void
MemCfg_setGSRAMControllerSel(uint32_t ramSections,
MemCfg_GSRAMControllerSel controllerSel)
{
uint32_t sectionNum;
//
// Check the arguments.
//
ASSERT((ramSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_GS);
//
// We only need the section number bits for this function.
//
sectionNum = ramSections & MEMCFG_SECT_NUM_MASK;
//
// Write the controller select setting into the appropriate field.
//
EALLOW;
if(controllerSel == MEMCFG_GSRAMCONTROLLER_CPU1)
{
HWREG(MEMCFG_BASE + MEMCFG_O_GSXMSEL) &= ~sectionNum;
}
else
{
HWREG(MEMCFG_BASE + MEMCFG_O_GSXMSEL) |= sectionNum;
}
EDIS;
}
//*****************************************************************************
//
// 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_D) ||
((memSection & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_LS) ||
((memSection & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_GS) ||
((memSection & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_MSG));
//
// 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_XTEST_M << shiftVal;
regVal = (uint32_t)testMode << shiftVal;
//
// Write the test mode into the appropriate field
//
EALLOW;
switch(memSection & MEMCFG_SECT_TYPE_MASK)
{
case MEMCFG_SECT_TYPE_D:
HWREG(MEMCFG_BASE + MEMCFG_O_DXTEST) &= ~maskVal;
HWREG(MEMCFG_BASE + MEMCFG_O_DXTEST) |= regVal;
break;
case MEMCFG_SECT_TYPE_LS:
HWREG(MEMCFG_BASE + MEMCFG_O_LSXTEST) &= ~maskVal;
HWREG(MEMCFG_BASE + MEMCFG_O_LSXTEST) |= regVal;
break;
case MEMCFG_SECT_TYPE_GS:
HWREG(MEMCFG_BASE + MEMCFG_O_GSXTEST) &= ~maskVal;
HWREG(MEMCFG_BASE + MEMCFG_O_GSXTEST) |= regVal;
break;
case MEMCFG_SECT_TYPE_MSG:
HWREG(MEMCFG_BASE + MEMCFG_O_MSGXTEST) &= ~maskVal;
HWREG(MEMCFG_BASE + MEMCFG_O_MSGXTEST) |= regVal;
break;
default:
//
// Do nothing. Invalid memSection.
//
break;
}
EDIS;
}
//*****************************************************************************
//
// MemCfg_initSections
//
//*****************************************************************************
void
MemCfg_initSections(uint32_t ramSections)
{
//
// Check the arguments.
//
ASSERT(((ramSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_D) ||
((ramSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_LS) ||
((ramSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_GS) ||
((ramSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_MSG) ||
(ramSections == MEMCFG_SECT_ALL));
//
// Set the bit in the various initialization registers that starts
// initialization.
//
EALLOW;
switch(ramSections & MEMCFG_SECT_TYPE_MASK)
{
case MEMCFG_SECT_TYPE_D:
HWREG(MEMCFG_BASE + MEMCFG_O_DXINIT) |= MEMCFG_SECT_NUM_MASK &
ramSections;
break;
case MEMCFG_SECT_TYPE_LS:
HWREG(MEMCFG_BASE + MEMCFG_O_LSXINIT) |= MEMCFG_SECT_NUM_MASK &
ramSections;
break;
case MEMCFG_SECT_TYPE_GS:
HWREG(MEMCFG_BASE + MEMCFG_O_GSXINIT) |= MEMCFG_SECT_NUM_MASK &
ramSections;
break;
case MEMCFG_SECT_TYPE_MSG:
HWREG(MEMCFG_BASE + MEMCFG_O_MSGXINIT) |= MEMCFG_SECT_NUM_MASK &
ramSections;
break;
case MEMCFG_SECT_TYPE_MASK:
//
// Initialize all sections.
//
HWREG(MEMCFG_BASE + MEMCFG_O_DXINIT) |= MEMCFG_SECT_NUM_MASK &
MEMCFG_SECT_DX_ALL;
HWREG(MEMCFG_BASE + MEMCFG_O_LSXINIT) |= MEMCFG_SECT_NUM_MASK &
MEMCFG_SECT_LSX_ALL;
HWREG(MEMCFG_BASE + MEMCFG_O_GSXINIT) |= MEMCFG_SECT_NUM_MASK &
MEMCFG_SECT_GSX_ALL;
HWREG(MEMCFG_BASE + MEMCFG_O_MSGXINIT) |= MEMCFG_SECT_NUM_MASK &
MEMCFG_SECT_MSGX_ALL;
break;
default:
//
// Do nothing. Invalid ramSections. Make sure you aren't OR-ing
// values for two different types of RAM.
//
break;
}
EDIS;
}
//*****************************************************************************
//
// MemCfg_getInitStatus
//
//*****************************************************************************
bool
MemCfg_getInitStatus(uint32_t ramSections)
{
uint32_t status;
//
// Check the arguments.
//
ASSERT(((ramSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_D) ||
((ramSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_LS) ||
((ramSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_GS) ||
((ramSections & MEMCFG_SECT_TYPE_MASK) == MEMCFG_SECT_TYPE_MSG) ||
(ramSections == MEMCFG_SECT_ALL));
//
// Read registers containing the initialization complete status.
//
switch(ramSections & MEMCFG_SECT_TYPE_MASK)
{
case MEMCFG_SECT_TYPE_D:
status = HWREG(MEMCFG_BASE + MEMCFG_O_DXINITDONE);
break;
case MEMCFG_SECT_TYPE_LS:
status = HWREG(MEMCFG_BASE + MEMCFG_O_LSXINITDONE);
break;
case MEMCFG_SECT_TYPE_GS:
status = HWREG(MEMCFG_BASE + MEMCFG_O_GSXINITDONE);
break;
case MEMCFG_SECT_TYPE_MSG:
status = HWREG(MEMCFG_BASE + MEMCFG_O_MSGXINITDONE);
break;
case MEMCFG_SECT_TYPE_MASK:
//
// Return the overall status.
//
if((HWREG(MEMCFG_BASE + MEMCFG_O_DXINITDONE) ==
MEMCFG_SECT_DX_ALL) &&
(HWREG(MEMCFG_BASE + MEMCFG_O_LSXINITDONE) ==
MEMCFG_SECT_LSX_ALL) &&
(HWREG(MEMCFG_BASE + MEMCFG_O_GSXINITDONE) ==
MEMCFG_SECT_GSX_ALL) &&
(HWREG(MEMCFG_BASE + MEMCFG_O_MSGXINITDONE) ==
MEMCFG_SECT_MSGX_ALL))
{
status = MEMCFG_SECT_NUM_MASK;
}
else
{
status = 0U;
}
break;
default:
//
// Invalid ramSections. Make sure you aren't OR-ing values for two
// different types of RAM.
//
status = 0U;
break;
}
return((ramSections & status) == (ramSections & MEMCFG_SECT_NUM_MASK));
}
//*****************************************************************************
//
// MemCfg_getViolationAddress
//
//*****************************************************************************
uint32_t
MemCfg_getViolationAddress(uint32_t intFlag)
{
uint32_t address;
uint32_t stsNumber;
//
// Calculate the the address of the desired violation address register.
//
if((intFlag & MEMCFG_MVIOL_MASK) != 0U)
{
stsNumber = intFlag >> MEMCFG_MVIOL_SHIFT;
address = ACCESSPROTECTION_BASE + MEMCFG_O_MCPUFAVADDR;
}
else
{
stsNumber = intFlag;
address = ACCESSPROTECTION_BASE + MEMCFG_O_NMCPURDAVADDR;
}
while(stsNumber > 1U)
{
stsNumber = stsNumber >> 1U;
address += (uint32_t)(MEMCFG_O_NMCPUWRAVADDR - MEMCFG_O_NMCPURDAVADDR);
}
//
// Read and return the access violation address at the calculated location.
//
return(HWREG(address));
}
//*****************************************************************************
//
// MemCfg_getCorrErrorAddress
//
//*****************************************************************************
uint32_t
MemCfg_getCorrErrorAddress(uint32_t stsFlag)
{
//
// Check the arguments.
//
if(stsFlag != MEMCFG_CERR_CPUREAD)
{
//
// Currently, the only correctable error address that can be read
// from a register is one for a CPU read error (MEMCFG_CERR_CPUREAD).
// For the sake of keeping this function portable to possible future
// devices with other error types, it still takes a stsFlag parameter.
//
ASSERT((bool)false);
}
//
// Read and return the error address.
//
return(HWREG(MEMORYERROR_BASE + MEMCFG_O_CCPUREADDR));
}
//*****************************************************************************
//
// MemCfg_getUncorrErrorAddress
//
//*****************************************************************************
uint32_t
MemCfg_getUncorrErrorAddress(uint32_t stsFlag)
{
uint32_t address;
uint32_t temp;
//
// Calculate the the address of the desired error address register.
//
address = MEMORYERROR_BASE + MEMCFG_O_UCCPUREADDR;
temp = stsFlag;
while(temp > 1U)
{
temp = temp >> 1U;
address += (uint32_t)(MEMCFG_O_UCDMAREADDR - MEMCFG_O_UCCPUREADDR);
}
//
// Read and return the error address at the calculated location.
//
return(HWREG(address));
}