-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[TW#24153] HW timer stops 2ms every 100ms #240
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Is there anything else I can provide to make this get more attention? :) |
The problem is that you use the |
The vTaskDelay doesn't pause the actual generating of the note. Isn't volatile only needed on variables handled both inside and outside an ISR? Thanks! |
Just an update, still the same with ESP8266_RTOS_SDK revision 7005cee, Updated source for the new SDK: #include <stddef.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "esp_attr.h"
#include "nvs_flash.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "user_config.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "driver/hw_timer.h"
#define NOTE_C6 1047
#define NOTE_CS6 1109
#define NOTE_D6 1175
#define NOTE_DS6 1245
#define NOTE_E6 1319
#define NOTE_F6 1397
#define NOTE_FS6 1480
#define NOTE_G6 1568
#define NOTE_GS6 1661
#define NOTE_A6 1760
#define NOTE_AS6 1865
#define NOTE_B6 1976
#define NOTE_C7 2093
#define NOTE_CS7 2217
#define NOTE_D7 2349
#define NOTE_DS7 2489
#define NOTE_E7 2637
#define NOTE_F7 2794
#define NOTE_FS7 2960
#define NOTE_G7 3136
#define NOTE_GS7 3322
#define NOTE_A7 3520
#define NOTE_AS7 3729
#define NOTE_B7 3951
#define QUARTER 4.0
#define THIRD 3.0
#define SPEAKER_PIN 13
//Mario main theme melody
int marioMelody[] = {
NOTE_E7, NOTE_E7, 0, NOTE_E7,
0, NOTE_C7, NOTE_E7, 0,
NOTE_G7, 0, 0, 0,
NOTE_G6, 0, 0, 0,
NOTE_C7, 0, 0, NOTE_G6,
0, 0, NOTE_E6, 0,
0, NOTE_A6, 0, NOTE_B6,
0, NOTE_AS6, NOTE_A6, 0,
NOTE_G6, NOTE_E7, NOTE_G7,
NOTE_A7, 0, NOTE_F7, NOTE_G7,
0, NOTE_E7, 0, NOTE_C7,
NOTE_D7, NOTE_B6, 0, 0,
NOTE_C7, 0, 0, NOTE_G6,
0, 0, NOTE_E6, 0,
0, NOTE_A6, 0, NOTE_B6,
0, NOTE_AS6, NOTE_A6, 0,
NOTE_G6, NOTE_E7, NOTE_G7,
NOTE_A7, 0, NOTE_F7, NOTE_G7,
0, NOTE_E7, 0, NOTE_C7,
NOTE_D7, NOTE_B6, 0, 0
};
//Mario main them tempo
int marioNoteDurations[] = {
QUARTER, QUARTER, QUARTER, QUARTER,
QUARTER, QUARTER, QUARTER, QUARTER,
QUARTER, QUARTER, QUARTER, QUARTER,
QUARTER, QUARTER, QUARTER, QUARTER,
QUARTER, QUARTER, QUARTER, QUARTER,
QUARTER, QUARTER, QUARTER, QUARTER,
QUARTER, QUARTER, QUARTER, QUARTER,
QUARTER, QUARTER, QUARTER, QUARTER,
THIRD, THIRD, THIRD,
QUARTER, QUARTER, QUARTER, QUARTER,
QUARTER, QUARTER, QUARTER, QUARTER,
QUARTER, QUARTER, QUARTER, QUARTER,
QUARTER, QUARTER, QUARTER, QUARTER,
QUARTER, QUARTER, QUARTER, QUARTER,
QUARTER, QUARTER, QUARTER, QUARTER,
QUARTER, QUARTER, QUARTER, QUARTER,
THIRD, THIRD, THIRD,
QUARTER, QUARTER, QUARTER, QUARTER,
QUARTER, QUARTER, QUARTER, QUARTER,
QUARTER, QUARTER, QUARTER, QUARTER,
};
void gpio_config(GPIO_ConfigTypeDef* pGPIOConfig);
static xTaskHandle tune_task_handle;
static bool state = false;
IRAM_ATTR void toneISR(void) {
state = !state;
GPIO_OUTPUT_SET(SPEAKER_PIN, state);
}
void playTune(const int noteMs, const int size, const int melody[], const int noteDurations[]) {
hw_timer_init();
hw_timer_set_func(toneISR);
for (int thisNote = 0; thisNote < size; thisNote++) {
int noteDurationMs = (int)(noteMs / noteDurations[thisNote]);
if (melody[thisNote] != 0) {
hw_timer_arm(((1000 * 1000) / melody[thisNote])/2, true);
}
vTaskDelay( noteDurationMs / portTICK_PERIOD_MS );
hw_timer_disarm();
GPIO_OUTPUT_SET(SPEAKER_PIN, false);
int pauseBetweenNotesMs = noteDurationMs * 0.30;
vTaskDelay( pauseBetweenNotesMs / portTICK_PERIOD_MS );
}
}
static void tune_task_thread(void* pvParameters) {
GPIO_ConfigTypeDef io_out_conf;
io_out_conf.GPIO_IntrType = GPIO_PIN_INTR_DISABLE;
io_out_conf.GPIO_Mode = GPIO_Mode_Output;
io_out_conf.GPIO_Pin = BIT(SPEAKER_PIN);
io_out_conf.GPIO_Pullup = GPIO_PullUp_DIS;
gpio_config(&io_out_conf);
GPIO_OUTPUT_SET(SPEAKER_PIN, false);
playTune(600, sizeof(marioMelody) / sizeof(int), marioMelody, marioNoteDurations);
vTaskDelete(NULL);
return;
}
static esp_err_t event_handler(void *ctx, system_event_t *event) {
switch(event->event_id) {
case SYSTEM_EVENT_STA_START:
esp_wifi_connect();
break;
case SYSTEM_EVENT_STA_GOT_IP:
printf("sta got ip ,create task and free heap size is %d\n", esp_get_free_heap_size());
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
/* This is a workaround as ESP32 WiFi libs don't currently
auto-reassociate. */
esp_wifi_connect();
break;
default:
break;
}
return ESP_OK;
}
static void initialise_wifi(void) {
tcpip_adapter_init();
ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
wifi_config_t wifi_config = {
.sta = {
.ssid = SSID,
.password = PASSWORD,
},
};
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
ESP_ERROR_CHECK( esp_wifi_start() );
}
void app_main() {
UART_SetBaudrate(UART0, BIT_RATE_74880);
ESP_ERROR_CHECK( nvs_flash_init() );
initialise_wifi();
printf("SDK version:%s\n", esp_get_idf_version());
xTaskCreate(tune_task_thread, "tune_task_thread", 2048, NULL, 7, &tune_task_handle);
} |
And since the new version of the SDK no longer crashes if I don't initialize WiFi, I could now also test with disabling WiFi (just comment out 'initialise_wifi();'). |
Just for comparison, esp8266 Arduino based SDK (using tone/noTone and delay, where tone is written also using hw timer, and delay allows system/wifi operation during a tone) there are no interruptions, even when WiFi is started/starting. |
I think your problem is related to the WiFi re-connecting issue, not to the interrupt. As you meant before that disabling the WiFi didnt produce 2ms delay anymore it is a WiFi issue per si. Can you try to enable WiFi in AP strict mode without APSTA? |
Well, since hw_timer_ headers/functions seem to be disappeared, it's hard to test this now :) All I want to do is make simple gpio tones, even with wifi functionality running. |
I tried to use the pwm methods as an alternative (pwm_init etc.), even though the pwm API is not very friendly for tones (one period for all pwm channels/pins). But it seems when pwm is enabled, vTaskDelay stops working correctly (wrong delay time).. |
hw_timer uses frc1 timer, and in RTOS, it can only be set as a shield interruption source. So when using WiFi, it is easy to be interrupted. |
So, what would you recommend on RTOS esp8266 as something that would provide a stable enough 'pwm' like signal, to play tones? (while still being able to do wifi) :) Or is it impossible to do that in RTOS? I'm curious what a 'shield' interruption source is, I don't recognize the term :) |
This also affects the GPIO ISR. I'm trying to receive an RF signal at base band and the GPIO interrupt works well until this 2ms gap happens. So I'm pretty sure this is an interrupt holding the CPU and blocking all other interrupts. Is there a way to mask this interrupt other than turning wifi off? Or can this 2ms go down to a few micro seconds? |
Environment
git rev-parse --short HEAD
to get the commit id.):305a338
Problem Description
I'm trying to play tunes using the hw timer (hw_timer.h)
This work, but it seems every 100ms the interrupt/timer stops for about 2ms.
I think some other task is interfering, but not sure how to find out which task.
This happens even in a minimal example.
Expected Behavior
hw timer keeps working continuously.
Actual Behavior
Every 100ms there's a 2ms of no interrupts.
Steps to repropduce
Code to reproduce this issue
NOTE: Wifi is enabled, cause removing all wifi code seems to cause a crash shortly after booting.
Debug Logs
Sigrok capture showing the 'gaps', each has roughly 102 ms inbetween:

Note: Click for full size, it's the tiny gaps in this picture. The big gaps are between notes and intended.
Sigrok capture showing one gap, it's size is roughly around 2ms

Sigrok capture file:
sample.zip
Other items if possible
sdkconfig file (attach the sdkconfig file from your project folder)
sdkconfig.txt
elf file in the
build
folder (note this may contain all the code details and symbols of your project.)my_first_project.zip
The text was updated successfully, but these errors were encountered: