SLAZ709A October 2017 – June 2025 MSP432E401Y , MSP432E411Y
To address the erratum EPI#01 Data reads can be corrupted when the code address space in the EPI module is used , the following code should be added to the epi.h file.
#ifdef rvmdk
//*****************************************************************************
//
// Keil case.
//
//*****************************************************************************
inline void
EPIWorkaroundWordWrite(uint32_t *pui32Addr, uint32_t ui32Value)
{
uint32_t ui32Scratch;
__asm
{
//
// Add a NOP to ensure we don’t have a flash read immediately before
// the EPI read.
//
NOP
//
// Perform the write we're actually interested in.
//
STR ui32Value, [pui32Addr]
//
// Read from SRAM to ensure that we don't have an EPI write followed by
// a flash read.
//
LDR ui32Scratch, [__current_sp()]
}
}
inline uint32_t
EPIWorkaroundWordRead(uint32_t *pui32Addr)
{
uint32_t ui32Value, ui32Scratch;
__asm
{
//
// Add a NOP to ensure we don’t have a flash read immediately before
// the EPI read.
//
NOP
//
// Perform the read we're actually interested in.
//
LDR ui32Value, [pui32Addr]
//
// Read from SRAM to ensure that we don't have an EPI read followed by
// a flash read.
//
LDR ui32Scratch, [__current_sp()]
}
return(ui32Value);
}
inline void
EPIWorkaroundHWordWrite(uint16_t *pui16Addr, uint16_t ui16Value)
{
uint32_t ui32Scratch;
__asm
{
//
// Add a NOP to ensure we don’t have a flash read immediately before
// the EPI read.
//
NOP
//
// Perform the write we're actually interested in.
//
STRH ui16Value, [pui16Addr]
//
// Read from SRAM to ensure that we don't have an EPI write followed by
// a flash read.
//
LDR ui32Scratch, [__current_sp()]
}
}
inline uint16_t
EPIWorkaroundHWordRead(uint16_t *pui16Addr)
{
uint32_t ui32Scratch;
uint16_t ui16Value;
__asm
{
//
// Add a NOP to ensure we don’t have a flash read immediately before
// the EPI read.
//
NOP
//
// Perform the read we're actually interested in.
//
LDRH ui16Value, [pui16Addr]
//
// Read from SRAM to ensure that we don't have an EPI read followed by
// a flash read.
//
LDR ui32Scratch, [__current_sp()]
}
return(ui16Value);
}
inline void
EPIWorkaroundByteWrite(uint8_t *pui8Addr, uint8_t ui8Value)
{
uint32_t ui32Scratch;
__asm
{
//
// Add a NOP to ensure we don’t have a flash read immediately before
// the EPI read.
//
NOP
//
// Perform the write we're actually interested in.
//
STRB ui8Value, [pui8Addr]
//
// Read from SRAM to ensure that we don't have an EPI write followed by
// a flash read.
//
LDR ui32Scratch, [__current_sp()]
}
}
inline uint8_t
EPIWorkaroundByteRead(uint8_t *pui8Addr)
{
uint32_t ui32Scratch;
uint8_t ui8Value;
__asm
{
//
// Add a NOP to ensure we don’t have a flash read immediately before
// the EPI read.
//
NOP
//
// Perform the read we're actually interested in.
//
LDRB ui8Value, [pui8Addr]
//
// Read from SRAM to ensure that we don't have an EPI read followed by
// a flash read.
//
LDR ui32Scratch, [__current_sp()]
}
return(ui8Value);
}
#else
#ifdef ccs
//*****************************************************************************
//
// Code Composer Studio versions of these functions can be found in separate
// source file epi_workaround_ccs.s.
//
//*****************************************************************************
extern void EPIWorkaroundWordWrite(uint32_t *pui32Addr, uint32_t ui32Value);
extern uint32_t EPIWorkaroundWordRead(uint32_t *pui32Addr);
extern void EPIWorkaroundHWordWrite(uint16_t *pui16Addr, uint16_t ui16Value);
extern uint16_t EPIWorkaroundHWordRead(uint16_t *pui16Addr);
extern void EPIWorkaroundByteWrite(uint8_t *pui8Addr, uint8_t ui8Value);
extern uint8_t EPIWorkaroundByteRead(uint8_t *pui8Addr);
#else
//*****************************************************************************
//
// GCC and IAR case.
//
//*****************************************************************************
inline void
EPIWorkaroundWordWrite(uint32_t *pui32Addr, uint32_t ui32Value)
{
volatile register uint32_t ui32Scratch;
__asm volatile (
//
// Add a NOP to ensure we don’t have a flash read immediately before
// the EPI read.
//
" NOP\n"
" STR %[value],[%[addr]]\n"
" LDR %[scratch],[sp]\n"
: [scratch] "=r" (ui32Scratch)
: [addr] "r" (pui32Addr), [value] "r" (ui32Value)
);
//
// Keep the compiler from generating a warning.
//
ui32Scratch = ui32Scratch;
}
inline uint32_t
EPIWorkaroundWordRead(uint32_t *pui32Addr)
{
volatile register uint32_t ui32Data, ui32Scratch;
//
// ui32Scratch is not used other than to add a padding read following the
// "real" read.
//
__asm volatile(
//
// Add a NOP to ensure we don’t have a flash read immediately before
// the EPI read.
//
" NOP\n"
" LDR %[ret],[%[addr]]\n"
" LDR %[scratch],[sp]\n"
: [ret] "=r" (ui32Data),
[scratch] "=r" (ui32Scratch)
: [addr] "r" (pui32Addr)
);
//
// Keep the compiler from generating a warning.
//
ui32Scratch = ui32Scratch;
return(ui32Data);
}
inline void
EPIWorkaroundHWordWrite(uint16_t *pui16Addr, uint16_t ui16Value)
{
volatile register uint32_t ui32Scratch;
__asm volatile (
//
// Add a NOP to ensure we don’t have a flash read immediately before
// the EPI read.
//
" NOP\n"
" STRH %[value],[%[addr]]\n"
" LDR %[scratch],[sp]\n"
: [scratch] "=r" (ui32Scratch)
: [addr] "r" (pui16Addr), [value] "r" (ui16Value)
);
//
// Keep the compiler from generating a warning.
//
ui32Scratch = ui32Scratch;
}
inline uint16_t
EPIWorkaroundHWordRead(uint16_t *pui16Addr)
{
register uint16_t ui16Data;
register uint32_t ui32Scratch;
//
// ui32Scratch is not used other than to add a padding read following the
// "real" read.
//
__asm volatile(
//
// Add a NOP to ensure we don’t have a flash read immediately before
// the EPI read.
//
" NOP\n"
" LDRH %[ret],[%[addr]]\n"
" LDR %[scratch],[sp]\n"
: [ret] "=r" (ui16Data),
[scratch] "=r" (ui32Scratch)
: [addr] "r" (pui16Addr)
);
//
// Keep the compiler from generating a warning.
//
ui32Scratch = ui32Scratch;
return(ui16Data);
}
inline void
EPIWorkaroundByteWrite(uint8_t *pui8Addr, uint8_t ui8Value)
{
volatile register uint32_t ui32Scratch;
__asm volatile (
//
// Add a NOP to ensure we don’t have a flash read immediately before
// the EPI read.
//
" NOP\n"
" STRB %[value],[%[addr]]\n"
" LDR %[scratch],[sp]\n"
: [scratch] "=r" (ui32Scratch)
: [addr] "r" (pui8Addr), [value] "r" (ui8Value)
);
//
// Keep the compiler from generating a warning.
//
ui32Scratch = ui32Scratch;
}
inline uint8_t
EPIWorkaroundByteRead(uint8_t *pui8Addr)
{
register uint8_t ui8Data;
register uint32_t ui32Scratch;
//
// ui32Scratch is not used other than to add a padding read following the
// "real" read.
//
__asm volatile(
//
// Add a NOP to ensure we don’t have a flash read immediately before
// the EPI read.
//
" NOP\n"
" LDRB %[ret],[%[addr]]\n"
" LDR %[scratch],[sp]\n"
: [ret] "=r" (ui8Data),
[scratch] "=r" (ui32Scratch)
: [addr] "r" (pui8Addr)
);
//
// Keep the compiler from generating a warning.
//
ui32Scratch = ui32Scratch;
return(ui8Data);
}
#endif
In addition, if using CCS, the following code should be saved as a file entitled epi_workaround_ccs.s driverlib directory and included in the project:
;*****************************************************************************
;
; epi_workaround_ccs.s - EPI memory access functions.
;
; Copyright (c) 2013 Texas Instruments Incorporated. All rights reserved.
; TI Information - Selective Disclosure
;
;*****************************************************************************
;*****************************************************************************
;
; void EPIWorkaroundWordWrite(uint32_t *pui32Addr, uint32_t ui32Value)
;
;*****************************************************************************
.sect ".text:EPIWorkaroundWordWrite"
.global EPIWorkaroundWordWrite
EPIWorkaroundWordWrite:
;
; Include a no-op to ensure that we don't have a flash data access
; immediately before the EPI access.
;
nop
;
; Store the word in EPI memory.
;
str r1, [r0]
;
; Make a dummy read from the stack to ensure that we don't have a flash
; data access immediately after the EPI access.
;
ldr r1, [sp]
;
; Return to the caller.
;
bx lr
.align 4
;*****************************************************************************
;
; uint32_t EPIWorkaroundWordRead(uint32_t *pui32Addr)
;
;*****************************************************************************
.sect ".text:EPIWorkaroundWordRead"
.global EPIWorkaroundWordRead
EPIWorkaroundWordRead:
;
; Include a no-op to ensure that we don't have a flash data access
; immediately before the EPI access.
;
nop
;
; Read the word from EPI memory.
;
ldr r0, [r0]
;
; Make a dummy read from the stack to ensure that we don't have a flash
; data access immediately after the EPI access.
;
ldr r1, [r13]
;
; Return to the caller.
;
bx lr
.align 4
;*****************************************************************************
;
; void EPIWorkaroundHWordWrite(uint16_t *pui16Addr, uint16_t ui16Value)
;
;*****************************************************************************
.sect ".text:EPIWorkaroundHWordWrite"
.global EPIWorkaroundHWordWrite
EPIWorkaroundHWordWrite:
;
; Include a no-op to ensure that we don't have a flash data access
; immediately before the EPI access.
;
nop
;
; Store the word in EPI memory.
;
strh r1, [r0]
;
; Make a dummy read from the stack to ensure that we don't have a flash
; data access immediately after the EPI access.
;
ldr r1, [sp]
;
; Return to the caller.
;
bx lr
.align 4
;*****************************************************************************
;
; uint16_t EPIWorkaroundHWordRead(uint16_t *pui16Addr)
;
;*****************************************************************************
.sect ".text:EPIWorkaroundHWordRead"
.global EPIWorkaroundHWordRead
EPIWorkaroundHWordRead:
;
; Include a no-op to ensure that we don't have a flash data access
; immediately before the EPI access.
;
nop
;
; Read the half word from EPI memory.
;
ldrh r0, [r0]
;
; Make a dummy read from the stack to ensure that we don't have a flash
; data access immediately after the EPI access.
;
ldr r1, [r13]
;
; Return to the caller.
;
bx lr
.align 4
;*****************************************************************************
;
; void EPIWorkaroundByteWrite(uint8_t *pui8Addr, uint8_t ui8Value)
;
;*****************************************************************************
.sect ".text:EPIWorkaroundByteWrite"
.global EPIWorkaroundByteWrite
EPIWorkaroundByteWrite:
;
; Include a no-op to ensure that we don't have a flash data access
; immediately before the EPI access.
;
nop
;
; Store the byte in EPI memory.
;
strb r1, [r0]
;
; Make a dummy read from the stack to ensure that we don't have a flash
; data access immediately after the EPI access.
;
ldr r1, [sp]
;
; Return to the caller.
;
bx lr
.align 4
;*****************************************************************************
;
; uint8_t EPIWorkaroundByteRead(uint8_t *pui8Addr)
;
;*****************************************************************************
.sect ".text:EPIWorkaroundByteRead"
.global EPIWorkaroundByteRead
EPIWorkaroundByteRead:
;
; Include a no-op to ensure that we don't have a flash data access
; immediately before the EPI access.
;
nop
;
; Read the byte from EPI memory.
;
ldrb r0, [r0]
;
; Make a dummy read from the stack to ensure that we don't have a flash
; data access immediately after the EPI access.
;
ldr r1, [r13]
;
; Return to the caller.
;
bx lr
.align 4
.end