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);
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);
}
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