This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSPM0G1507: True random generator (TRNG) self test fail (false negative result)

Part Number: MSPM0G1507

Tool/software:

The following initialization code doesn't work, but if increase TRNG_POST_TEST_CMD_DELAY to 520, it will work (return true).

However, if use following code piece, and later use CCS to attach debugger upon it hangs to while(1) and check the register TRNG->TEST_RESULTS, the result is 0xFF (pass).

Can you provide a way to check if digital test has done?

MCLK=32MHz

//See mspm0g1507 datasheet 7.23.2
#define TRNG_STARTUP_DELAY_US           520
//Weird, why do we need this
#define TRNG_POST_TEST_CMD_DELAY        400
static bool rng_init(void) {
    DL_TRNG_reset(TRNG);
    DL_TRNG_enablePower(TRNG);
    hal_delay_us(TRNG_STARTUP_DELAY_US);
    DL_TRNG_setClockDivider(TRNG, DL_TRNG_CLOCK_DIVIDE_2);  //Make sure in 9.6MHz - 20MHz range
    DL_TRNG_sendCommand(TRNG, DL_TRNG_CMD_NORM_FUNC);
    while (!DL_TRNG_isCommandDone(TRNG));
    DL_TRNG_sendCommand(TRNG, DL_TRNG_CMD_TEST_DIG);
    while (!DL_TRNG_isCommandDone(TRNG));
    hal_delay_us(TRNG_POST_TEST_CMD_DELAY);
    if (DL_TRNG_DIGITAL_HEALTH_TEST_SUCCESS != DL_TRNG_getDigitalHealthTestResults(TRNG)) {
        ////////code fall to here.
        // set_led_operation(LED_AMBER, LED_OP_ON);
        while(1);
        return false;
    }
    DL_TRNG_sendCommand(TRNG, DL_TRNG_CMD_TEST_ANA);
    while (!DL_TRNG_isCommandDone(TRNG));
    hal_delay_us(TRNG_POST_TEST_CMD_DELAY);
    if (DL_TRNG_ANALOG_HEALTH_TEST_SUCCESS != DL_TRNG_getAnalogHealthTestResults(TRNG)) {
        // set_led_operation(LED_GREEN, LED_OP_ON);
        while(1);
        return false;
    }
    DL_TRNG_sendCommand(TRNG, DL_TRNG_CMD_NORM_FUNC);
    while (!DL_TRNG_isCommandDone(TRNG));

    DL_TRNG_clearInterruptStatus(TRNG, DL_TRNG_INTERRUPT_CMD_DONE_EVENT);
    DL_TRNG_setDecimationRate(TRNG, DL_TRNG_DECIMATION_RATE_8);
    DL_TRNG_clearInterruptStatus(TRNG, (DL_TRNG_INTERRUPT_CAPTURE_RDY_EVENT));
    // DL_TRNG_enableInterrupt(TRNG, (DL_TRNG_INTERRUPT_CAPTURE_RDY_EVENT));

    //Discard the 1st output
    while (!DL_TRNG_isCaptureReady(TRNG));
    DL_TRNG_getCapture(TRNG);
    return true;
}

  • Hi, 

    Please refer to TRM 24.2.4.1 Digital Block Startup Self-Test:

    The test sequence includes eight tests.
    Each test requires 1024 TRNG clock cycles to complete, 
    as 1024 samples are input to the digital block for each test.

    It need more than 400 us I think.

    Regards,

    Helic

  • Do you mean that the cmd_done flag doesn't indicate test being finished for digital test?

    What about analog test? I remember that in reference manual, it said that the cmd_done flag willl be set.

  • Hi, 

    I think device need more that 400us to finished digital test.

    Total 1024 * 8 clock cycles is needed, one cycles is 32MHz/2 = 16MHz.

    1/16000000 * 1024 * 8 is large than 400us.

    What about analog test?

    You can have a detailed look at 24.2.4.2 Analog Block Startup Self-Test.

    Have a calculation.

    Regards,

    Helic

  • I was asking:

    Is the cmd_done flag indicate the self-test finished?

    The document slau846a (RM) 24.2.5.2 section, step 5a & 5b don't mention the delay at all. Is this documentation issue? 6a and 6b as well.

    This is my updated source code, was recommended from Luke Ledbetter in email: clear CMD_DONE flag before execute next cmd, then the flag poll is real.

    The problem is solved now, no longer need delay.

    Thank you all.

    //See mspm0g1507 datasheet 7.23.2
    #define TRNG_STARTUP_DELAY_US           520
    #define TRNG_POST_TEST_CMD_DELAY_US     1000
    
    static bool rng_init(void) {
        DL_TRNG_reset(TRNG);
        DL_TRNG_enablePower(TRNG);
        hal_delay_us(TRNG_STARTUP_DELAY_US);
        DL_TRNG_setClockDivider(TRNG, DL_TRNG_CLOCK_DIVIDE_2);  //Make sure in 9.6MHz - 20MHz range
        DL_TRNG_clearInterruptStatus(TRNG, DL_TRNG_INTERRUPT_CMD_DONE_EVENT);
        DL_TRNG_sendCommand(TRNG, DL_TRNG_CMD_NORM_FUNC);
        while (!DL_TRNG_isCommandDone(TRNG));
        DL_TRNG_clearInterruptStatus(TRNG, DL_TRNG_INTERRUPT_CMD_DONE_EVENT);
        DL_TRNG_sendCommand(TRNG, DL_TRNG_CMD_TEST_DIG);
        while (!DL_TRNG_isCommandDone(TRNG));
        DL_TRNG_clearInterruptStatus(TRNG, DL_TRNG_INTERRUPT_CMD_DONE_EVENT);
        hal_delay_us(TRNG_POST_TEST_CMD_DELAY_US);
        if (DL_TRNG_DIGITAL_HEALTH_TEST_SUCCESS != DL_TRNG_getDigitalHealthTestResults(TRNG)) {
            return false;
        }
        DL_TRNG_sendCommand(TRNG, DL_TRNG_CMD_TEST_ANA);
        while (!DL_TRNG_isCommandDone(TRNG));
        DL_TRNG_clearInterruptStatus(TRNG, DL_TRNG_INTERRUPT_CMD_DONE_EVENT);
        hal_delay_us(TRNG_POST_TEST_CMD_DELAY_US);
        if (DL_TRNG_ANALOG_HEALTH_TEST_SUCCESS != DL_TRNG_getAnalogHealthTestResults(TRNG)) {
            return false;
        }
        DL_TRNG_sendCommand(TRNG, DL_TRNG_CMD_NORM_FUNC);
        while (!DL_TRNG_isCommandDone(TRNG));
        DL_TRNG_clearInterruptStatus(TRNG, DL_TRNG_INTERRUPT_CMD_DONE_EVENT);
        DL_TRNG_setDecimationRate(TRNG, DL_TRNG_DECIMATION_RATE_8);
        // DL_TRNG_enableInterrupt(TRNG, (DL_TRNG_INTERRUPT_CAPTURE_RDY_EVENT));
    
        //Discard the 1st output
        while (!DL_TRNG_isCaptureReady(TRNG));
        DL_TRNG_clearInterruptStatus(TRNG, (DL_TRNG_INTERRUPT_CAPTURE_RDY_EVENT));
        DL_TRNG_getCapture(TRNG);
        return true;
    }