
#include <cmsis_os.h>                                           // CMSIS RTOS header file
#include <stdio.h>

#include "CRC32.h"
#define ROM_BLOCK_LEN    0x0000FFFC
#define ROM_BLOCK_NO     4

uint32_t crc_nominal_dummy0 __attribute__((at(0x0000FFFC)));
uint32_t crc_nominal_dummy1 __attribute__((at(0x0001FFFC)));
uint32_t crc_nominal_dummy2 __attribute__((at(0x0002FFFC)));
uint32_t crc_nominal_dummy3 __attribute__((at(0x0003FFFC)));

typedef struct crc_info
{
    const uint32_t crc_block_nominal;
    uint32_t       blockstart;
} crc_info_t;

crc_info_t g_crc_info[ROM_BLOCK_NO] = {
    0x0000FFFCul, 0x00000000ul,
    0x0001FFFCul, 0x00010000ul,
    0x0002FFFCul, 0x00020000ul,
    0x0003FFFCul, 0x00030000ul
};

enum system_exceptions_t
{
    SELFTEST_ROM_MISMATCH = 1
};

void raise_exception(enum system_exceptions_t fault_code, uint32_t param)
{
    switch (fault_code)
    {
    case SELFTEST_ROM_MISMATCH:
        //handle invalid ROM image exception
        break;
    }
}

/*----------------------------------------------------------------------------
*      SelfTest_Thread  'SelfTest_Thread'
*---------------------------------------------------------------------------*/

void SelfTest_Thread(void const *argument);                              // thread function
osThreadId tid_SelfTest_Thread;                                          // thread id
osThreadDef(SelfTest_Thread, osPriorityBelowNormal, 1, 0);                    // thread object

int Init_SelfTest_Thread(void)
{
    tid_SelfTest_Thread = osThreadCreate(osThread(SelfTest_Thread), NULL);
    if (!tid_SelfTest_Thread)
        return(-1);

    return(0);
}

void SelfTest_Thread(void const *argument)
{
    static uint32_t current_block_index = 0;
    while (1)
    {
        uint32_t crc_actual = 0;

        crc_actual = crc32_fsl(0, (void *) g_crc_info[current_block_index].blockstart, ROM_BLOCK_LEN);
        if (crc_actual != *(uint32_t *) g_crc_info[current_block_index].crc_block_nominal)
        {
            raise_exception(SELFTEST_ROM_MISMATCH, current_block_index);
        }
				current_block_index++;
        if (current_block_index == ROM_BLOCK_NO)
        {
            current_block_index = 0;
        }

        osDelay(1000);
    }
}


