0

I have a code that spit out random number when the ISR register is ready:

#define TRNG_KEY  0x524E47
uint8_t lut[10] = {0xF6, 0x12, 0xAE, 0xEC, 0xD8, 0x7C, 0x7E, 0xE0, 0xFE, 0xFC};
uint32_t msk = 0x1FE;

void setup()
{
  Serial.begin(9600);
  PIOC->PIO_PER = msk;
  PIOC->PIO_OER = msk;
  PIOC->PIO_OWDR = ~msk;

  PMC->PMC_PCER1 = PMC_PCER1_PID41;
  TRNG->TRNG_CR = TRNG_CR_ENABLE | TRNG_CR_KEY(TRNG_KEY);
  TRNG->TRNG_IER = 1 << 0;
}

void loop()
{
  if (TRNG->TRNG_ISR == 1) {
  PIOC->PIO_ODSR = lut[REG_TRNG_ODATA % 10];
  }
  delay(500);
}

The code above works. However, when I tried to switch to internal interrupt:

#define TRNG_KEY  0x524E47
uint8_t lut[10] = {0xF6, 0x12, 0xAE, 0xEC, 0xD8, 0x7C, 0x7E, 0xE0, 0xFE, 0xFC};
uint32_t msk = 0x1FE;

void setup()
{
  Serial.begin(9600);
  PIOC->PIO_PER = msk;
  PIOC->PIO_OER = msk;
  PIOC->PIO_OWDR = ~msk;

  PMC->PMC_PCER1 = PMC_PCER1_PID41;
  TRNG->TRNG_CR = TRNG_CR_ENABLE | TRNG_CR_KEY(TRNG_KEY);
  TRNG->TRNG_IER = 1 << 0;

  NVIC_EnableIRQ(TRNG_IRQn);
}

void loop()
{

}

void TRNG_Handler(void) {
  PIOC->PIO_ODSR = lut[REG_TRNG_ODATA % 10];
}

The code only spit out one random number and then freezes, indicating TRNG_Handler(void) was only executed once. I cannot figure out why.

Thanks in Advance !

3
  • I presume delay will internally wait on some millisecond variable to be incremented, and that only happens in some timer ISR, that you may be blocking by delaying in the first place. You might want to setup a hardware timer in the needed interval or use a flag inside loop to toggle a boolean "it's okay to update" value every 500ms, that is then reset in the TRNG_Handler. – Maximilian Gerhardt Jan 31 at 15:40
  • Hm actually I may be partially wrong. The datasheet says This interrupt is set when a new random value is available and is cleared when the status register is read(TRNG_SR register). The SR is probably a typo and means ISR. Can you try and read the status register the same as in github.com/davecheney/trng/blob/master/arduino-due-trng/… ? – Maximilian Gerhardt Jan 31 at 15:49
  • That delay() was a typo, sorry. It's not in my actual code. – 7E10FC9A Jan 31 at 17:41
2

Two things:

  1. Never use delay() inside an ISR. On some systems it may work, but on most it will just block. It's bad practice to have your ISRs run for more time that absolutely needed anyway.
  2. You need to read the status register for the TRNG to clear the interrupt flag. You're doing that in your first code sample with if (TRNG->TRNG_ISR == 1) {.
2
  • Isn't if (TRNG->TRNG_ISR = 1) {. an assignment? TRNG->TRNG_ISR is not read - 1 is assigned to it. I think it is intended to be a comparisson. That's an error in the first example. But the condition was always true, and the generator is fast enough to gnerate a number every 500ms it seems ;-). – Peter Paul Kiefer Jan 31 at 20:23
  • @PeterPaulKiefer You might be right... The end result would probably be reading the register before writing the changed content back. – Majenko Jan 31 at 20:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.