Need help with PWM/TC channels - Specifically PC26

Discussion around product based on ARM Cortex M3 core.

Moderators: nferre, ncollot

Tyler@Technica
Posts: 8
Joined: Thu Jul 03, 2014 12:02 am

Need help with PWM/TC channels - Specifically PC26

Thu Jul 03, 2014 12:42 am

Hey guys,

First, a bit of background.  I'm a Mechanical Engineer, and over the past two years I have been working on a project that started originally with an Arduino Uno, and is now currently on a custom board based off of the sam3x8e / Arduino Due platform.  I have no formal training in C++ or microcontroller architectures, so I will more than likely use the wrong names for everything and be a bit slow to follow.  Please bear with me.

Over the past two months or so, I've been trying to transition entirely away from the Arduino platform (hardware and IDE).  For all its merits, it's not enough for what we need, and it has ended up causing a lot of problems for us in the long run.  As of right now, everything on our custom board does work, but it's run through the Visual Micro plugin for Atmel Studio, so essentially still on the Arduino IDE.  

We've got 13 ADC channels (including chip temp), 4 PWM channels, 2 TC waveform channels, 2 TC capture channels, and a handful of digital I/Os on our board that we need access to.

All are operational except one of the TC waveform channels.  PC26 is connected to pin 4 on the Arduino Due, and within the Arduino IDE is considered a PWM channel, but it is actually a TC channel.  I ran into a similar problem with PC25, but managed to get it working by following some similar formatting with the TC capture channels.  I've tried everything I know how to do to get PC26 up and running the same way, as a PWM channel, but I can't figure it out, and I can't seem to find anything in the Arduino source code that would lead me in the right direction.  

tl;dr

I need to set up PC26 the same way that PC25 is setup below.  As far as I can tell, they're both a part of TC6.  PC25 is TIOA6 and PC26 is TIOB6 - the 'B' seems to be my problem.  

This comes from src\ASF\sam\boards\arduino_due_x\arduino_due_x.h - 

Code: Select all

/*! Waveform Output Channel 6 */
#define CHANNEL_PWM_MAC6 
#define PIN_TC2_TIOA6           (PIO_PC25_IDX)
#define PIN_TC2_TIOA6_MUX       (IOPORT_MODE_MUX_B)
#define PIN_TC2_TIOA6_FLAGS     (PIO_PERIPH_B | PIO_DEFAULT)

#define PIN_TC2_TIOA6_PIO       PIOC
#define PIN_TC2_TIOA6_MASK      PIO_PC25
#define PIN_TC2_TIOA6_ID        ID_PIOC
#define PIN_TC2_TIOA6_TYPE      PIO_PERIPH_B
#define PIN_TC2_TIOA6_ATTR      PIO_DEFAULT
And from src\config\conf_board.h - 

Code: Select all

/** Configure TC2 channel A6 as waveform output. **/
#define TC2_CHANNEL_WAVEFORM 0
#define ID_TC2_WAVEFORM      ID_TC6
#define PIN_TC2_WAVEFORM     PIN_TC2_TIOA6
#define PIN_TC2_WAVEFORM_MUX PIN_TC2_TIOA6_MUX
I've likely not included all of the information that I should have to get an answer, so please don't hesitate to ask for more details or more code.  

Any help would be greatly appreciated.  Once I get this figured out my next tasks include SD memory communication over SPI, FTDI programming with SAM-BA, and plenty more.

Thanks!

-Tyler
Tyler@Technica
Posts: 8
Joined: Thu Jul 03, 2014 12:02 am

Re: Need help with PWM/TC channels - Specifically PC26

Tue Jul 15, 2014 8:51 pm

So with the 2000+ views and no responses, I have to ask...

Did I ask a stupid question?  Or is this really as difficult as I think it is?  I figure it's got to be one of the two.  Hah.
jharley
Posts: 238
Joined: Thu Dec 06, 2012 6:40 am

Re: Need help with PWM/TC channels - Specifically PC26

Tue Jul 15, 2014 11:21 pm

Correct me if i have this wrong.... from your explanation, for HW you are using a custom board with the sam3x8e, this design is based off the Arduino Due, and you are leveraging the ASF code for the Due.

Q: on the Due PC26 is also connected to PA29, does your custom board also connect these two pins?

Also, It might help if you provided your HW initialization code, at the very least your PWM intialization.

Just to make sure your hardware is working have you tried to just set PC26 as a GPIO output and toggled it high/low?
Tyler@Technica
Posts: 8
Joined: Thu Jul 03, 2014 12:02 am

Re: Need help with PWM/TC channels - Specifically PC26

Tue Jul 15, 2014 11:59 pm

Correct me if i have this wrong.... from your explanation, for HW you are using a custom board with the sam3x8e, this design is based off the Arduino Due, and you are leveraging the ASF code for the Due.
That is correct.  
Q: on the Due PC26 is also connected to PA29, does your custom board also connect these two pins?
Nope, it does not.  PC26 is the pin I want though, I know it works (see below).
Just to make sure your hardware is working have you tried to just set PC26 as a GPIO output and toggled it high/low?
I haven't run that test specifically, but the hardware does work.  As mentioned, our program is fully operational through Visual Micro, which utilizes the Arduino IDE.  So somewhere within the Arduino source code, they configure PC26 to do exactly what I want it to do.  Can't find it to save my life.
Also, It might help if you provided your HW initialization code, at the very least your PWM intialization.
Do you mean the TC initialization?  As far as I can tell, using this channel for PWM wouldn't actually have anything to do with the PWM module, just the TC module.  I could be wrong though. 

Here's the initialization code for the TC waveform outputs.  Two are operational, the sections of code that are commented out are the sections where I was trying to get PC26 up and running.  

Code: Select all

static void tc_waveform_initialize(void)
{
	uint32_t ra, rc;
	uint32_t ra2, rc2;

	/* Configure the PMC to enable the TC module. */
	sysclk_enable_peripheral_clock(ID_TC1);
	sysclk_enable_peripheral_clock(ID_TC6);

	/* Init TC to waveform mode. */
	tc_init(CAP1_TC, TC0_CHANNEL_WAVEFORM,
			/* Waveform Clock Selection */
			TC_CMR_TCCLKS_TIMER_CLOCK4
			| TC_CMR_WAVE /* Waveform mode is enabled */
			| TC_CMR_ACPA_SET /* RA Compare Effect: set */
			| TC_CMR_ACPC_CLEAR /* RC Compare Effect: clear */
			| TC_CMR_CPCTRG /* UP mode with automatic trigger on RC Compare */
			);
			
	tc_init(CAP2_TC, TC2_CHANNEL_WAVEFORM,
			/* Waveform Clock Selection */
			TC_CMR_TCCLKS_TIMER_CLOCK4
			| TC_CMR_WAVE /* Waveform mode is enabled */
			| TC_CMR_ACPA_SET /* RA Compare Effect: set */
			| TC_CMR_ACPC_CLEAR /* RC Compare Effect: clear */
			| TC_CMR_CPCTRG /* UP mode with automatic trigger on RC Compare */
			| TC_CMR_BCPB_SET
			| TC_CMR_BCPC_CLEAR
			);		
			
	//tc_init(CAP2_TC, TC2_B6_WAVEFORM,
			///* Waveform Clock Selection */
			//TC_CMR_TCCLKS_TIMER_CLOCK4
			//| TC_CMR_WAVE /* Waveform mode is enabled */
			//| TC_CMR_ACPA_SET /* RA Compare Effect: set */
			//| TC_CMR_ACPC_CLEAR /* RC Compare Effect: clear */
			//| TC_CMR_CPCTRG /* UP mode with automatic trigger on RC Compare */
			//);

	/* Configure waveform frequency and duty cycle. */
	rc = (sysclk_get_peripheral_bus_hz(CAP1_TC) /
			divisors[TC_CMR_TCCLKS_TIMER_CLOCK4]) /
			PWM_FREQUENCY;
	tc_write_rc(CAP1_TC, TC0_CHANNEL_WAVEFORM, rc);
	ra = (PERIOD_VALUE - 150) * rc / PERIOD_VALUE;
	tc_write_ra(CAP1_TC, TC0_CHANNEL_WAVEFORM, ra);
	
	rc2 = (sysclk_get_peripheral_bus_hz(CAP2_TC) /
			divisors[TC_CMR_TCCLKS_TIMER_CLOCK4]) /
			PWM_FREQUENCY;
	tc_write_rc(CAP2_TC, TC2_CHANNEL_WAVEFORM, rc2);
	ra2 = (PERIOD_VALUE - 100) * rc2 / PERIOD_VALUE;
	tc_write_ra(CAP2_TC, TC2_CHANNEL_WAVEFORM, ra2);
	
	//rc3 = (sysclk_get_peripheral_bus_hz(CAP2_TC) /
			//divisors[TC_CMR_TCCLKS_TIMER_CLOCK4]) /
			//PWM_FREQUENCY;
	//tc_write_rc(CAP2_TC, TC2_B6_WAVEFORM, rc3);
	//ra3 = (PERIOD_VALUE - 100) * rc3 / PERIOD_VALUE;
	//tc_write_ra(CAP2_TC, TC2_B6_WAVEFORM, ra3);

	/* Enable TC TC_CHANNEL_WAVEFORM. */
	tc_start(CAP1_TC, TC0_CHANNEL_WAVEFORM);
	tc_start(CAP2_TC, TC2_CHANNEL_WAVEFORM);
}
Thanks for your help!  Let me know if I need to put up any more of my code.
jharley
Posts: 238
Joined: Thu Dec 06, 2012 6:40 am

Re: Need help with PWM/TC channels - Specifically PC26

Wed Jul 16, 2014 7:42 pm

So, after some digging...

The TC_CMRx register, like most registers is cleared on reset. One minor problem ... one field, if it remains cleared, configures TIOB as an input.

See EEVT: External Event Selection register.

Try changing your tc_init() call to add TC_CMR_EEVT_XC0 to make sure you can use TIOB as output.

Code: Select all

   tc_init(CAP2_TC, TC2_B6_WAVEFORM,
         /* Waveform Clock Selection */
         TC_CMR_TCCLKS_TIMER_CLOCK4
         | TC_CMR_WAVE /* Waveform mode is enabled */
         | TC_CMR_ACPA_SET /* RA Compare Effect: set */
         | TC_CMR_ACPC_CLEAR /* RC Compare Effect: clear */
         | TC_CMR_CPCTRG /* UP mode with automatic trigger on RC Compare */
         | TC_CMR_EEVT_XC0 /* make sure TIOB is NOT selected as ext evnt, so it can generate waveforms */
         );  
There is also a note about this "gotcha" for the tc_init() function in the tc.c file

Code: Select all

/**
 * \brief Configure TC for timer, waveform generation or capture.
 *
 * \param p_tc Pointer to a TC instance.
 * \param ul_channel Channel to configure.
 * \param ul_mode Control mode register value to set.
 *
 * \attention If the TC is configured for waveform generation, the external
 * event selection (EEVT) should only be set to \c TC_CMR_EEVT_TIOB or the
 * equivalent value \c 0 if it really is the intention to use TIOB as an
 * external event trigger.\n
 * This is because the setting forces TIOB to be an input even if the
 * external event trigger has not been enabled with \c TC_CMR_ENETRG, and
 * thus prevents normal operation of TIOB.
 */
void tc_init(Tc *p_tc, uint32_t ul_channel, uint32_t ul_mode)

Return to “SAM3 Cortex-M3 MCU”

Who is online

Users browsing this forum: No registered users and 1 guest