Synchronous UART. SCK clock.

Hello all! I'm new in the forum and new with Renesas MCUs.

I'm working with an S124 and peripheral SCI9 in SYNCHRONOUS UART/SIMPLE SPI mode:

 - P109 --> MOSI

 - P110 --> MISO

 - P111 --> SCK

It is working well, but I need to synchronize one more pin. I need to raise or low a digital pin after a certain number of SCK pulses. My question is: Is there any way of counting SCK pulses? Or maybe could I use any interrupt?

Thanks in advance!

  • Hi AlfonsoV,

    AGT can count external events, please refer to S124 User's Manual (section 20.3.5). You may need to configure AGT using registers, because the SSP driver does not currently support this.

    Regards,
    adboc

  • In reply to adboc:

    Thanks for your response adboc.

    So, the only way of doing it is using external events?
    Are there no internal counters to do that?

    Regards
  • In reply to AlfonsoV:

    Hi AlfonsoV,

    Based on S124 user's manual, I don't think that SCI exposes any interface to read SCK state internally.

    Regards,
    adboc
  • In reply to adboc:

    Is there any example of this use of AGT (or something similar) in the RENESAS web site or somewhere else?

    Thanks

  • In reply to adboc:

    One more question.
    Why does not AGT SSP driver support it? Do you know if will be possible to do it in the future?

  • In reply to AlfonsoV:

    Hi AlfonsoV,

    Unfortunately I don't know when it will be added. But SSP is actively maintained and developed so for sure there is a chance one of the future release will include updated AGT driver.

    Regards,
    adboc
  • In reply to adboc:

    Hello.

    I share what I finally did:

    1) Event Counter with Timer3 and AGT1 (Pin 204):

        /* Open AGT */
        g_timer3.p_api->open(g_timer3.p_ctrl, g_timer3.p_cfg);
        tx_thread_sleep(15);
        /* AGT initialization */
        g_timer3.p_api->start(g_timer3.p_ctrl);
        /* AGT info */
        g_timer3.p_api->infoGet(g_timer3.p_ctrl, &infoAGT);
        /* AGT version */
        g_timer3.p_api->versionGet(&versionAGT);
        printf("AGT API version is: %02d%02d\n",(int16_t)versionAGT.api_version_major, (int16_t)versionAGT.api_version_minor);
        printf("AGT Code version is: %02d%02d\n",(int16_t)versionAGT.code_version_major, (int16_t)versionAGT.code_version_minor);
        printf("Count direction : %lu  // (0 = Down; 1 = Up) \n", (uint32_t)infoAGT.count_direction);    // Dirección de conteo (Arriba o abajo)
        printf("Clock_frequency: %lu\n", (uint32_t)infoAGT.clock_frequency);   
        printf("Period_counts: %lu\n", (uint32_t)infoAGT.period_counts);
        printf("Status: %lu // (0 = counting; 1 = Stopped) \n", (uint32_t)infoAGT.status);                     
        printf("ELC event: %lu\n", (uint32_t)infoAGT.elc_event);              

        R_AGT1->AGTCR_b.TSTOP= 1;                       // STOP counting --> AGTR = 0xffff
        R_AGT1->AGTCR_b.TUNDF = 0;                      // No underflow
        R_AGT1->AGTCR_b.TEDGF = 0;                      // No active edge received
        R_AGT1->AGTCR_b.TCMBF = 0;                      // Flab compare B. No match
        R_AGT1->AGTCR_b.TCMAF = 0;                      // Flab compare A. No match
        R_AGT1->AGTMR1_b.TMOD = 2;                     // Event count mode
        R_AGT1->AGTMR1_b.TCK = 0;                        // Count source --> PCLKB
        R_AGT1->AGTIOC_b.TEDGSEL = 0;                 // Conteo en flanco de subida

        printf("AGTCR --> START: %d // (0 = STOP; 1 = START) \n", R_AGT1->AGTCR_b.TSTART);
        printf("AGTCR --> STATUS FLAG: %d // (0 = STOP; 1 = PROGRESS) \n", R_AGT1->AGTCR_b.TCSTF);
        printf("AGTCR --> FORCED STOP: %d // (1 = STOP Forzado) \n", R_AGT1->AGTCR_b.TSTOP);
        printf("AGTCR --> ACTIVE EDGE FLAG: %d // (0 = No active; 1 = Active) \n", R_AGT1->AGTCR_b.TEDGF);
        printf("AGTCR --> UNDERFLOW FLAG: %d // (0 = No underflow; 1 = Underflow) \n", R_AGT1->AGTCR_b.TUNDF);
        printf("AGTCR --> COMPARE A FLAG: %d // (0 = No match; 1 = Match) \n", R_AGT1->AGTCR_b.TCMAF);
        printf("AGTCR --> COMPARE B FLAG: %d // (0 = No match; 1 = Match) \n", R_AGT1->AGTCR_b.TCMBF);

        printf("AGTMR1 --> EDGE POLARITY: %d // (0 = Single; 1 = Both) \n", R_AGT1->AGTMR1_b.TEDGPL);
        printf("AGTMR1 --> COUNT SOURCE: %d // (0 = PCLKB; 1 = PCLKB/8; 3 = PCLKB/2; 5 = UNDERFLOW SIGNAL; 4 y 6 = AGTCK)\n", R_AGT1->AGTMR1_b.TCK);*/

     

        /* AGT Counter Register (AGT) --> 16 bit register [0x0000 a 0xFFFF (65535)] */
        /* READ --> From counter //// WRITE --> To reload register **/
        printf("AGT --> Register: %d\n", R_AGT1->AGT);

        g_timer3.p_api->counterGet(g_timer3.p_ctrl, &value);
        printf("AGT --> Counter: %lu\n", (uint32_t)value);

     

    2) Event generator (SCK clock from SPI driver):

     

     

     

    3) Final program:

    bool write = true;

    uint16_t interval = 16;      // 16 counts before raising PIN_LE2
    uint16_t current_counter, target_counter;

    while (1)
    {
            g_timer3.p_api->counterGet(g_timer3.p_ctrl, &value);
            current_counter= (uint16_t)value;

            /* This condition is only true when timer4 expires */
            if(write == true)
            {
                R_AGT1->AGTCR_b.TSTART = 1; // Counter starts to decrease

                g_uart0.p_api->write(g_uart0.p_ctrl, data, 2);  // SCI send 2 bytes after counter starts

                write = false;
            }

            /* This condition is true when AGT has counted "interval" events since first bit of SCI message was sent */.

            /* When this occurs, PIN_LE2 is raised*/
            if(target_counter == current_counter)
           {
                g_ioport.p_api->pinWrite(PIN_LE2, IOPORT_LEVEL_HIGH);

                R_AGT1->AGTCR_b.TSTOP = 1;  // Counter stops. By default, its new value es 0xffff

                g_timer3.p_api->counterGet(g_timer3.p_ctrl, &value);
                current_counter= (uint16_t)value;
                target_counter= (uint16_t)(current_counter- intervalo);   // New target value for the next iteration
            }
        }
    }

     

    void user_uart0_callback(uart_callback_args_t * p_args)
    {
        switch(p_args->event)
        {
            case UART_EVENT_TX_COMPLETE:
                g_ioport.p_api->pinWrite (PIN_LE2, IOPORT_LEVEL_LOW);  // When the SCI message has been completely sent, PIN_LE2 falls
                break;

        }

    }

    /* This timer lasts 1 second. Thus, it is only possible to send data through SCI 60 times per minute */

    void Callback_Timer4_SCI(timer_callback_args_t *p_args)
    {
        escribir = true;
    }

     

    Hope it helps people.

    Please, correct any mistake.