Page 1 of 1

MCPWM register programming...

Posted: Sun Nov 17, 2024 9:04 pm
by FX2032
I am trying to set up the MCPWM on a esp32-3s wroom-1 module.

I want to write to the registers directly to set the PWM up, but none of the values are changing after I write to them for example:

WRITE_PERI_REG(MCPWM_CLK_REG(0) , MCPWM_CLK_EN);
WRITE_PERI_REG(MCPWM_TIMER0_CFG0_REG(0), ((0x0<<MCPWM_TIMER0_PERIOD_UPMETHOD_S) | (914<<MCPWM_TIMER0_PERIOD_S))); // See page 1344 this sets the when to update and the period
WRITE_PERI_REG(MCPWM_GEN0_TSTMP_A_REG(0), (457)); // Set the timer compare value

None of these writes make any change to the default values if I read the values back after a pause!
(I have checked writing to things like the GPIO register etc and there seems no issue!)
HELP!

Re: MCPWM register programming...

Posted: Mon Nov 18, 2024 2:19 am
by Sprite
Did you enable and un-clockgate the MCPWM peripheral? (periph_ll_enable_clk_clear_rst)

Re: MCPWM register programming...

Posted: Wed Nov 20, 2024 7:49 pm
by FX2032
Did you enable and un-clockgate the MCPWM peripheral? (periph_ll_enable_clk_clear_rst)
Hi ESP_Sprite Many thanks! I checked and saw I made the foolish mistake of SETTING the clock reset, and not clearing it!

In case someone one day wants to do similar here is the code:

#include <stdio.h>
#include "esp_log.h"
#include "soc/mcpwm_reg.h" // For MCPWM register definitions
#include "soc/gpio_struct.h" // GPIO register definitions
#include "esp32/rom/gpio.h" // For gpio_matrix_out function
#include "driver/gpio.h" // needed for GPIO pins _num_41
#include "soc/gpio_sig_map.h" // needed for PWM0_OUT1A_IDX
#include "soc/system_reg.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/periph_ctrl.h" // For periph_module_enable() function


void app_main() {

SET_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_RMT_CLK_EN); // Enable RMT clock (check which register is needed 0 or 1)
CLEAR_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_RMT_RST); // Unclear Periferal
WRITE_PERI_REG(RMT_CH0CONF0_REG, (40 << RMT_DIV_CNT_CH0_S) | (0x8 << RMT_MEM_SIZE_CH0_S)| (0x1 << RMT_APB_MEM_RST_CH0_S)| (0x1 << RMT_CONF_UPDATE_CH0_S)); // Initialise the TX register 0 !! Ymust have the update bit or you get a carrier wave and wrong timing. Note Memsize=>No. of 48x32 blocks-max8 =8x48 pulses
WRITE_PERI_REG(RMT_SYS_CONF_REG, RMT_SCLK_ACTIVE | RMT_CLK_EN | (0x1 <<RMT_SCLK_SEL_S) | (1 << RMT_SCLK_DIV_NUM_S));

gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT);
gpio_matrix_out(GPIO_NUM_4, RMT_SIG_OUT0_IDX, 0, 0); // Map the pin to the function , signal inversion, open drain

WRITE_PERI_REG(RMT_CH0DATA_REG, (((0b0 << 31) | (PulsePeriod << 16) | (0b1<< 15) | PulsePeriod )));
WRITE_PERI_REG(RMT_CH0DATA_REG, (0x0));
SET_PERI_REG_MASK(RMT_CH0CONF0_REG, RMT_TX_START_CH0); // Send the data

Re: MCPWM register programming...

Posted: Wed Apr 23, 2025 7:56 am
by eriksl
Just out of curiousity, is there a specific reason you're writing to hardware registers explicitly, not using the IDF driver code?

Re: MCPWM register programming...

Posted: Thu Apr 24, 2025 8:12 am
by FX2032
I'm just old fashioned I guess! Most of my experience is from programing Atmel microcontrollers, and I find all the ESP32 APIs so very abstracted and exceptionally challenging to know what they are doing and how to use them!

Re: MCPWM register programming...

Posted: Thu Apr 24, 2025 9:08 am
by eriksl
I am absolutely where you are, I have lots of ESP8266s where I also bypass the SDK code as much as possible (because basically it's just bad). Also very experienced with ATmel microcontrollers.

But I must say, the IDF isn't that bad. It's well-maintained and the source is mostly open. So for the moment, and as long as it can do what I need, I'll stick to IDF driver calls. It will also make sure multi-threading and multi-core will work. But I can imagine the call to simply poke some registers ;).

Having said that, using the IDF I think you'll get more help here ;)

Re: MCPWM register programming...

Posted: Thu Apr 24, 2025 11:47 am
by FX2032
I guess I work in a bit of a strange way, and I like to know exactly what is going on in code, so I am not a big fan of "black box" systems and libraries. I realise now just how good Atmel data sheets were!

The EPS32 data sheet are OK, but for example with the ADC... the register information is worthless. I had to reverse engineer some of the earlier version APIs to see why I was getting a full scale readout at only a fraction of the fullscale voltage. It seems the API plucks some fitted curve out of a memory address to generate a calibration table. But its not a standard y=x.... type calibration, and you really cant use the ADC without it! The version 4. I think it was calls are simple enough, but the later versions are mind boggling for something which should inherently be simple!
I have managed to cobble some of the Wifi API stuff together, but only really by copying sample code, and I dont really know how it is functioning. If I try to follow some of the functions it's one call that calls another that accesses a parameter in another function that waits for the return of another variable from another function.. etc..etc. I have no idea how you are supposed to get an idea of what is actually happening, what "things" are critical, etc...
How do you manage with such things yourself?

Re: MCPWM register programming...

Posted: Thu Apr 24, 2025 11:52 am
by eriksl
I realise now just how good Atmel data sheets were!
Definitively agree there!

Also agree on the documentation that's lacking, really. These dreaded "examples". I just complained about the other day, once again. But I feel their stance towards documentation has really improved with the ESP-IDF and some complaints are actually acted upon...

Re: MCPWM register programming...

Posted: Sun May 04, 2025 5:08 am
by espxefona
Tubidy Mp3I am absolutely where you are, I have lots of ESP8266s where I also bypass the SDK code as much as possible (because basically it's just bad). Also very experienced with ATmel microcontrollers.

But I must say, the IDF isn't that bad. It's well-maintained and the source is mostly open. So for the moment, and as long as it can do what I need, I'll stick to IDF driver calls. It will also make sure multi-threading and multi-core will work. But I can imagine the call to simply poke some registers ;).

Having said that, using the IDF I think you'll get more help here ;)
Totally agree, IDF might not be perfect, but it’s definitely a step up from the old SDK days. Having the source open really helps when you want to dig deeper without going full bare-metal.