µTasker Forum

µTasker Forum => NXPTM M522XX, KINETIS and i.MX RT => Topic started by: Raffaele on May 13, 2018, 07:29:46 PM

Title: First steps into uTasker and generating PWM from my task
Post by: Raffaele on May 13, 2018, 07:29:46 PM
Hi,
I'm having some problems with running simple tasks for the FRDM-KL03.

1)
As a first step I tried something very simple: adding a fnDebug("Hello World!"); in the file Watchdog.c before the function fnRetriggerWatchdog();
I followed the guide to build the project (did it for FLASH).
Opened the terminal for serial communication at baud rate 19200
Copied the .bin file created in "Applications\uTaskerV1.4\KinetisDesignStudio\uTaskerV1.4_FLASH" to the board.

But nothing is printed to the terminal.
I also built the project in Visual Studio and set a breakpoint in the Watchdog.c file to be sure the function is reached, and yes it is.


2)
I tried to create my own task. Following the  guide (http://www.utasker.com/docs/uTasker/uTaskerV1.4_user_guide.PDF   chapter 5):
I created my .c file with a function that generates PWM signals:



Code: [Select]
#include "config.h"

extern void fnTaskMyPWM(TTASKTABLE *ptrTaskTable){
    PWM_INTERRUPT_SETUP pwm_setup;
    pwm_setup.int_type = PWM_INTERRUPT;
    pwm_setup.int_handler = 0;                                           
    pwm_setup.pwm_mode = (PWM_CLOCK | PWM_PRESCALER_16);
    pwm_setup.pwm_frequency = PWM_FREQUENCY(20000, 16);
    pwm_setup.pwm_reference = (_TIMER_0 | 0);
    fnConfigureInterrupt((void *)&pwm_setup);
    pwm_setup.pwm_reference = (_TIMER_0 | 1);                            // timer module 0, channel 1
    fnConfigureInterrupt((void *)&pwm_setup);                           
    pwm_setup.pwm_reference = (_TIMER_1 | 0);                            // timer module 0, channel 1
   // pwm_setup.pwm_frequency = PWM_TIMER_US_DELAY(TIMER_FREQUENCY_VALUE(20), 4);// generate 20000Hz on PWM output
    pwm_setup.pwm_reference = (_TIMER_1 | 1);                            // timer module 1, channel 0
    fnConfigureInterrupt((void *)&pwm_setup);                           
    pwm_setup.pwm_value   = _PWM_PERCENT(50, pwm_setup.pwm_frequency);   // 50% PWM (high/low)
    fnConfigureInterrupt((void *)&pwm_setup);   
}

I launch the task from TaskConfig.c with
Code: [Select]
{"x", fnTaskMyPWM, NO_QUE, (DELAY_LIMIT)(2 * SEC), 0, UTASKER_GO},However I can't see any PWMs on PA0, PB5, PB10 or PB11.
I also tried to generate only 1 signal at the time instead of 4, but nothing.
Title: Re: First steps into uTasker and generating PWM from my task
Post by: mark on May 13, 2018, 10:36:48 PM
Hi Raffaele

1. When you build for your KL03 board and load the binary do you see the green LED flashing at 2.5Hz? If you don't it means that the code doesn't operate - make sure that you have set the compiler to build for Cortex-M0+ core and used the correct linker script file KL_32_2_BM.ld. If any of these are wrong the code will not be able to operate.

2. Are you sure that you have set up your new task to be scheduled (once)?

I corrected your PWM setup as follows:

        PWM_INTERRUPT_SETUP pwm_setup;
        pwm_setup.int_type = PWM_INTERRUPT;
        pwm_setup.int_handler = 0;
        pwm_setup.pwm_mode = (PWM_SYS_CLK/*PWM_CLOCK*/ | PWM_PRESCALER_16);
        pwm_setup.pwm_frequency = PWM_FREQUENCY(20000, 16);
        pwm_setup.pwm_value = _PWM_PERCENT(50, pwm_setup.pwm_frequency);   // 50% PWM (high/low)
        pwm_setup.pwm_reference = (_TIMER_0 | 0);
        fnConfigureInterrupt((void *)&pwm_setup);
        pwm_setup.pwm_reference = (_TIMER_0 | 1);                            // timer module 0, channel 1
        fnConfigureInterrupt((void *)&pwm_setup);
        pwm_setup.pwm_reference = (_TIMER_1 | 0);                            // timer module 0, channel 1
        fnConfigureInterrupt((void *)&pwm_setup);
        pwm_setup.pwm_reference = (_TIMER_1 | 1);                            // timer module 1, channel 0
        fnConfigureInterrupt((void *)&pwm_setup);


Note that PWM_SYS_CLK is used to select the standard clock to the timer (you were using the clock frequency itself which causes the mode to be incorrectly understood).
Also you were not setting PWM values for the first channels (they were probably 0 since when I first tried it i had no output)

Attached is the binary that I build with this code - the green LED doesn't blink because it is now used as PWM output and the LED has an orange /yellow color since its individual LEDs are being controlled with 50% PWM.
I also added a "Hello" output in the watchdog task in the second binary, which works on my board (19200 Baud).

Regards

Mark

P.S. Use UTASKER_ACTIVATE to schedule the task once - (or UTASKER_STOP so that it is scheduled after 2s). UTASKER_GO causes it to continuously run!
Title: Re: First steps into uTasker and generating PWM from my task
Post by: Raffaele on May 14, 2018, 02:54:54 AM
Hi Mark,
yes all the parameters are set correctly. I followed all the steps in this video: https://www.youtube.com/watch?v=K8ScSgpgQ6M&feature=youtu.be
But the code still does not operate, the LED doesn't blink at 2.5Hz (I tried again with new code).

Your .bin files work on my boards (both LED and PWM are correct) so the hardware is ok. At this point it is obviously a problem of my config

The only doubt is about the linker, the correct name should be KL_32_2.ld and not KL_32_2_BM.ld, correct?

I also ran the simulation. From
\uTasker-Kinetis-master\Applications\uTaskerV1.4\Simulator
I launched the file uTaskerV1-4 in Visual Studio, and the simulator shows the blinking LED!
Title: Re: First steps into uTasker and generating PWM from my task
Post by: mark on May 14, 2018, 11:53:44 AM
Raffaele

Yes, KL_32_2.ld (my mistake with the _BM..!)

Please post the binary file that is not running because I can check it on my board (it is visible in case of setup errors)).

Also try the following:
- set the define BLINKY (or BLINKEY, depending how it is spelled in your version) in config.h

This will reduce the project to just the OS with the watchdog re-trigger/LED flashing and so will exclude any problems potential due to peripherals (also make sure that your new task is removed, or made conditional on this define so that it is automatically removed).
This version will also use little SRAM (which is tight on the KL03, with just 2k).

Regards

Mark
Title: Re: First steps into uTasker and generating PWM from my task
Post by: mark on May 14, 2018, 12:32:45 PM
Raffaele

I just tried with the open source version and found that if I simply set up the KL03 it worked when built with IAR but not when build with GCC. As I mentioned in the previous post, the SRAM is very small in this part so I disabled a few things that consume some when not needed for basic testing:
- I2C_INTERFACE
- SUPPORT_PORT_INTERRUPTS
- SUPPORT_ADC
- SUPPORT_RTC
and then it operated.

Looking at the RAM use (in menu 5 - "memory") it looked still critical:

System memory use:
==================
Free heap = 0x010c from 0x0400
Unused stack = 0x00000000 (0x0000011b)


There are 0x10c byte on heap that haven't been allocated but there is no unused stack (this means that the stack pointer is overlapping with the top of heap)

So I reduced the heap size by 0xf0

    #define OUR_HEAP_SIZE        (HEAP_REQUIREMENTS)(((1.0 * 1024) - 0xf0) * MEM_FACTOR)

which then gave

Free heap = 0x001c from 0x0310
Unused stack = 0x00000053 (0x0000020c)


which shows that there is no overlap any more and there is 0x53 bytes of stack margin.

I expect that your problems are due to having too any things enabled for the KL03's memory. You will need to check the map file to see what is consuming static memory and disable as much as possible that is not relevant to your work in order to keep the stack margin positive (and thus safe). Use the memory monitor regularly to keep an eye on its state as you develop your own code since you may be surprised at how much even small chances can additionally consume. The small parts like KL02 (1k SRAM) and KL03 (2k SRAM) are very limited and need to be closely monitored to achieve reliable operation!

Regards

Mark

P.S. I you disable the ADC there is an error in a simulation file. Pull the latest kinetisSim.c to solve this.


Title: Re: First steps into uTasker and generating PWM from my task
Post by: Raffaele on May 14, 2018, 03:04:31 PM
Hey Mark,
no need to upload the bin file. It was a matter of resources. I disabled SUPPORT_ADC, RTC.. and it's working.

Still a few questions about the PWM:

1) is it possible to set the voltage amplitude of the PWM signal?
2) would it be possible to use a secondary task that changes the parameters of the PWM during operation? Say I have TASK1 that generates the PWM and then during operation a TASK2 stops the TASK1, changes the parameters of the PWM and generates it again with the new parameters. Would this work?
3) How do I choose the PREASCALER if the PWM frequency and duty cycle are both very low - 2 or 3 Hz but the duty cycle of 0.2ms?

Thanks a lot for your support
Title: Re: First steps into uTasker and generating PWM from my task
Post by: mark on May 14, 2018, 05:59:54 PM
Hi

1. THE PWM output is a digital output that is fixed at the CPU's power supply, so can not be adjusted in amplitude.

2. Once the PWM is running its value can be changed by writing directly to its compare register:
EG. for an output controlled by FTM (or TPM), channel 1
FTM1_C1V = _PWM_PERCENT(ucPWMValue, usFrequencyCount);
where the first parameter is the required PWM percentage value (0..100) and the second is the value that was set as time base originally.

3. The timers are 16 bit and there is a limit to the lowest frequency that can be generated. This limit is defined by the PWM resolution required, the counter width (16 bits) and the clock frequency that it uses. For slower PWM signals a slower clock needs to be used.
The options are
TPM_CLOCKED_FROM_OSCERCLK     (crystal speed - 32kHz?)
TPM_CLOCKED_FROM_MCGIRCLK     (8MHz)    if USE_FAST_INTERNAL_CLOCK is disabled it will be 2MHz instead
or clocked from MCGFLLCLK when above are not defined.


If the 8MHz clock is used it will give 120Hz (8ms) as slowest frequency (with pre-scaler or 1 and 128 times slower with prescaler of 128)
From 2MHz 30Hz (32ms)
Therefore the best solution is to use an external 32kHz source (TPM_CLOCKED_FROM_OSCERCLK) which allows down to 2Hz (488ms)

These are with no pre-scaler:
You can choose pre-scaler from 1 to 128 (PWM_PRESCALER_1, PWM_PRESCALER_2, ....PWM_PRESCALER_128) to divide further.

The pre-scaler value is valid for each individual timer, eg.
pwm_setup.pwm_mode = (PWM_SYS_CLK | PWM_PRESCALER_16);
When setting the PWM frequecy use the same pre-scaler value in the equation, eg.:
pwm_setup.pwm_frequency = PWM_TIMER_US_DELAY(TIMER_FREQUENCY_VALUE(1000), 16);

Although not exactly the same in the KL03 the following give some ideas of also cascading timers or using lower frequencies:
https://community.nxp.com/message/1006476
https://community.nxp.com/message/1006476

Regards

Mark





Title: Re: First steps into uTasker and generating PWM from my task
Post by: Raffaele on June 01, 2018, 02:16:07 PM
Hi still 2 quick questions about this. Where do I find the following two (RAM use in menu 5 and map file)?

Looking at the RAM use (in menu 5 - "memory") it looked still critical:
You will need to check the map file to see what is consuming static memory and disable as much as possible
Title: Re: First steps into uTasker and generating PWM from my task
Post by: AlexS on June 01, 2018, 03:15:30 PM
I can help with the second one. It's in the build folder, next to the AXF/ELF binary file. It has the same root name as the binary, but with '.map' as extension. Open it with any text editor, it contains a lot of useful information on how your RAM and FLASH memory is being spent and is key to understanding what optimizations you need to do.

Alex
Title: Re: First steps into uTasker and generating PWM from my task
Post by: Raffaele on June 01, 2018, 05:47:31 PM
Thank you Alex. The other, I think is the build option nr. 5 in KDS