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;
        }
    }
}