Problem with eTPU SPWM function.

Discussion to talk about software related topics only.
Post Reply
fanat9
Posts: 56
Joined: Thu Apr 24, 2008 4:23 pm
Location: Boston
Contact:

Problem with eTPU SPWM function.

Post by fanat9 »

I need to use SPWM eTPU function on MOD5234. And I managed to get it to work. Big thanks to APPNOTE-MOD5234-eTPU: http://www.netburner.com/downloads/mod5 ... ppNote.zip. Also AppNote on SPWM from Freescale site was very useful: http://www.freescale.com/files/32bit/do ... umentation

But in real application, sometimes I have to stop SPWM on two channels. Set them to some state. Let say on to "On" and second to "Off". And finally after some time resume SPWM. Btw, I also have to have regular PWM working on third channel all the time.

Problem is next. When I trying to stop SPWM output on those channels they stop at random state. Sometimes in "On", sometimes in "Off". But at least I can resume SPWM later. See example code below.
But if I try to reinitialize those two channels as GPIO and try to toggle them - first it does not work and second SPWM got screwed too. No matter how I will try to reinitialize - it doesn't work again.

So howto stop SPWM to known state? And what is correct way to reinitialize them as GPIO pins?

It's MOD5234. Rel23_rc7. In this example nothing connected to those channels except scope probes...

Any help? Please.

Code: Select all

#include "predef.h"
#include <stdio.h>
#include <ctype.h>
#include <startnet.h>
#include <autoupdate.h>
#include <dhcpclient.h>
#include <smarttrap.h>
#include <taskmon.h>
#include <NetworkDebug.h>

#include <pins.h>      // NetBurner GPIO Pins Class
#include <eTPUinit.h>  // NetBurner eTPU Initialization
#include <eTPU.h>      // NetBurner eTPU API
#include <etpu_qom.h>  // Freescale API for eTPU QOM
#include <etpu_pwm.h>  // Freescale API for eTPU PWM
#include <etpu_spwm.h> // Freescale API for eTPU SPWM
#include <etpu_gpio.h> // Freescale API for eTPU GPIO

extern uint32_t fs_etpu_code_start;
extern uint32_t fs_etpu_data_ram_start;
extern uint32_t fs_etpu_data_ram_end;
extern uint32_t fs_etpu_data_ram_ext;

extern "C" {
void UserMain(void * pd);
}

const char * AppName="spwmTest";

#define CHANNEL0 0
#define CHANNEL1 1
#define CHANNEL9 9

void initSPWM()
{
    uint32_t *Master_rising_edge_ptr;  // Pointers used to reference.
    uint8_t  *Master_rising_edge_ptr8; // Master's rising edge.

	int error = fs_etpu_spwm_init_master(CHANNEL1, 48, 4275,
											FS_ETPU_TCR2,
											etpu_a_tcr2_freq,
											FS_ETPU_SPWM_IMMEDIATE,
											0,
											FS_ETPU_SPWM_FALLING_EDGE_INT_DMA,
											0x00010101,
											0x01010101);
	if (error != 0)
		iprintf("fs_etpu_spwm_init_master error = %d\n\r", error);

	Master_rising_edge_ptr = fs_etpu_data_ram(CHANNEL1) +
							(uint32_t)((uint32_t*)(FS_ETPU_SPWM_RISING_OFFSET >> 2)) -
							(uint32_t)((uint32_t*)((fs_etpu_data_ram_start) / 4));

	Master_rising_edge_ptr8 = (uint8_t*)Master_rising_edge_ptr + 1;
	Master_rising_edge_ptr = (uint32_t*)Master_rising_edge_ptr8;

	error = fs_etpu_spwm_init_slave(CHANNEL0, FS_ETPU_PRIORITY_MIDDLE,
										48,
										4200,
										50,
										FS_ETPU_TCR2,
										etpu_a_tcr2_freq,
										Master_rising_edge_ptr);
	if (error != 0)
	  	iprintf("fs_etpu_spwm_init_slave error = %d\n\r", error);

	fs_etpu_spwm_run_master(CHANNEL1, FS_ETPU_PRIORITY_MIDDLE);
}

void pauseSPWM()
{
	fs_etpu_disable(CHANNEL0); //Slave channels must be disabled prior to stopping the master channel.
	while ((eTPU->CSSR_A.R >> CHANNEL0) &0x1 == 0x1); //Wait if channel is being serviced.
	fs_etpu_disable(CHANNEL1); //Now when all Slave channels disabled we can disable Master channel.
	while ((eTPU->CSSR_A.R >> CHANNEL1) &0x1 == 0x1); //Wait if channel is being serviced.
}

void restartSPWM()
{
	//The slave channels must be re-enabled prior to re-enabling the master channel.
	fs_etpu_enable(CHANNEL0,FS_ETPU_PRIORITY_MIDDLE);
	fs_etpu_spwm_run_master(CHANNEL1, FS_ETPU_PRIORITY_MIDDLE);
}

void UserMain(void * pd) {
    InitializeStack();
    if (EthernetIP == 0) GetDHCPAddress();
    OSChangePrio(MAIN_PRIO);
    EnableAutoUpdate();
    EnableTaskMonitor();

    #ifndef _DEBUG
    EnableSmartTraps();
    #endif

    #ifdef _DEBUG
    InitializeNetworkGDB_and_Wait();
    #endif

    iprintf("spwmTest application started\n");

	//eTPUInit();  //SPWM don't work with this init.
    MOD5234_etpu_init();
    MOD5234_etpu_start();

	//Init PWM on Channel9 of eTPU module.
	int error = fs_etpu_pwm_init(CHANNEL9, FS_ETPU_PRIORITY_MIDDLE,
									12,
									3,
									FS_ETPU_PWM_ACTIVEHIGH,
									FS_ETPU_TCR1,
									etpu_a_tcr1_freq);
    if (error != 0)
    	iprintf("PWM on Channel9 init error = %d\n\r", error);

    //Init SPWM.
    initSPWM();
	iprintf("SPWM initialized.\n\r");

	int i = 0;
    while (true)
    {
    	iprintf("Cycle = %d\n\r", i);
    	OSTimeDly(TICKS_PER_SECOND * 2);
        pauseSPWM();
        iprintf("SPWM disabled.\n\r");

    	OSTimeDly(TICKS_PER_SECOND);
        restartSPWM();
        iprintf("SPWM enabled.\n\r");
        i++;
    }
}
fanat9
Posts: 56
Joined: Thu Apr 24, 2008 4:23 pm
Location: Boston
Contact:

Re: Problem with eTPU SPWM function.

Post by fanat9 »

Ok. A quick update =)

1. Where is a problem with eTPU RAM malloc, so switching between eTPU functions for given etpu channel is limited.
2. SPWM and PWM channels could be stopped in desired state by changing duty cycle and frequency and then stopping the channel. At low frequency takes too long, so wasn't acceptable in my case.
3. Another hack always stop channels in "Off" state: In PWMMDC eTPU function you actually can stop channels in desired state, check fs_etpu_pwmmdc_disable_1ph for example. What they do is they write predefined value to eTPU->CHAN[CHANNEL1].HSRR.R; This functionality missing for SPWM. But experimentally I found that with 0x01 channels always stop in "Off" state. Clearly dangerous solution, but so far no problems discovered.
4. And finally I found solution which works for me: QOM eTPU function. In LOOP mode it works the same way as SPWM and final state could be defined.

Best regards
Post Reply