zephyrproject-rtos / zephyr

Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
https://docs.zephyrproject.org
Apache License 2.0
10.82k stars 6.6k forks source link

Silabs EFM32 / EZR32 Happy Gecko Timer and PWM support #66893

Open viktorcsanak opened 10 months ago

viktorcsanak commented 10 months ago

Is your feature request related to a problem? Please describe. PWM configured the same way via the devicetree as for efr32mg_sltb004a for a custom board based on EZR32HG220F64 does not work.

Describe the solution you'd like Understand what is causing the issue, so I can use PWM with said MCU and contribute the updated EFM32 devicetree files.

Additional context Recently I started working on a new sub-GHz radio device, based on the Si446x series. After receiving the prototypes I started porting the board out-of tree in the project. Since the board is based on EZR32HG220F64, I used efm32hg322f64.dtsi as the basis of the devicetree, since the SOC is similar enough. I have CONFIG_PWM_GECKO and CONFIG_PWM enabled in the board defconfig and project config files respectively.

In the .dts file I include a .dtsi with the following timer node:

/ {
    soc {
    timer2: timer@40010800 {
        compatible = "silabs,gecko-timers";
        reg = <0x40010800 0x400>;
        status = "disabled";

        pwm {
            compatible = "silabs,gecko-pwm";
            status = "disabled";
            #pwm-cells = <3>;
        };
    };
};

And then in the .dts file I've got

&timer2 {
    status = "okay";

    pwm2: pwm {
       status = "okay";
       pin-location = <GECKO_LOCATION(2) GECKO_PORT_C GECKO_PIN(8)>;
    };
};

Since I need to use TIM2_CC0 #2 at PC8 which is routed to a buzzer.

In the root node in the .dts file I have the following:

pwmleds {
    status = "okay";
    compatible = "pwm-leds";

    alarm_buzzer: alarm_buzzer {
        pwms = <&pwm2 0 PWM_NSEC(366166) PWM_POLARITY_NORMAL>;
    };
    pwm_led0: pwm_led0 {
        pwms = <&pwm1 1 PWM_MSEC(20) PWM_POLARITY_NORMAL>;
};

where pwm_led0 has an alias for blinky_pwm support.

At the time of writing this ticket I'm using Zephyr v3.5.0-rc1.

Please note, that to the best of my knowledge, the board was ported properly, I can build my application for it and the blinky and blinky_pwm samples, but both with my application and with the PWM sample, I don't get a PWM output signal, even tho everything else is working properly, including radio transmission and the SPI bitbang driver used for connecting the EFM32HG and Si4463 cores.

When I hook it up with a debugger, I can see that the TIMER_TypeDef *timer member of pwm_gecko_config_0 structure initialized by the driver is reset, none of the members corresponding to the register fields have a value other than zero, unlike with a efr32mg_sltb004a Thunderboard Sense 2, so my guess was that for some reason the timer itself is not initialized, but I could not figure out why.

I've run out of ideas, I already triple checked #37057 and the PRs mentioned there, and I also followed the more up to date efr32mg_sltb004a devicetree files.

I' will try to update to the latest versions, hoping that if everything else fails I can get some help here.

github-actions[bot] commented 10 months ago

Hi @viktor0061! We appreciate you submitting your first issue for our open-source project. 🌟

Even though I'm a bot, I can assure you that the whole community is genuinely grateful for your time and effort. 🤖💙

viktorcsanak commented 10 months ago

So, a quick update in-between the holidays. After verifying that the hardware itself is not faulty by successfully setting up the timer registers through SWD - even tho I encountered some shenanigans when the set commands did not have any effect on the registers - it turns out that PWM on TIM2_CC0 #2 will only work, if PWM is enabled and routed to some pins in the previous timer nodes as well, resulting in the following devictree snippet:

    &timer2 {
        status = "okay";

        pwm2: pwm {
           status = "okay";
       pin-location = <GECKO_LOCATION(2) GECKO_PORT_C GECKO_PIN(8)>;
        };
    };

    &timer1 {
        status = "okay";

        pwm1: pwm {
           status = "okay";
       pin-location = <GECKO_LOCATION(1) GECKO_PORT_E GECKO_PIN(11)>;
        };
    };

    &timer0 {
        status = "okay";

        pwm0: pwm {
           status = "okay";
       pin-location = <GECKO_LOCATION(0) GECKO_PORT_A GECKO_PIN(0)>;
        };
    };

And PR #67051.