Hi jingpan,
Thank you for your reply, instead of making sure the DCP only accesses non-cacheable memory I'm trying the following: (FYI: In this reply I will be referring to source code found in fsl_dcp.[hc] found in the SDK version 2.5.0 of the i.mx RT 1050 board.)
I've adapted dcp_schedule_work to clean or invalidate the data cache lines wrt to the dcpPacket, it cleans or invalidates the memory area of the packet itself, and the memory areas pointed to by the pointers contained in the dcpPacket, namely nextCmdAddress, sourceBufferAddres, destinationBufferAddress & payloadPointer. I've pasted the definition of the _dcp_work_packet struct for your reference.
/*! @brief DCP's work packet. */
typedef struct _dcp_work_packet
{
uint32_t nextCmdAddress;
uint32_t control0;
uint32_t control1;
uint32_t sourceBufferAddress;
uint32_t destinationBufferAddress;
uint32_t bufferSize;
uint32_t payloadPointer;
uint32_t status;
} dcp_work_packet_t;
Can this approach ever work? And if not, why not? Am I looking over something? FYI, when running the mbedTLS_selftest from SDK 2.5.0 this approach seems to work well, except it fails when running the hmac_drbg_self_test for the first time, susbsequent runs pass.
I like this centralized handling of the cache, because then the DCP can be used by client code without worrying about cache coherence.
(added code in bold)
static status_t dcp_schedule_work(DCP_Type *base, dcp_handle_t *handle, dcp_work_packet_t *dcpPacket)
{
status_t status;
/* check if our channel is active */
if ((base->STAT & (uint32_t)handle->channel) != handle->channel)
{
/* disable global interrupt */
uint32_t currPriMask = DisableGlobalIRQ();
dcp_clean_dcpPacket(dcpPacket); /* Clean data cache with regard to dcp packet itself and its contents */
/* re-check if our channel is still available */
if ((base->STAT & (uint32_t)handle->channel) == 0)
{
volatile uint32_t *cmdptr = NULL;
volatile uint32_t *chsema = NULL;
switch (handle->channel)
{
case kDCP_Channel0:
cmdptr = &base->CH0CMDPTR;
chsema = &base->CH0SEMA;
break;
case kDCP_Channel1:
cmdptr = &base->CH1CMDPTR;
chsema = &base->CH1SEMA;
break;
case kDCP_Channel2:
cmdptr = &base->CH2CMDPTR;
chsema = &base->CH2SEMA;
break;
case kDCP_Channel3:
cmdptr = &base->CH3CMDPTR;
chsema = &base->CH3SEMA;
break;
default:
break;
}
if (cmdptr && chsema)
{
/* set out packet to DCP CMDPTR */
*cmdptr = (uint32_t)dcpPacket;
/* set the channel semaphore */
*chsema = 1u;
}
status = kStatus_Success;
}
else
{
status = kStatus_DCP_Again;
}
/* global interrupt enable */
dcp_invalidate_dcpPacket(dcpPacket); /* Invalidate data cache with regard to dcp packet itself and its contents */
EnableGlobalIRQ(currPriMask);
}
else
{
return kStatus_DCP_Again;
}
return status;
}