Page 1 of 1

Timer frequency question

Posted: Fri Sep 13, 2019 1:59 am
by AndrewM
Hi,

I'm getting something wrong with timer settings and how long things actually take. Output is much to slow for a timer set on an 80MHz clock with a 2 divider.


I'm trying to use the SPI peripheral to send some serial data out, then set off a timer to set a pin low for ~150ns, set the pin high for ~150ns, and then set the pin low again. The code I am using:

Timer Setup

Code: Select all

    
    timer_config.divider = 2;
    timer_config.counter_dir = TIMER_COUNT_UP;
    timer_config.counter_en = TIMER_PAUSE;
    timer_config.alarm_en = TIMER_ALARM_DIS;
    timer_config.intr_type = TIMER_INTR_LEVEL;
    timer_config.auto_reload = 0;
    timer_init(TIMER_GROUP_0, TIMER_0, &timer_config);
    timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0x00000000ULL);
    timer_enable_intr(TIMER_GROUP_0, TIMER_0);
    timer_isr_register(TIMER_GROUP_0, TIMER_0, timer_group0_isr, NULL, ESP_INTR_FLAG_IRAM, &timer_isr_handle);
 
SPI send data (the rest of the spi_send struct is defined elsewhere)

Code: Select all

void io_spi_write(uint16_t data) {
    ESP_LOGI(TAG, "IO SPI Write: %X", data);
    gpio_set_level(RCLK, 0);
    //split into 8 bit chunks
    spi_send.tx_data[1] = (data & 0xff);
    spi_send.tx_data[0] = (data >> 8);
    //zero out the timer stage counter
    io_rclk_stage = 0;
    timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0x00000000ULL);
    timer_set_alarm_value(TIMER_GROUP_0, TIMER_0,5ULL);
    timer_set_alarm(TIMER_GROUP_0, TIMER_0, TIMER_ALARM_EN);
    spi_device_polling_transmit(device_handle, &spi_send);
    timer_start(TIMER_GROUP_0, TIMER_0);
}
Timer interrupt

Code: Select all

void IRAM_ATTR timer_group0_isr(void *arg) {
    if(io_rclk_stage == 0) {
        REG_WRITE(GPIO_OUT_W1TC_REG, (1 << RCLK));
        io_rclk_stage++;
        timer_group_set_alarm_value_in_isr(TIMER_GROUP_0, TIMER_0, 10ULL);
        timer_group_enable_alarm_in_isr(TIMER_GROUP_0, TIMER_0);
    } else if(io_rclk_stage == 1) {
        REG_WRITE(GPIO_OUT_W1TS_REG, (1 << RCLK));
        io_rclk_stage++;
        timer_group_set_alarm_value_in_isr(TIMER_GROUP_0, TIMER_0, 20ULL);
        timer_group_enable_alarm_in_isr(TIMER_GROUP_0, TIMER_0);
    } else {
        REG_WRITE(GPIO_OUT_W1TC_REG, (1 << RCLK)); //turn off again
        io_rclk_stage = 2;
        io_timer_pause_in_isr(TIMER_GROUP_0, TIMER_0);
    }
    timer_group_intr_clr_in_isr(TIMER_GROUP_0, TIMER_0);
}

I wasn't sure if I needed to create an IRAM_ATTR wrapper for timer_pause like I found in the timer library for other timer setting functions, so I did anyways:

Code: Select all

esp_err_t IRAM_ATTR io_timer_pause_in_isr (timer_group_t group_num, timer_idx_t timer_num) {
    return timer_pause(group_num, timer_num);   
}



Here's the problem: The timer should be running at 40MHz. The "on" pulse should be 10 counts, or ~250ns. When I measure this with a logic analyzer, I measure a pulse 775ns wide.

Also, why is there such a long gap between the end of the SPI transmission and the beginning of the pulse (26.65us) when I only have the timer running for a 10 count delay?

See: https://imgur.com/Gx6Hbk9

Re: Timer frequency question

Posted: Sat Sep 14, 2019 7:52 am
by ESP_Sprite
I think you're running into the fact that interrupts just aren't that quick on the Xtensa.

Re: Timer frequency question

Posted: Sat Sep 14, 2019 4:38 pm
by AndrewM
ESP_Sprite wrote:
Sat Sep 14, 2019 7:52 am
I think you're running into the fact that interrupts just aren't that quick on the Xtensa.
Thanks, I guess that's the answer then.