Atmel website | ARM Community | AVR freaks | Technical Support
Banner
 FAQ •  Search •  Register •  Login 

All times are UTC + 1 hour [ DST ]




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Problems using TC on 9260 (for PWM-like generation) [SOLVED]
PostPosted: Fri Jul 03, 2009 1:19 pm 
Offline

Joined: Fri Jul 03, 2009 1:07 pm
Posts: 5
Hi all,

I'm trying to write a linux kernel module, that should activate the TIOA3 and TIOB3, to output a pulse train. Later on, I'll add a sysfs interface to control the pulse width and possibly the frequency.

However, I'm not able to get anything out on TIOA3 and TIOB3...
And I've probably got even worse problems, as it seems that I can't read back any values at all from the TC-registers...

Do anyone have any idea to why I can't write/read the registers?

The code:
Code:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <asm/io.h>
#include <mach/at91sam9260.h>
#include <mach/at91_tc.h>
#include <mach/gpio.h>


static volatile __iomem *tc_base;
struct clk *tc_clk;

static inline u32 at91_tc_read(unsigned int offset)
{
   return __raw_readl(tc_base + offset);
}

static inline void at91_tc_write(unsigned int offset, u32 value)
{
   __raw_writel(value, tc_base + offset);
}


static int __init beeper_init()
{
   at91_set_B_periph(AT91_PIN_PB0, 0);
   at91_set_B_periph(AT91_PIN_PB1, 0);

   tc_clk = clk_get(NULL, "tc3_clk");
   clk_enable(tc_clk);

   tc_base = ioremap(AT91SAM9260_BASE_TC3, 0xFC);
   if (!tc_base){
      printk("ERROR\n");
      goto unmap;
   }

   at91_tc_write(AT91_TC_CCR,
            AT91_TC_CLKDIS);

   at91_tc_write(AT91_TC_BMR,
            AT91_TC_TC0XC0S_NONE |
            AT91_TC_TC1XC1S_NONE |
            AT91_TC_TC2XC2S_NONE);

   printk(KERN_ALERT "register TC_BMR (0x%08X) = 0x%08X\n",
          AT91_TC_BMR,
          at91_tc_read(AT91_TC_BMR));

   at91_tc_write(AT91_TC_CMR,
            AT91_TC_TIMER_CLOCK5 | /* slow clock, 32 kHz */
            AT91_TC_WAVE | /* waveform mode */
            AT91_TC_EEVTEDG_NONE | /* must be disabled for TIOB output */
            AT91_TC_WAVESEL_UP); /* count up and wrap back to zero */

   wmb();

   printk(KERN_ALERT "register TC_CMR (0x%08X) = 0x%08X\n",
          AT91_TC_CMR,
          at91_tc_read(AT91_TC_CMR));

#define TIMER_COUNTER_MAX_DUTY 0x4000
   at91_tc_write(AT91_TC_RC,
            TIMER_COUNTER_MAX_DUTY);

   wmb();

   printk(KERN_ALERT "register TC_RC (0x%08X) = 0x%08X\n",
          AT91_TC_RC,
          at91_tc_read(AT91_TC_RC));

   wmb();

/* Enable TC */
   at91_tc_write(AT91_TC_CCR,
            AT91_TC_SWTRG | AT91_TC_CLKEN);

   wmb();

   at91_tc_write(AT91_TC_RB,
            TIMER_COUNTER_MAX_DUTY/2);
   wmb();
   printk(KERN_ALERT "register TC_RB (0x%08X) = 0x%08X\n",
          AT91_TC_RB,
          at91_tc_read(AT91_TC_RB));

   at91_tc_write(AT91_TC_RA,
            TIMER_COUNTER_MAX_DUTY/3);
   wmb();
   printk(KERN_ALERT "register TC_RA (0x%08X) = 0x%08X\n",
          AT91_TC_RA,
          at91_tc_read(AT91_TC_RA));

unmap:
   return 0;
}

static void __exit beeper_exit(void)
{
   printk("Removing beeper.\n");

   at91_tc_write(AT91_TC_CCR,
            AT91_TC_CLKDIS);

   wmb();

   clk_disable(tc_clk);
   clk_put(tc_clk);
   iounmap(tc_base);
}

module_init(beeper_init);
module_exit(beeper_exit);

MODULE_AUTHOR("Author");
MODULE_DESCRIPTION("Use TC to create PWM for beeper");
MODULE_LICENSE("GPL");

Which results in:
Code:
# insmod ./atmel_tc_beeper_pwm.ko
register TC_BMR (0x000000C4) = 0x00000000                                   
register TC_CMR (0x00000004) = 0x00000000                                   
register TC_RC (0x0000001C) = 0x00000000                                   
register TC_RB (0x00000018) = 0x00000000                                   
register TC_RA (0x00000014) = 0x00000000 
#

Thus, I'm not able to read out anything from the controllling registers. (And/or I'm not able to write to them).

I'm sure that I'm missing something simple...
Is there anyone that can spot something obvious? Or lead me in the correct path?

Thanks in advance!
Regards,


Last edited by vastgoten on Sat Jul 04, 2009 2:01 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Problems using TC on 9260 (for PWM-like generation)
PostPosted: Fri Jul 03, 2009 7:12 pm 
Offline

Joined: Tue Nov 11, 2008 12:47 am
Posts: 30
Location: Russia
vastgoten wrote:

The code:
Code:
static volatile __iomem *tc_base;


Thus, I'm not able to read out anything from the controllling registers. (And/or I'm not able to write to them).


Hi.
It is necessary to assign type to the pointer tc_base, the compiler considers it as the pointer to int and You have wrong addressing. Maybe

static void volatile __iomem *tc_base;


Top
 Profile  
 
 Post subject: Re: Problems using TC on 9260 (for PWM-like generation) [SOLVED]
PostPosted: Sat Jul 04, 2009 1:25 pm 
Offline

Joined: Fri Jul 03, 2009 1:07 pm
Posts: 5
sasamy wrote:
Hi.
It is necessary to assign type to the pointer tc_base, the compiler considers it as the pointer to int and You have wrong addressing. Maybe

static void volatile __iomem *tc_base;

Hi!

Thanks for your good eyes!

I knew that it should be/was something simple that I overlooked.

After fixing that problem, it was just a matter of configuring the registers as I want them. Everything is working now.

All that is left is to design and build a good sysfs interface; but that should be simple.

Regards


Top
 Profile  
 
 Post subject: Re: Problems using TC on 9260 (for PWM-like generation) [SOLVED]
PostPosted: Thu Sep 10, 2009 2:06 pm 
Offline

Joined: Tue Sep 01, 2009 3:43 pm
Posts: 3
Hello,

I have this same code in an attempt to generate a signal on TIOB2. I have
Code:
at91_set_A_periph(AT91_PIN_PC6, 0)
and have adjusted the at91_tc_read/write routines to the proper offset for this channel (2*0x40). I can see the counter registers changing and everything seems to be fine. However, I can't get any signal out on the pin.

Is there anything else that has to be done to get the signal out on the pin? Do I have to tell somehow that this pin is in the out direction or something similar?

Thanks,

--
Pedro


Top
 Profile  
 
 Post subject: Re: Problems using TC on 9260 (for PWM-like generation) [SOLVED]
PostPosted: Thu Oct 01, 2009 9:03 pm 
Offline

Joined: Fri Jul 03, 2009 1:07 pm
Posts: 5
psanchez wrote:
Hello,

I have this same code in an attempt to generate a signal on TIOB2. I have
Code:
at91_set_A_periph(AT91_PIN_PC6, 0)
and have adjusted the at91_tc_read/write routines to the proper offset for this channel (2*0x40). I can see the counter registers changing and everything seems to be fine. However, I can't get any signal out on the pin.

Is there anything else that has to be done to get the signal out on the pin? Do I have to tell somehow that this pin is in the out direction or something similar?

Thanks,

--
Pedro

How do you set up the CMR? I set it up as:
Code:
        at91_tc_write(AT91_TC_CMR,
                      AT91_TC_TIMER_CLOCK5 | /* slow clock, 32 kHz */
                      AT91_TC_WAVE | /* waveform mode */
                      AT91_TC_WAVESEL_UP_AUTO |
                      AT91_TC_EEVTEDG_NONE | /* must be disabled for TIOB
                                              * output */
                      AT91_TC_WAVESEL_UP | /* count up and wrap back to
                                            * zero */
                      AT91_TC_CPCTRG |
                      AT91_TC_ACPA_SET |
                      AT91_TC_ACPC_CLEAR
                );

Could you show your code?


Top
 Profile  
 
 Post subject: Re: Problems using TC on 9260 (for PWM-like generation) [SOLVED]
PostPosted: Fri Mar 11, 2011 12:11 pm 
Offline

Joined: Sat Jun 13, 2009 5:50 pm
Posts: 43
Hi,

I think we didn't configure the AT91_TC_CMR register correctly. Take a breif look the at91sam9260's datasheet and I modified the source bellow:

#define TCCLKS(val) ((val) << 0)
#define CLKI(val) ((val) << 3)
#define BURST(val) ((val) << 4)
#define CPCSTOP(val) ((val) << 6)
#define CPCDIS(val) ((val) << 7)
#define EEVTEDG(val) ((val) << 8)
#define EEVT(val) ((val) << 10)
#define ENETRG(val) ((val) << 12)
#define WAVSEL(val) ((val) << 13)
#define WAVE(val) ((val) << 15)
#define ACPA(val) ((val) << 16)
#define ACPC(val) ((val) << 18)
#define AEEVT(val) ((val) << 20)
#define ASWTRG(val) ((val) << 22)
#define BCPB(val) ((val) << 24)
#define BCPC(val) ((val) << 26)
#define BEEVT(val) ((val) << 28)
#define BSWTRG(val) ((val) << 30)

at91_tc_write(AT91_TC_CMR, // Waveform Mode (datasheet page 535/788)
TCCLKS(4) | // TIMER_CLOCK5 (SLCK)
CLKI(0) | // Rising edge clock
BURST(0) | // The clock is not gated by an external signal
CPCSTOP(0) | // Counter clock is not stopped when counter reaches RC
CPCDIS(0) | // Counter clock is not disabled when counter reaches RC
EEVTEDG(0) | // External Event Edge Selection = none
EEVT(1) | // Signal selected as external event = XC0
ENETRG(0) | // The external event has no effect on the counter and its clock
WAVSEL(2) | // UP mode with automatic trigger on RC Compare
WAVE(1) | // Waveform Mode is enabled
ACPA(1) | // RA Compare Effect on TIOA = set
ACPC(2) | // RC Compare Effect on TIOA = clear
AEEVT(0) | // External Event Effect on TIOA = none
ASWTRG(2) | // Software Trigger Effect on TIOA = clear
BCPB(1) | // RB Compare Effect on TIOB = set
BCPC(2) | // RC Compare Effect on TIOB = clear
BEEVT(0) | // External Event Effect on TIOB = none
BSWTRG(2)); // Software Trigger Effect on TIOB = clear

And it works fine.

Best regards.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC + 1 hour [ DST ]


Who is online

Users browsing this forum: No registered users and 12 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: