ARDUINO DUE - Multi timer with internal and external clocks

Hello,

In first, i want to apology because my English is not good, so please don't tease me...
My project is base on the use of internal and external clocks and command 3 digital output pins to command a sequence in a multiplexer 8 to 1. I create PWM signal with a frequency max 2,5 Mhz and min 217 KHz. With another interruption timer, i change the output on the multiplexer every 10 KHz.


In the beginning, i choose the DUE card because of the 9 timers. But after some tests and research, i think this card it's not really good for this job. And the first reason is this table :

Instance TCX Channel External Clock Input pin Internal clock output pin
T0 TC0 0 XC0 pin 22 TCLK0 Pin 2
T1 TC0 1 XC0 Ana In5 TCLK1 Ana In7
T2 TC0 2 XC0 pin 31 TCLK2 /
T3 TC1 0 XC1 Ana In3 TCLK3 /
T4 TC1 1 XC1 Ana In2 TCLK4 /
T5 TC1 2 XC1 DAC1 TCLK5 /
T6 TC2 0 XC2 / TCLK6 pin 5
T7 TC2 1 XC2 LED "RX" TCLK7 Pin 3
T8 TC2 2 XC2 pin 30 TCLK8 Pin 11

Like i understand this, if you want to use an external clock to create a PWM signal, you can use only the timer0 and timer8. All the other have not hardware connection for a external clock (timer6 and timer7) or a hardware output (timer1, timer2, timer3, timer4 and timer5). So, in first you have 9 timers and in the end you can use only 2 ! (or 4 with internal clock)

In the first place, when i want to comprehend the DUE board, i create 4 PWM signals with internal clock only (timer0, timer6, timer7 and timer8) because they have hardware connection output.

void setup()
{
  //Declaration des sorties PWM
  pinMode (2, OUTPUT);
  pinMode (3, OUTPUT);
  pinMode (5, OUTPUT);
  pinMode (11, OUTPUT);
 

 
  /*Initialisation périfiques du timers 0, 6, 7, 8 */
  pmc_set_writeprotect(false);  //Turn off write protection on Power Management Controller
  pmc_enable_periph_clk(TC0_IRQn);  // Enable the  peripheral clock by IRQ for Timer 0 channel 0 
  pmc_enable_periph_clk(TC6_IRQn);  // Enable the  peripheral clock by IRQ for Timer 2 channel 0 
  pmc_enable_periph_clk(TC7_IRQn);  // Enable the  peripheral clock by IRQ for Timer 2 channel 1 
  pmc_enable_periph_clk(TC8_IRQn);  // Enable the  peripheral clock by IRQ for Timer 2 channel 2

  
  /* Configuration du timer TC2 channel 0 => timer 6 */
  TcChannel * t6 = &(TC2->TC_CHANNEL)[0] ;    // creation du pointeur sur le registre TC0 channel 0
                                             
  t6->TC_CCR = TC_CCR_CLKDIS ;  // désactivation des horloges le temps des reglages
  t6->TC_IDR = 0xFFFFFFFF ;     // desactivation des interruptions
  t6->TC_SR ;                   // lecture status pour reinitialisation du timer
  t6->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 |   // utilisation TCLK1 (division par 2, F = 42MHz)
              TC_CMR_WAVE |         // mode courbe
              TC_CMR_WAVSEL_UP_RC | // compteur PWM utilisant le registre RC 
              TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR |
              TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR ;
 
  t6->TC_RC = 42;     // Definition de la fréquence : 42 MHz / TC_RC
  t6->TC_RA = 21;      // Definition du rapport cyclique, avec RA = 1/2 RC
  
  t6->TC_CMR = (t6->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET ; // set et reset des flags pour la comparaison des registres RA et RC                     
  t6->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ;  // reactivation de l horloge.
  /* Configuration des I/O : */
  int ulPin6 = 5; // Timer6 -> PWM Pin 5
  PIO_Configure(g_APinDescription[ulPin6].pPort,
  g_APinDescription[ulPin6].ulPinType,
  g_APinDescription[ulPin6].ulPin,
  g_APinDescription[ulPin6].ulPinConfiguration);

  /* Configuration du timer TC0 channel 0 => timer 0 */
  TcChannel * t0 = &(TC0->TC_CHANNEL)[0] ;    // creation du pointeur sur le registre TC0 channel 0
                                             
  t0->TC_CCR = TC_CCR_CLKDIS ;  // désactivation des horloges le temps des reglages
  t0->TC_IDR = 0xFFFFFFFF ;     // desactivation des interruptions
  t0->TC_SR ;                   // lecture status pour reinitialisation du timer
  t0->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 |   // utilisation TCLK1 (division par 2, F = 42MHz)
              TC_CMR_WAVE |         // mode courbe
              TC_CMR_WAVSEL_UP_RC | // compteur PWM utilisant le registre RC 
              TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR |
              TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR ;
              
  t0->TC_RC = 17;     // Definition de la fréquence : 42 MHz / TC_RC
  t0->TC_RA = 8;      // Definition du rapport cyclique, avec RA = 1/2 RC
  
  t0->TC_CMR = (t0->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET ; // set et reset des flags pour la comparaison des registres RA et RC
                        
  t0->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ;  // reactivation de l horloge.

  int ulPin0 = 2; // Timer0 -> PWM Pin 2
  PIO_Configure(g_APinDescription[ulPin0].pPort,
  g_APinDescription[ulPin0].ulPinType,
  g_APinDescription[ulPin0].ulPin,
  g_APinDescription[ulPin0].ulPinConfiguration);


 
}

void loop()
{
  

}

With this code, i have my 4 signals with the correct frequency i set.

After, i want to use the external clock to generate a PWM signal. For this task, i use a 5 MHz clock connected to the pin22 (timer0) on DUE board .

void setup()
{
  //Declaration des sorties PWM
  pinMode (2, OUTPUT);  // timer0 - OUT
  pinMode (22, INPUT);  // timer0 - IN 
  
  
 
  /*Initialisation périfiques du timers 0, 6, 7, 8 */
  pmc_set_writeprotect(false);  //Turn off write protection on Power Management Controller
  pmc_enable_periph_clk(TC0_IRQn);  // Enable the  peripheral clock by IRQ for Timer 0 channel 0 


  /* Configuration du timer TC0 channel 0 => timer 0 */
  TcChannel * t0 = &(TC0->TC_CHANNEL)[0] ;    // creation du pointeur sur le registre TC0 channel 0
                                             
  t0->TC_CCR = TC_CCR_CLKDIS ;  // désactivation des horloges le temps des reglages
  t0->TC_IDR = 0xFFFFFFFF ;     // desactivation des interruptions
  t0->TC_SR ;                   // lecture status pour reinitialisation du timer
  t0->TC_CMR = TC_CMR_TCCLKS_XC0 |   // utilisation horloge externe (F = 5 MHz) - pin 22
              TC_CMR_WAVE |         // mode courbe
              TC_CMR_WAVSEL_UP_RC;  // compteur PWM utilisant le registre RC 
                 
  t0->TC_RC = 5;     // Definition de la fréquence : 5 MHz / TC_RC
  t0->TC_RA = 2;      // Definition du rapport cyclique, avec RA = 1/2 RC
  
  t0->TC_CMR = (t0->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_SET | TC_CMR_ACPC_CLEAR ; // set et reset des flags pour la comparaison des registres RA et RC
                        
  t0->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ;  // reactivation de l horloge.

  int ulPin0 = 2; // Timer0 -> PWM Pin 2
  PIO_Configure(g_APinDescription[ulPin0].pPort,
  g_APinDescription[ulPin0].ulPinType,
  g_APinDescription[ulPin0].ulPin,
  g_APinDescription[ulPin0].ulPinConfiguration);
}

void loop()
{
}

This code work fine.
But my problem is when i change / adapt this code for the timer8.

void setup()
{
  //Declaration des sorties PWM
  pinMode (11, OUTPUT);  // timer0 - OUT
  pinMode (30, INPUT);  // timer0 - IN 
  
  
 
  /*Initialisation périfiques du timers 0, 6, 7, 8 */
  pmc_set_writeprotect(false);  //Turn off write protection on Power Management Controller
  pmc_enable_periph_clk(TC8_IRQn);  // Enable the  peripheral clock by IRQ for Timer 0 channel 0 


  /* Configuration du timer TC2 channel 2 => timer 8 */
  TcChannel * t8 = &(TC2->TC_CHANNEL)[2] ;    // creation du pointeur sur le registre TC2 channel 2
                                             
  t8->TC_CCR = TC_CCR_CLKDIS ;  // désactivation des horloges le temps des reglages
  t8->TC_IDR = 0xFFFFFFFF ;     // desactivation des interruptions
  t8->TC_SR ;                   // lecture status pour reinitialisation du timer
  t8->TC_CMR = TC_CMR_TCCLKS_XC2 |   // utilisation horloge externe (F = 5 MHz) - pin 30
              TC_CMR_WAVE |         // mode courbe
              TC_CMR_WAVSEL_UP_RC;  // compteur PWM utilisant le registre RC 
                 
  t8->TC_RC = 5;     // Definition de la fréquence : 5 MHz / TC_RC
  t8->TC_RA = 2;      // Definition du rapport cyclique, avec RA = 1/2 RC
  
  t8->TC_CMR = (t8->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_SET | TC_CMR_ACPC_CLEAR ; // set et reset des flags pour la comparaison des registres RA et RC
                        
  t8->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ;  // reactivation de l horloge.

  int ulPin0 = 11; // Timer8 -> PWM Pin 11
  PIO_Configure(g_APinDescription[ulPin0].pPort,
  g_APinDescription[ulPin0].ulPinType,
  g_APinDescription[ulPin0].ulPin,
  g_APinDescription[ulPin0].ulPinConfiguration);
}

void loop()
{
}

I put the external clock in pin 30, but i have nothing in the output pin 11.
Can i have some help please ? where is my problem in the code or in the understanding of the DUE board ?

To avoid confusion, see "Timer Pins routed to the Arduino Due Board" here :

ard_newbie:
To avoid confusion, see "Timer Pins routed to the Arduino Due Board" here :

Timer Pins routed to the Arduino Due Board · Issue #11 · ivanseidel/DueTimer · GitHub

I have already check this. My table is a quick summary of the content of the link.

Did you activate PWM controller : PMC->PMC_PCER1 |= PMC_PCER1_PID36; ?

I don't know. I will check that.

I add the "TC_CMR_BURST_XC2" instruction in my code for the CMR register and it work.

Thank for this point.

Now, i will code a timer interruption for the multiplexer command with a frequency of 10 KHz.

With an adaptation, i make a timer with an interruption for the multiplexer command :

// Initialisation des variables
volatile int sequence = 0;
//Creation du tableau contenant l'ordre des fréquences à afficher
int table[16][3] = {{0,1,0},//F4 - 0
                    {1,0,1},//F6 
                    {0,0,0},//F1 
                    {0,0,1},//F2
                    {0,1,0},//F4
                    {1,0,1},//F5
                    {1,0,0},//F6
                    {0,1,1},//F3
                    {1,0,0},//F6
                    {1,1,1},//F7
                    {0,0,0},//F1
                    {0,1,1},//F3
                    {0,1,0},//F4
                    {0,0,1},//F1
                    {1,0,0},//F5
                    {0,0,1}};//F2 - 15

//TC1 ch 0
void TC3_Handler()
{
        TC_GetStatus(TC1, 0);
        digitalWrite(8, table[sequence][0]);
        digitalWrite(9, table[sequence][1]);
        digitalWrite(10, table[sequence][2]);
        
     //   Serial.print(sequence);
     //   Serial.print(" ; ");
     //   Serial.println(table[sequence][2]);
        
        sequence++;
}

void startTimer(Tc *tc, uint32_t channel, IRQn_Type irq) {
        pmc_set_writeprotect(false);
        pmc_enable_periph_clk((uint32_t)irq);

        /* Configuration du timer TC0 channel 2 => timer 2 */
        TcChannel * t3 = &(TC1->TC_CHANNEL)[0] ;    // creation du pointeur sur le registre TC1 channel 0
                                             
        t3->TC_CCR = TC_CCR_CLKDIS ;  // désactivation des horloges le temps des reglages
        t3->TC_SR ;                   // lecture status pour reinitialisation du timer
        t3->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 |   // utilisation TCLK1 (division par 2, F = 42MHz)
              TC_CMR_WAVE |         // mode courbe
              TC_CMR_WAVSEL_UP_RC; // compteur PWM utilisant le registre RC 
              
        t3->TC_RC = 4200;     // Definition de la fréquence : 5 MHz / TC_RC
        t3->TC_RA = 2100;      // Definition du rapport cyclique, avec RA = 1/2 RC
        TC_Start(tc, channel);
        tc->TC_CHANNEL[channel].TC_IER=TC_IER_CPCS;
        tc->TC_CHANNEL[channel].TC_IDR=~TC_IER_CPCS;
        NVIC_EnableIRQ(irq);
}

void setup()
{
        pinMode(8,OUTPUT);
        pinMode(9,OUTPUT);
        pinMode(10,OUTPUT);
        startTimer(TC1, 0, TC3_IRQn); //TC1 channel 0, the IRQ for that channel and the desired frequency
        Serial.begin(250000);
        delay(500);
}

void loop()
{
        if (sequence > 15)
        {
          sequence = 0;
        }
}