TC and the SAM4S Xplained Pro example

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've been working on a small proof-of-concept piece of test equipment based on the SAM4S Xplained Pro.  One function I've been asked to implement, and have not yet been able to, is the following:

 

We are making a "sniffer" to see if a certain protocol bus has data running on it or not.  The bus will have bursts of data on it, which I try to count.  The original code I wrote used the input pin (PA0) as an I/O pin, with a counter on interrupt on the rising edge.  This proved to be too slow for the signal, which at the fastest is about 2.5MHz (the distance between rising edges during transmission can go as low as ~400ns.), and the interrupt began to miss rising edges at about 10us (if I remember correctly, might have been 1us, but it definitely failed at 400ns).  So I thought I'd let a TC do the work in hardware. I tried defining the pin as TIOA0, which can, as far as I understand, be used as the input clock to a timer counter.  I figured that this would be the easiest way to implement what I want - define the pin as the input, start the timer, run it for 1 second (using systick as my second counter), and read the TC count value as the number of rising edges.

 

Needless to say, this didn't work.  That's why I'm here.  I tried some other methods, including suggestions from Atmel's support, who kept pointing me to the sample code described with AT07898.  I tried to implement that as well, and this, too, failed.  However, I think my original idea is actually what I'm looking for, as the example code is not working as an event counter but as a frequency measurement.

 

    sysclk_enable_peripheral_clock(ID_TC1); // enable clocking to the device.
    ioport_set_pin_mode(PIO_PA0B_TIOA0, IOPORT_MODE_MUX_B); // make the pin TIOA0
    ioport_disable_pin(PIO_PA0B_TIOA0);  // and not PA0
    tc_init(TC1, 1, TC_CMR_TCCLKS_XC1); // enable channel 1 on timer 1.
    tc_set_block_mode(TC1, TC_BMR_TC1XC1S_TIOA0); // use TIOA0 as input clock to the 
    tc_start(TC1, 1);    waiter = st;  // st is volatile systick counter 

    while ((st-waiter) < 200000) // 1 second
        ;
    tc_stop(TC1, 1);
    wordcount = tc_read_cv(TC1, 1);

 

    What am I missing here?  wordcount is always coming out as 0.

 

 

This topic has a solution.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've solved part of the issue.  The timer/counter code works now, using an internal clock, when I do this...

 

    sysclk_enable_peripheral_clock(ID_TC1); // !!!!!

    tc_init(TC0, 1, TC_CMR_TCCLKS_TIMER_CLOCK3); // use internal clock just to see...
    tc_start(TC0, 1);

    waiter = st;
    while ((st-waiter) < 200000) // 1 second
        ;
    tc_stop(TC0, 1);
    wordcount = tc_read_cv(TC0, 1);

 

However, when I try to use an external clock (and one which I have verified is coming in, fits the timing requirements, etc...) nothing.

 

The only difference is these four lines at the beginning, and a call to set the BMR in the middle.  

 

    sysclk_enable_peripheral_clock(ID_TC1); // !!!!!
    sysclk_enable_peripheral_clock(ID_PIOA); // 

    ioport_set_pin_mode(PIO_PA0B_TIOA0, IOPORT_MODE_MUX_B);
    ioport_disable_pin(PIO_PA0B_TIOA0);

    sysclk_enable_peripheral_clock(ID_TC1); // !!!!!

    tc_init(TC0, 1, TC_CMR_TCCLKS_XC1); // use external clock
    tc_set_block_mode(TC0, TC_BMR_TC1XC1S_TIOA0);

    tc_start(TC0, 1);

    waiter = st;
    while ((st-waiter) < 200000) // 1 second
        ;
    tc_stop(TC0, 1);
    wordcount = tc_read_cv(TC0, 1);

 

This does not work, and returns 0.  Any takers?

 

Thanks, Steve

 

 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As it turned out, PA0 as TIOA0 is not a good choice for external clock.  Moving it to PA29 and selecting it as the external clock directly worked.