3.1.2 Using the Library
ICM can be configured to cover different purposes:
- Digest mode: Get the Hash values according to the region configurations.
- Compare mode: Compare the Hash value previously calculated with the new Hash value obtained from the same memory region.
- Monitor mode: The ICM passes through the Main List once to calculate the message digest of the monitored area and begins monitoring.
Digest mode
/* Hash area */
uint32_t outputSHA[0x20] __ALIGNED(128);
/* Memory region0 area */
volatile uint32_t appData[16] = {
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678
};
void SYS_Initialize ( void* data )
{
(...)
ICM_Initialize();
(...)
}
static void lAppHashCompletedCallback(ICM_REGION_ID regionId)
{
if (regionId == ICM_REGION_0)
{
appData.hashCompleted = true;
}
}
void APP_Initialize ( void )
{
appData.state = APP_STATE_CONFIGURE_ICM;
appData.hashCompleted = false;
(void *)memset((uint8_t *)outputSHA, 0, sizeof(outputSHA));
}
void APP_Tasks ( void )
{
switch ( appData.state )
{
case APP_STATE_CONFIGURE_ICM:
{
ICM_SetRegionDescriptorData(ICM_REGION_0, (uint32_t *)appData, sizeof(appData));
ICM_SetHashAreaAddress((uint32_t)outputSHA);
// Set ICM callbacks (Hash Completed))
ICM_CallbackRegister(ICM_INTERRUPT_RHC, lAppHashCompletedCallback);
ICM_EnableInterrupt(ICM_INTERRUPT_RHC, ICM_REGION_0);
// Compute de Hash values
ICM_Enable();
appData.state = APP_STATE_WAIT_DIGEST;
break;
}
case APP_STATE_WAIT_DIGEST:
{
if (appData.hashCompleted == true)
{
ICM_Disable();
}
break;
}
default:
{
/* TODO: Handle error in application's state machine. */
break;
}
}
}
Compare mode
/* Hash area */
uint32_t outputSHA[0x20] __ALIGNED(128);
/* Memory region0 area */
volatile uint32_t appMessageSHA0[16] = {
0x80636261,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x18000000
};
/* Memory region1 main list area,
* string "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" */
volatile uint32_t appMessageSHA1[16] = {
0x64636261,
0x65646362,
0x66656463,
0x67666564,
0x68676665,
0x69686766,
0x6a696867,
0x6b6a6968,
0x6c6b6a69,
0x6d6c6b6a,
0x6e6d6c6b,
0x6f6e6d6c,
0x706f6e6d,
0x71706f6e,
0x00000080,
0x00000000
};
/* Memory region1 secondary list area */
volatile uint32_t appMessageSHA1Sec[16] = {
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0xc0010000
};
void SYS_Initialize ( void* data )
{
(...)
ICM_Initialize();
(...)
}
static void lAppHashCompletedCallback(ICM_REGION_ID regionId)
{
if (regionId == ICM_REGION_0)
{
appData.hashCompleted = true;
}
}
static void _appDigestMismatchCallback(ICM_REGION_ID regionId)
{
if (regionId == ICM_REGION_0) {
printf("...ICM_REGION_0 is modified\r\n");
appData.data0Changed = true;
} else if (regionId == ICM_REGION_1) {
printf("...ICM_REGION_1 is modified\r\n");
appData.data1Changed = true;
}
}
void APP_Initialize ( void )
{
appData.state = APP_STATE_CONFIGURE_ICM;
appData.hashCompleted = false;
appData.data0Changed = false;
appData.data1Changed = false;
(void *)memset((uint8_t *)outputSHA, 0, sizeof(outputSHA));
}
void APP_Tasks ( void )
{
switch ( appData.state )
{
case APP_STATE_CONFIGURE_ICM:
{
ICM_SECONDARY_LIST icmSecList;
ICM_SetRegionDescriptorData(ICM_REGION_0, (uint32_t *)appMessageSHA0, sizeof(appMessageSHA0));
ICM_SetRegionDescriptorData(ICM_REGION_1, (uint32_t *)appMessageSHA1, sizeof(appMessageSHA1));
ICM_SetHashAreaAddress((uint32_t)outputSHA);
// Configure Secondary List of the region 1
appData.pRegionDescriptor = ICM_GetRegionDescriptor(ICM_REGION_1);
appData.pRegionDescriptor->secondaryList = &icmSecList;
icmSecList.startAddress = (uint32_t)appMessageSHA1Sec;
icmSecList.transferSize = ICM_GetTransferSize(sizeof(appMessageSHA1Sec));
icmSecList.nextAddress = 0;
// Compute de Hash values
ICM_Enable();
appData.state = APP_STATE_WAIT_DIGEST;
break;
}
case APP_STATE_WAIT_DIGEST:
{
if (appData.hashCompleted == true)
{
appData.state = APP_STATE_MODIFY_REGION0_DATA;
}
break;
}
case APP_STATE_MODIFY_REGION0_DATA:
{
// Set Compare mode
appData.pRegionDescriptor = ICM_GetRegionDescriptor(ICM_REGION_0);
appData.pRegionDescriptor->config.bitfield.compareMode = 1;
appData.pRegionDescriptor = ICM_GetRegionDescriptor(ICM_REGION_1);
appData.pRegionDescriptor->config.bitfield.compareMode = 1;
// Set ICM callbacks
ICM_CallbackRegister(ICM_INTERRUPT_RDM, _appDigestMismatchCallback);
ICM_EnableInterrupt(ICM_INTERRUPT_RDM, ICM_REGION_0);
ICM_EnableInterrupt(ICM_INTERRUPT_RDM, ICM_REGION_1);
printf("Change Data in Region 0\r\n");
appMessageSHA0[2] = 1;
ICM_Enable();
appData.state = APP_STATE_WAIT_REGION0_MISMATCH;
break;
}
case APP_STATE_WAIT_REGION0_MISMATCH:
{
if (appData.data0Changed == true)
{
appData.data0Changed = false;
printf("...appMessageSHA0 content has been modified\r\n\r\n");
// restore data content
appMessageSHA0[2] = 0;
appData.state = APP_STATE_MODIFY_REGION1_DATA;
}
break;
}
case APP_STATE_MODIFY_REGION1_DATA:
{
printf("Change Data in Region 1\r\n");
appMessageSHA1[5] = 0xAA5555AA;
ICM_Enable();
appData.state = APP_STATE_WAIT_REGION1_MISMATCH;
break;
}
case APP_STATE_WAIT_REGION1_MISMATCH:
{
if (appData.data1Changed == true)
{
appData.data1Changed = false;
printf("...appMessageSHA1 content has been modified\r\n\r\n");
// restore data content
appMessageSHA1[5] = 0x69686766;
appData.state = APP_STATE_MODIFY_REGION1SEC_DATA;
}
break;
}
case APP_STATE_MODIFY_REGION1SEC_DATA:
{
printf("Change Data in Region 1 - secondary list\r\n");
appMessageSHA1Sec[5] = 0xAA5555AA;
ICM_Enable();
appData.state = APP_STATE_WAIT_REGION1SEC_MISMATCH;
break;
}
case APP_STATE_WAIT_REGION1SEC_MISMATCH:
{
if (appData.data1Changed == true)
{
appData.data1Changed = false;
printf("...appMessageSHA1Sec content has been modified\r\n\r\n");
appData.state = APP_STATE_IDLE;
}
break;
}
case APP_STATE_IDLE:
default:
{
/* TODO: Handle error in application's state machine. */
break;
}
}
}
Monitor mode
/* Hash area */
uint32_t outputSHA[0x20] __ALIGNED(128);
/* Memory region0 area */
volatile uint32_t appMonitoredData[16] = {
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678,
0x12345678
};
void SYS_Initialize ( void* data )
{
(...)
ICM_Initialize();
(...)
}
static void lAppHashCompletedCallback(ICM_REGION_ID regionId)
{
if (regionId == ICM_REGION_0)
{
appData.hashCompleted = true;
}
}
static void lAppDigestMismatchCallback(ICM_REGION_ID regionId)
{
if (regionId == ICM_REGION_0) {
appData.dataChanged = true;
}
}
void lAppTimerCallback ( uintptr_t context )
{
appData.timerExpired = true;
}
void APP_Initialize ( void )
{
appData.state = APP_STATE_CONFIGURE_ICM;
appData.hashCompleted = false;
appData.dataChanged = false;
appData.timerExpired = false;
(void *)memset((uint8_t *)outputSHA, 0, sizeof(outputSHA));
}
void APP_Tasks ( void )
{
switch ( appData.state )
{
case APP_STATE_CONFIGURE_ICM:
{
ICM_SetRegionDescriptorData(ICM_REGION_0, (uint32_t *)appData, sizeof(appData));
ICM_SetHashAreaAddress((uint32_t)outputSHA);
// Set ICM callbacks (Hash Completed))
ICM_CallbackRegister(ICM_INTERRUPT_RHC, lAppHashCompletedCallback);
ICM_EnableInterrupt(ICM_INTERRUPT_RHC, ICM_REGION_0);
// Compute de Hash values
ICM_Enable();
appData.state = APP_STATE_WAIT_DIGEST;
break;
}
case APP_STATE_WAIT_DIGEST:
{
if (appData.hashCompleted == true)
{
ICM_Disable();
// Disable ICM callbacks (Hash Completed))
ICM_CallbackRegister(ICM_INTERRUPT_RHC, NULL);
ICM_DisableInterrupt(ICM_INTERRUPT_RHC, ICM_REGION_0);
// Set ICM Monitor Mode
appData.pRegionDescriptor = ICM_GetRegionDescriptor(ICM_REGION_0);
appData.pRegionDescriptor->config.bitfield.compareMode = 1;
appData.pRegionDescriptor->config.bitfield.wrap = 1;
appData.pRegionDescriptor->config.bitfield.endMonitor = 0;
appData.pRegionDescriptor->config.bitfield.mismatchIntDis = 0;
// Set ICM callbacks (Digest mismatch)
ICM_CallbackRegister(ICM_INTERRUPT_RDM, lAppDigestMismatchCallback);
ICM_EnableInterrupt(ICM_INTERRUPT_RDM, ICM_REGION_0);
ICM_SetMonitorMode(true, 15);
ICM_EnableRegionMonitor(ICM_REGION_0);
ICM_Enable();
// Launch Periodic Timer to Modify data
appData.timer = SYS_TIME_CallbackRegisterMS(lAppTimerCallback, 0,
APP_TIME_TO_CHANGE_DATA,
SYS_TIME_SINGLE);
appData.state = APP_STATE_MODIFY_REGION0_DATA;
}
break;
}
case APP_STATE_MODIFY_REGION0_DATA:
{
if (appData.timerExpired == true)
{
appData.timerExpired = false;
appMonitoredData[2] = 1;
appData.state = APP_STATE_WAIT_REGION0_MISMATCH;
}
break;
}
case APP_STATE_WAIT_REGION0_MISMATCH:
{
if (appData.dataChanged == true)
{
appData.dataChanged = false;
// restore data content
appMonitoredData[2] = 0x12345678;
appData.state = APP_STATE_IDLE;
}
break;
}
case APP_STATE_IDLE:
default:
{
/* TODO: Handle error in application's state machine. */
break;
}
}
}
