IOsetting / hc32l110-template

HDSC HC32L110 GNU GCC SDK, template and examples
Apache License 2.0
17 stars 4 forks source link

Cannot set Clock to 24 MHz #2

Open yahaggach opened 3 months ago

yahaggach commented 3 months ago

Hey there ,

First, thanks a lot :) If I can tip you some coffee let me know where !

I have an issue btw with setting the clock to the full 24 MHz using the internal RCH clock. I looked at the code and saw that prescaler being DIV1 does nothing for both PCLK and HCLK is that normal ?

IOsetting commented 3 months ago

Thank you for pointing out, I have submitted a fix 34c200e812743a63a6cd00dee57741bd6eedd7fa

Invoking Clk_Init(ClkFreq24Mhz, ClkDiv1, ClkDiv1) will set the clock to 24MHz, what kind of issue did you met?

yahaggach commented 3 months ago

Thank you for the quick reply. It still doesn't work for some weird reason. Here is my main code :

`

include "ddl.h"

include "gpio.h"

include "base_timer.h"

include "clk.h"

define LED_PIN (1) // Change this to the actual pin connected to your LED

define LED_PORT (0) // Change this to the actual port connected to your LED

int main(void) { Clk_Init(ClkFreq24Mhz, ClkDiv1, ClkDiv1); Gpio_InitIOExt(LED_PORT, LED_PIN, GpioDirOut, FALSE, FALSE, FALSE, FALSE);

while (1)
{
    GPIO_SetPinOutLow(LED_PORT, LED_PIN);
    __NOP();
    GPIO_SetPinOutHigh(LED_PORT, LED_PIN);
    __NOP();

}

}

`

I am monitoring with a logic analyzer the P01 port and here is what I see :

image

My goal is to evaluate the duration of the __NOP() function in an attempt to recreate the factory app that you can find in the T-HC32 repository (since I am using that evaluation board) in order to control a WS2812 led. I expect that this code should yield consistant 50% duty cycle square wave with the pulse width being approx. the duration of NOP + whatever overhead writing the to the GPIO port and having the level change... What is weird in the picture above is that :

1- The pulse low width seems to be approx. 4 MHz. Would that equate to the NOP duration ? That would be the case if the clock is 4 MHz which it is by default if i am not mistaken. I also expected much faster switching if the MCU really ran at 24 MHz. 2- The pulse high width seems to be equiv to approximately 2 MHz which is two times longer than the low pulse width. I tested and it is from the while loop looping which I find weird. If I put in my loop two times the code you see there successively then I get identical high and low width except for the last one which again turns to be twice longer....

So I am not really sure what is going on. It is not possible to do bitbanging of the WS2812 with pulses that are 0.2 us one needs much finer resolution in time. Am I getting something wrong ?

yahaggach commented 3 months ago

Nevermind... I ran a code that basically pulses the gppio (basically go high then go low) and inserted in between N amount of NOP. I did it with one NOP and got a pulse width of 260 ns and did it with 3 NOP and got 340 ns which means that a NOP duration is indeed approx. 40 ns corresponding to 24MHz ... What surprises me is that the duration needed for turning a gpio high then low is necessarily 220 ns which seems a lot ... Is that normal ? We are only writing to a register to do that no ? Isn't that a single clock cycle op

yahaggach commented 3 months ago

It seems that when working with such MCU one has really to go back to the basics. The macros are the reason why it takes 220 ns due to the pointer arithmetic inside... Direct port manipulation with hardcoded pointer

define PORT1_OUT_REG ((volatile uint32_t )((uint32_t)&M0P_GPIO->P1OUT))

I get approx. 90 ns per gpio operation meaning that the shortest pulse you can generate is approx. 180 ns with the M0+ at 24 MHz. I still have this weird issue that if I call successively :

PORT1_OUT_REG = 0x00; PORT1_OUT_REG = 0x10;

The above statement holds true and I get N pulses based on N lines of code but If I do a standard

while (1) { PORT1_OUT_REG = 0x10; PORT1_OUT_REG = 0x00; }

I get a train of pulses of high width of 140 ns and low width of 280 ns. I understand that in a while loop the PC counter is incremented across the lines then reset but I wonder if that explains this huge discrepancy

IOsetting commented 3 months ago

http://efton.sk/STM32/gotcha/g14.html It's not a good idea to output accurate GPIO flips using software, you might need to use a timer or other peripherals to toggle a pin.

in order to control a WS2812 led

Using SPI to control WS2812 might be more feasible, please check this https://www.newinnovations.nl/post/controlling-ws2812-and-ws2812b-using-only-stm32-spi/, I have an example for PY32F0xx but I haven't migrated it to HC32L110.

yahaggach commented 3 months ago

Yes I was aware of hardware being more consistent and faster because the mcu doesnt waste clock cycles there once it is setup. I still wanted to explore this and got to refresh my knowledge and that is thanks to your work :)

Still i realize that i come from MCUs like esp32 or the teensy with minimum 10 times higher performance so the thinking and logic with m0+ devices needs to be different. Do you have plans to implement the other examples ?

IOsetting commented 3 months ago

You are welcome~ So far, no, I am working on other projects, may not be able to play this chip for a while.