ATSAM4SD32C | SAM4S-EK2 dev board | Unable to generate PWM   - Page 1
Forum section: electronics / general

author: CM800
author_rank: Frequent Contributor
timestamp: December 14, 2015, 10:32:21 pm
content: Hello all,I am a tad stuck with trying to generate a PWM output on the ATSAM4S chip.for some reason I am getting no output at all. I may be missing something as I have not had much experience with ARM at all.What I am trying to accomplish is to generate the outputs needed for a full-bridge transformer driver, I also need to add dead-time.I have been reading through the manuals for ages, I cannot find anything that helps and along with that I have no clue on how to go about fault finding on the ARM system without any proper experience, guides or advice.Here is my code:Code:#include <asf.h>int main (void){/* Insert system clock initialization code here (sysclk_init()). */sysclk_init();board_init();pwm_channel_t pwm_channel_instance;pwm_channel_disable(PWM, PWM_CHANNEL_0);pwm_clock_t clock_setting = {.ul_clka = 1000 * 100,.ul_clkb = 0,.ul_mck = 48000000};pwm_init(PWM, &clock_setting);pwm_channel_instance.ul_prescaler = PWM_CMR_CPRE_CLKA;pwm_channel_instance.ul_period = 100;pwm_channel_instance.ul_duty = 50;pwm_channel_instance.channel = PWM_CHANNEL_0;pwm_channel_init(PWM, &pwm_channel_instance);pio_configure_pin(PIO_PA19B_PWML0, PIO_PERIPH_B);ioport_disable_pin(PIO_PA19B_PWML0);pmc_enable_periph_clk(ID_PWM);pwm_channel_enable(PWM, PWM_CHANNEL_0);while(1);}I would really appreciate any and all advice and help given.

author: poorchava
author_rank: Super Contributor
timestamp: December 15, 2015, 06:31:39 am
content: PWM library for that chip sucks. It will end up compiling to large and inefficient code even with high degree of optimization. The abstraciton layer is not convenient and is coded badly. ATMEL libs for ARM chips suck bigtime (almost the same level as STM32 CubeMX)Manipulate registers directly as advised by datasheet and you'll be fine.

author: CM800
author_rank: Frequent Contributor
timestamp: December 15, 2015, 07:56:34 am
content: Quote from: poorchava on December 15, 2015, 06:31:39 amProblem is there is so much in there I have no clue what needs to be done to get it started and going. I'm sure you understand having only used AVR before it's a major leap.

author: poorchava
author_rank: Super Contributor
timestamp: December 15, 2015, 08:13:58 am
content: Your first problem is that you are enabling clock at the end. This should not be understood as clocking the PWM counter, but clocking the module at all. No clock = no effect. In general when a module which is not clocked is written to or read from the chip should either do nothing or raise some sort of fault. SAM4 does the former (no effect). First thing you do in order to communicate with any peripheral in ARM powered microcontrollers is usually to enable power/clock to that module.So the line:Code:pmc_enable_periph_clk(ID_PWM);should be the first one, as all previous lines do nothing.In general PWM config in SAM goes like this:-configure gpio. Make sure that 'GPIO' bits are off, you want it to be peripheral output, not GPIO. Assign correct peripheral to that pin (letters from A to D)-using syntax like this:Code:PWM->PWM_CH_NUM.for exampleQuoteThere are 4 registers for every PWM channelPWM_CMR - mode register - sets clocking, data alignment and other stuff like thatPWM_CPRD - pwm periodPWM_CDTY - duty cycle register (mus be smaller than SPRD or PWM won't workPWM_DT - dead time - useful when using PWM to generate complementary outputs driving a half-bridge power stagethere are also general registers which are shared between all channels:PWM_FPE - fault detection - cam be set to 0 in order to disable thisPWM_SCM - channel sync registers, advanced stuff that you can find out on your ownPWM_DIS / PWM_EN - enable, disable channelsPWM_IFR1/IDR1/IER1/IFR2/IER2/IDR2 - interrupt controlPWM_CLK - more clock control

author: CM800
author_rank: Frequent Contributor
timestamp: December 15, 2015, 03:58:13 pm
content: Quote from: poorchava on December 15, 2015, 08:13:58 amThanks for the information, I have redone my code to look like this:Code:#include <asf.h>int main (void){/* Insert system clock initialization code here (sysclk_init()). */sysclk_init();board_init();pmc_enable_periph_clk(ID_PWM);PWM->PWM_DIS = (1 << PWM_CHANNEL_0);PWM->PWM_CH_NUM.PWM_CMR = (PWM_CMR_CPRE_CLKA & 0xF) | (PWM_CMR_CALG);PWM->PWM_CH_NUM.PWM_CDTY = 50;PWM->PWM_CH_NUM.PWM_CPRD = 100;PWM->PWM_ENA = (1 << PWM_CHANNEL_0);pio_configure_pin(PIO_PA19B_PWML0, PIO_PERIPH_B);ioport_disable_pin(PIO_PA19B_PWML0);pio_configure_pin(PIO_PA11B_PWMH0, PIO_PERIPH_B);ioport_disable_pin(PIO_PA11B_PWMH0);while(1);}However I am still getting nothing out. Am I missing something?Do you also have any recommended readings that helped you?EDIT:At last, something worked! seemed PIO wasn't working:Code:#include <asf.h>int main (void){/* Insert system clock initialization code here (sysclk_init()). */sysclk_init();board_init();PIOA->PIO_PER=0x00000000;PIOA->PIO_PDR=PIO_PA11B_PWMH0; // enable PWMPIOA->PIO_IER=0x00000000; // disable interruptsPIOA->PIO_IDR=0xFFFFFFFF;PIOA->PIO_ABCDSR= PIO_PA11B_PWMH0; // assign pin to peripheral Bpmc_enable_periph_clk(ID_PWM);PWM->PWM_CH_NUM.PWM_CMR = (PWM_CMR_CPRE_MCK & 0xF);PWM->PWM_CH_NUM.PWM_CPRD = 100;PWM->PWM_CH_NUM.PWM_CDTY = 50;PWM->PWM_ENA = (1 << PWM_CHANNEL_0);//ioport_disable_pin(PIO_PA19B_PWML0);//pio_configure_pin(PIO_PA19B_PWML0, PIO_PERIPH_B);//ioport_disable_pin(PIO_PA11B_PWMH0);//pio_configure_pin(PIO_PA11B_PWMH0, PIO_PERIPH_B);while(1);}Thankfully some people with the Arduino Due had been doing similar stuff and I managed to come across it googling bits of your code. Huge thanks!

author: poorchava
author_rank: Super Contributor
timestamp: December 15, 2015, 06:46:33 pm
content: O was gonna write that you also need to enable clock to the pip peripheral in order to set it up properly.Sent from my HTC One M8s using Tapatalk.

author: CM800
author_rank: Frequent Contributor
timestamp: December 15, 2015, 10:01:10 pm
content: Quote from: poorchava on December 15, 2015, 06:46:33 pmcurrently trying to integrate dead time and failing. I believe I disabled the protection, however I don't know how to check registers and that 'memory' thing you can access during debugging doesn't add up.. (32 hex bytes across not bits?)Code:#include <asf.h>int main (void){/* Insert system clock initialization code here (sysclk_init()). */sysclk_init();board_init();PIOA->PIO_PER = 0;PIOA->PIO_PDR = PIO_PA11B_PWMH0 | PIO_PA19B_PWML0; // enable PWMPIOA->PIO_IER = 0; // disable interruptsPIOA->PIO_IDR = 0xFFFFFFFF;PIOA->PIO_ABCDSR = PIO_PA11B_PWMH0 | PIO_PA19B_PWML0; // assign pin to peripheral Bpmc_enable_periph_clk(ID_PWM);PWM->PWM_WPCR = PWM_WPCR_WPKEY_PASSWD | (PWM_WPCR_WPRG4 << 2) | PWM_WPCR_WPCMD_DISABLE_SW_PROT;int32_t deadtime = 100; // set deadtimeint32_t width = 1000;int32_t duty = 500;// equal deadtimePWM->PWM_CH_NUM.PWM_CMR = (PWM_CMR_CPRE_MCK_DIV_8 & 0xF);PWM->PWM_CH_NUM.PWM_CPRD = width;PWM->PWM_CH_NUM.PWM_CDTY = duty;PWM->PWM_CH_NUM.PWM_DT = deadtime | ((duty-deadtime)<<15);PWM->PWM_ENA = (1 << PWM_CHANNEL_0);while(1);}Have you got any advice on this?EDIT: nevermind, figured it out. Forgot to enable it on the PWM_CMR

author: poorchava
author_rank: Super Contributor
timestamp: December 16, 2015, 07:37:04 am
content: Check the registers pertinent to PWM fault detection. If not handled correctly (and I dunno what the correct way is to be honest) but enabled (by default) if fault is detected the PWM is stopped until the fault is reset. Disable the fault detection system.