SuperHouse / esp-open-rtos

Open source FreeRTOS-based ESP8266 software framework
BSD 3-Clause "New" or "Revised" License
1.53k stars 491 forks source link

SPIFFS, FLASH SPI and PWM (Timer1) bug #604

Open Zaltora opened 6 years ago

Zaltora commented 6 years ago

Hi i got a recent bug, It is feel that receive UART interrupt > Timer1 interrupt. The motor is disrupting when i wrote on keyboard some text. Before, this problem was not present. I try to found what PR or sub-module does this bug. recent "lock" change maybe ? It is not a HW bug, and i didn't change the uart part of my app.

Zaltora commented 6 years ago

I use uart_getc_nowait(bus). I try to checkout old commit 3 month ago, but i got same problem. The good program was made 19 feb 2018. I don't no what happens.

Zaltora commented 6 years ago

Okay, i was wrong. Is not uart problem, it is the filesystem spiffs/ libc API when a save or close file. Each time a file is saved, the pwm is disturbed. Maybe the FLASH acces.

ourairquality commented 6 years ago

Interrupts are disabled while accessing the flash, for reading or writing. This is necessary because code can not be run from the flash while accessing it. Writing might be especially slow and could this cause the pwm problems? The extras/pwm implementation appears to use an interrupt that would be disabled.

It might be possible to run the pwm from a NMI. All the code in the interrupt handler would need to be in the IRAM. Never tried this, but perhaps sdk_wDev_MacTimSetFunc and sdk_wDev_MacTimArm or sdk_wDev_MacTim1SetFunc and sdk_wDev_MacTim1Arm could be used for the pwm timer?? These appears to generate NMIs. The sdk_wDev_MacTim1Arm appears to be used for a soft wdt, so perhaps try the other.

Also saw some discussion that the esp8266 might have a hardware pwm, and perhaps support could be added for that. For example, see https://github.com/esp8266/Arduino/issues/1654 Does anyone know or a hardware pwm implementation?

ourairquality commented 6 years ago

Fwiw the hardware pwm seems to work, and the registers appear to be already defined. Where this were adequate it might be smoother than a software pwm and less burden on the system. The example below could dim the blue led on a nodemcu. If someone could confirm the frequency and duty calculations then we could add a description to gpio_regs.h and perhaps even some supporting functions and an example.

    uint8_t gpio_num = 2; // Blue led
    gpio_enable(gpio_num, GPIO_OUTPUT);
    GPIO.CONF[gpio_num] |= GPIO_CONF_SOURCE_PWM;
    // Freq = (80,000,000/prescale) * (target / 256) HZ           (0   < target < 128)
    // Freq = (80,000,000/prescale) * ((256 - target) / 256)  HZ  (128 < target < 256)
    uint8_t prescale = 0xff;
    uint8_t duty = 32;
    GPIO.PWM = GPIO_PWM_ENABLE | (prescale << 16) | duty;
Zaltora commented 6 years ago

o yeah, That will be nice to get this HW pwm !! I will try this. I a mreally surprise to learn today that exist this HW pwm.

Before, i was trying to work with overlap SPI without succes to connect the flash SPI wire with my screen. I am no sure if it is possible to put esp8266 in SPI slave mode too.

Edit: the resolution is 256 ? or it can be greater ?

flannelhead commented 6 years ago

Wow @ourairquality, where did you learn about this HW PWM capability? I thought there wasn't one. So is this really different from the HW delta-sigma modulator that has been known to exists? Do you know if it supports multiple channels?

ourairquality commented 6 years ago

@flannelhead The definitions were already in the include files, and it is described there as a PWM. I think this is the sigma-delta modulator. It seems to support only one channel, but it seems possible to route that one channel to all of gpio 0 to 15. It does appear to be limited to a resolution of 256. So it is limited, but still it might suit some uses and be smoother and less burden than the software solutions. If the name 'PWM' is misleading then perhaps we should rename the definitions in the include file, and we need to confirm and documentation the frequency and duty cycle.

@Zaltora Can this PWM address your use case? If not then have you tried using the NMI timer? I could try to write an example if needed?

nochkin commented 6 years ago

I'm not 100% positive what you are referring to, but I believe this is Espressif's implementation of their software PWM. The most noticable issue is that it does not work well on 100% duty. Hardware PWM is available in ESP32 though.

Zaltora commented 6 years ago

i had begin to write a HW PWM driver with same API that SOFT PWM driver. If 100% duty don't work well, it is doesn't matter. like soft pwm, the pin will be set as output at level high. After looking register definition, i found that the correct setting for PWM is : GPIO.PWM = GPIO_PWM_ENABLE | (prescale << 8) | duty;

I can't confirm this:

    // Freq = (80,000,000/prescale) * (target / 256) HZ           (0   < target < 128)
    // Freq = (80,000,000/prescale) * ((256 - target) / 256)  HZ  (128 < target < 256)

I don't no how set the variable "target". We got just a prescale in register definition. After test, i can change duty from 0(0%) to 127(100%) for my motor. I think the problem is the frequency. It is too high. With a prescale of 0, my motor can just be on or off.

@ourairquality : I can't use this HW PWM for my app. I need more precision on duty. I didn't test NMI yet, i don't no what i need to change. My first thought was to use sdk_wDev_MacTimSetFunc and call the interupt handler. i don't no if i need to disable thing related to Timer1 or it is just a way to tell the system that this function will be masked ?