How do I just simply use a timer to count up to a number then start over?

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

I really appreciate the power of the timers in all what they can do with wave generation, pulse stuff, capture mechanics and output or event counting etc... But I feel a bit lost when I want the counter to just count to a number, generate an event, then start over. I've been at this for sometime scouring the manual and while it goes into great detail in all of the really advanced mechanics of a timer it's somewhat vague about just a very simple timer.

 

I'm using Atmel SAMD51J19 on an Adafruit Metro M4 board using a JTag programmer and bare metal programming. I'm trying to get TC0 (Basic Timer/Counter 0) to count up to 255 in 8-bit mode then start over and generate an event. I'm not using CMSIS and am using my own code instead.

 

I've selected a clock frequency of 1.768 KHz for TC0 in the GCLK and have selected it prescaled by 1024 in TC0 to just to try and get it to appear counting. The issue is it events never worked but I got it to work using interrupts however it blinks at a steady pace. I've tried changing the PRE to all different values and even the clock frequency to all different values even 120 MHz but the rate at which it blinks is steadily the same.

 

I don't even know what PRE is but I'm assuming from the data sheet it maybe has something to do with the reload value? Overall I'm pretty lost.

 

This is what I have so far, any help would be great:

 

  /*
   * ENABLE EVENTS
  */

  // Configure event channel 0 to be TC0 Overflow and to give an async output
  set32(EVSYS::CHANNEL::addr_32(0),
          EVSYS::CHANNEL::EVGEN(TC::EVGEN_TC0_OVF) |
          EVSYS::CHANNEL::TO_PATH_16(EVSYS::CHANNEL::PATH_ASYNCHRONOUS));

  // Setup GPIO Event User 0 to be connected to channel 0
  set8(EVSYS::USER::addr(GPIO::EVU_PORT_EV0_A), EVSYS::USER::CHANNEL(0));
  
  /*
   * SETUP PIN A2
   * A2 = LED Toggle from timer event
  */

  // Set A2 to be out
  set32(GPIO::PIN::ADDR_DIR_32 + BOARD::PORT_A0, GPIO::PIN::pinToBit(BOARD::PIN_A2));

  // Set A2 to be off
  set32(GPIO::PIN::ADDR_OUT_32 + BOARD::PORT_A0, 0);

  // Register pin A2 as a user to event user 0, signals will cause it to toggle
  set8(GPIO::EVCTRL::addr(0), GPIO::EVCTRL::PORTEIx | GPIO::EVCTRL::PIDx(BOARD::PIN_A2) | GPIO::EVCTRL::TO_EVACTx(GPIO::EVCTRL::EVACTx_TGL));
  
  /*
   * ENABLE EXTERNAL INTERRUPTS
   * (Couldn't get events to work)
  */

  // Enable External Interrupts
  set8(EIC::CTRLA::addr, EIC::CTRLA::ENABLE);

  // Wait until enabled
  while(get8(EIC::SYNCBUSY::addr) & EIC::SYNCBUSY::ENABLE > 0)
    continue;
  
  /*
   * ENABLE TIMER 0
   * Timer 0 runs on a 1.768 KHz clock
  */
  
  // Use in 8-bit mode and use timer clock (1.768 KHz)
  set32(TC::addr_tc0 + TC::CTRLA::offset1, 
          TC::CTRLA::B1_TO_MODE(TC::CTRLA::MODE_COUNT8));

  // Enable Event Output on Overflow
  // Doesn't work for some reason
  set16(TC::addr_tc0 + TC::EVCTRL::offset1,
        concat8to16(
          0,
          TC::EVCTRL::B2_OVFEO
        ));

  // Enable Overflow Interrupt
  // Because event output doesn't work
  set8(TC::addr_tc0 + TC::INTEN::offsetSet, TC::INTEN::OVF);

  // Enable Running in Debug
  set8(TC::addr_tc0 + TC::DBGCTRL::offset,
          TC::DBGCTRL::DBGRUN);

  // Set Per Register
  set8(TC::addr_tc0 + TC::PER::offset_8, TC::PER::PER(0));

  while(get8(TC::addr_tc0 + TC::SYNCBUSY::offset) & TC::SYNCBUSY::PER)
    continue;

  // Enable and scale down clock
  set32(TC::addr_tc0 + TC::CTRLA::offset1, 
          concat8to32(
            TC::CTRLA::B1_ENABLE,
            TC::CTRLA::B2_PRESCALER(TC::CTRLA::PRESC_GCLK_DIV1024)
          ));

  while(get8(TC::addr_tc0 + TC::SYNCBUSY::offset) & TC::SYNCBUSY::ENABLE)
    continue;

  // Start timer
  set8(TC::addr_tc0 + TC::CTRLB::offsetSet,
          TC::CTRLB::TO_CMD(TC::CTRLB::CMD_RETRIGGER));

  while(get8(TC::addr_tc0 + TC::SYNCBUSY::offset) & TC::SYNCBUSY::CTRLB)
    continue;
  
  /*
   * ENABLE MASTER INTERRUPTS
  */

  // Enable TC0 Overflow Interupt
  set8(SCS::NVIC::addrISER + SCS::NVIC::findIxRByte(TC::INT_TC0_OVF), SCS::NVIC::findIxRBitFlag(TC::INT_TC0_OVF));
  
  /////////////////////////////////////////
  
  extern "C" __attribute__ ((interrupt)) void TC0_Handler()
  {
    // Toggle A2
    set32(GPIO::PIN::ADDR_OUTTGL_32 + BOARD::PORT_A2, GPIO::PIN::pinToBit(BOARD::PIN_A2));

    // Clear Overflow Interrupt
    set8(TC::addr_tc0 + TC::INTEN::offsetFlag, TC::INTEN::OVF);
  }

 

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

Welcome to the forums.

 

I see form your other threads/posts you are quite new to all of this(as am I in many respects as well) so maybe a few suggestions.....

 

1) why are you so set on using 120Mhz for everything?  SLOW DOWN!

 

junebug12851 wrote:
I'm not using CMSIS and am using my own code instead.

2) This might be/is a bad idea based on the issues you are having.  Since you are using an Adafruit board maybe you should try using their example projects on their repository?

     I myself use AtmelSTART fo rthis stuff.  It's not the best solution, but it certainly helps and I can post the project here for others to dissect as needed.  IT also makes setup pretty simple as well.

 

Heres the link:

https://start.atmel.com

 

Jim

 

 

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

To answer your first question:

 

I'm designing a custom PCB board which will use this chip, the project goal is to interface with a retro device that runs at 1 MHz. I need to be as fast as possible beyond 1 MHz for complex tasks to finish out so that when the device gets the data it's looking for it will be there. Otherwise things break and don't work. 120MHz was a good candidate because it gets me 120 times faster than 1 MHz because the instructions I need to carry out may require rather complex decision making beforehand including syncing with external components or sensors which the retro device isn't going to know about or wait for. So in my case speed is really important, well that and a microcontroller capable of more complexity than many of the simpler ones. There's a specific reason why I chose this particular microcontroller out of the many thousands on the active market and after more than one hour of browsing through them.

 

With that said it takes me to the answer to your next question, I'm not interested in programming for a framework that runs on the device. I'm interested in programming on the device also called bare metal programming and I want that for a lot of reasons, speed and complex instructions are number one - you don't get that with frameworks by the inherit nature of the framework. This is why I don't use Adafruit's stuff. I literally wanted a board from anywhere online that had the chip I selected (SAMD51J20) and adafruit was the closest match to a custom fabrication option (SAMD51J19). If it weren't for it having the same chip, I would never have bought it because I'm generally not interested in adafruit boards.

 

Adafruit is sort of a weird arduino competitor and partner at the same time. They have their own line of boards like Arduino but their innovative and original to separate the two yet their boards are arduino compatible. Regardless Arduino (An absurdly dumbed down C++ embedded programming) and Adafruit (Python equivalent) are not my, excluding the fact that it shields me deeply from pretty much anything related to the chip it's also got so much going on under the hood it has no interest to me. My interest is working on the bare metal wires of the chip. Regardless this greatly pays off for many of the very speed oriented and often assembly oriented projects I'm working on.

 

Now with CMSIS I agree I should probably use CMSIS because it is bare metal programming just in a standardized way. The issue is the IDE I use is Segger Studio Embedded. It supports CMSIS but not really to the best, CMSIS is also apparently really complicated to set up and I'm extremely suprised at how theres little to no documentation on using it outside of a vague website. The SAMD51 specific CMSIS files are even more vague and Segger doesn't support officially SAMD51 only SAME51 - they're really close so I guess it's not the biggest problem.

 

The alternative is Atmel Studio which I'd love to try, it provides direct support for my chip and CMSIS all very well, but I can't get it to run at all. It can't debug whatsoever and often I run into various errors. ultimately I never got it to ever actually ork for me and I've found no help anywhere so I can't use it. This brings me back to Segger Studios and rolling out my own solution in Segegr studios.

 

I'm not familiar well with AtmelSTART but I know that Atmel Studio supports it out of the box and I know it's one of those frameworks that dumbs down the chip so everything is simpler and it takes on a lot more under the hood which has no interest to me at all. I'd be fine with CMSIS if I could ever get Atmel Studio to work right.

 

Also don't underestimate me too much, yes I'm very new to embedded programming. It's a totally new and exciting world for me to enter, but I've been programming on computers for a very long time so I know programming, c++, assembly programming etc... I just don't know anything about micro-controllers or embedded programming but I've made a lot of progress than when I first started posting on here by spending 8-20 hours daily practicing bare metal programming with the data sheet and various Atmel manuals.

 

Sorry for the long post but your questions needed more explanation than a simple one-liner. Also thank you very much for helping me out, I often find good help is rather scarce online.

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

junebug12851 wrote:
Also don't underestimate me too much,

Agreed!  By your response I humbly(and happily)stand corrected! smiley

 

junebug12851 wrote:
I'm not familiar well with AtmelSTART but I know that Atmel Studio supports it out of the box and I know it's one of those frameworks that dumbs down the chip

 

Well I will agree that START does add a lot to the programming that many find objectionable.  BUT for the purposes of getting your feet wet and proof of some of the concepts I still recommend it.  As I wrote I am quite the noob at ARM stuff, but hours of experimentation has yielded milestones using START.  I have also been trying my hand at direct 'bare metal' as well...but for the short future the bloat START creates is good enough for me.

 

junebug12851 wrote:
I've made a lot of progress than when I first started posting on here by spending 8-20 hours daily practicing bare metal programming with the data sheet and various Atmel manuals.

And kept your sanity?  Now I am impressed.

 

Back to START for a moment.  In some of your other threads you have asked about the Timer/counters, and the clocks etc. setups.  This is where START may help out as its a mostly Graphical userinterface.  This way you can see how things get connected based on your requirements.  It's sort of like looking under the hood so to speak.

 

junebug12851 wrote:
Sorry for the long post but your questions needed more explanation than a simple one-liner.

And I thank you on behalf of the community....too many times we get "PLEASE HELP ME!!" with NO explanation of what needs helping.

 

junebug12851 wrote:
Also thank you very much for helping me out, I often find good help is rather scarce online.

Don't think I've been much help, but if it gets someone else to pop in that can help then all the better.

 

junebug12851 wrote:
I'd be fine with CMSIS if I could ever get Atmel Studio to work right.

What are you having a problem with regarding Studio?

 

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

Thank you for your amazing response, as for Atmel Studio it shows "Failed to launch program. Error: Failed to set GDB Proxy". It seems to upload fine and can do everything else except for debugging which is very important. A few people have had this problem and it either went without any help or unresolved help. One person did find a solution which was to lower the speed of the adapter which I tried long ago and it didn't help plus Segger Studio worked out of the box without any extra configuration. I've literally even tried downloading the latest arm gnu toolchain and having Atmel Studio use that gdb proxy and flavor but it didn't work, same exact error. If I disable GDB proxy it says "Timed out waiting for initial response event" - 1 or 2 others have also had this issue and there was no help or support to fix it.

 

After the occasional back and forth with Atmel Studio I kept Segger because it worked right out of the box instantly and quickly. I just never got Atmel to work right.

 

And kept your sanity?  Now I am impressed.

If you call cussing at the thing and griping about it to my friends and nearly pulling my hair out keeping my sanity whenever i run into a problem. But I get through it and figure it out and it's often very rewarding when I get past a difficult obstacle. I'm determined to understand everything there is to know about this chip, all the ins and outs down to the assembly and wires and hope it carries over to newer ARM chips which I'm sure it does there seems to be many standards with ARM which is another reason I chose an ARM chip because I know the company and community behind ARM and it's been pretty big and major for a while.

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

You definitely want to figure out how to get the Vendor-supplied CMSIS files in there.

 

set32(EVSYS::CHANNEL::addr_32(0),
          EVSYS::CHANNEL::EVGEN(TC::EVGEN_TC0_OVF) |
          EVSYS::CHANNEL::TO_PATH_16(EVSYS::CHANNEL::PATH_ASYNCHRONOUS));

I mean, that's awful; not what anyone is used to seeing, and while I can figure our what it's supposed to do, and the namespace separation is an interesting idea, I have little faith that everything has been defined correctly, or implemented correctly.  And I have no interest whatsoever in digging into the code to check...

 

It's annoying that the Segger IDE doesn't have a package for the D51 :-(

 

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

It is but I've switched over to CMSIS and as suggested Atmel Start which, given how new I am to embedded programming I'm finding really helpful despite the horrid web page setup, performance, and efficiency which is expected of most Javascript based systems. It does do it's job and helps me really visualize a lot of information so I'm almost embarrassed to say that I'm using it for now (coming from someone who really just loves bare metal programming), still though I mostly stick to CMSIS after the initial Atmel Start Init line.

 

The way I switched over was to use Atmel Studio, yes the debugger doesn't work at all for me but everything else does so if I need a debugger I pull out Ozone which works really well. Sure I'd liek it all to be in the same IDE but Ozone is a great stand-alone debugger so it's a minimal inconvenience and allows me to use CMSIS and, at least for the immediate moment, Atmel Start.

 

The only thing I don't like is many of these IDE's and libraries/frameworks are based on C++98 or before which can give me annoying warnings or errors. That's the one thing I liked about Segger Studios, it worked just fine with the latest language version and really gave me that raw control I want at the cost of not the best support and very poor CMSIS support. What I wrote used "constexpr" and other features to minimize and simplify what was actually compiled and never really used #define at all, it produced amazingly optimized and amazingly clean code. CMSIS is a cluster of defines and i feel it's a garbled mess written in the late 90's especially the chip specific additions but it works for the time being and gets me on the same page as everyone else and ensures I'm mainly checking errors on my side and not both sides (as in the case of a custom solution)

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

The only thing I don't like is many of these IDE's and libraries/frameworks are based on C++98

I'm pretty sure that you can add "-std=C++17"  or whatever in the Project Configuration/Toolchain/AVRGNUC++ Compiler/Miscellaneous section of the project...

(I don't know if anything is broken, there.  In general, you can sneak in any gcc/g++ option...)

 

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

I'm not talking about compiler flags, I use the flags all the time to compile C++17 code down. What I'm talking about is the includes themselves regardless of compiler settings as in the code style they used when writing the include is something of the late 90's. I just feel it's incredibly messy and including that with my code makes me feel my code is now incredibly messy. But I'll use CMSIS because it gets me on the same page as everyone else.

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

I'm not talking about compiler flags [but] about is the includes themselves regardless of compiler settings as in the code style they used when writing the include is something of the late 90's.

Ah.  So you don't like most of the constants being preprocessor #defines rather than preferred more modern constructs (you mentioned constexpr, and used namespaces to good effect in your own code.)

 

I can see that.  On the other hand, it's a bit of a tradeoff - right now the same include files get used for C and Assembly Language as well as C++, where the preprocessor is somewhere between very useful and necessary.   There's a lot of AVR code that looks like:

#if defined (USART2)
  // initialize and deal with USART2, IFF it exists...
#endif

that will just break horribly if USART2 is an actual C/C++ object rather than a #define...

 

Microchip has had an interestingly different philosophy (from historical Atmel) WRT peripheral addresses.  Instead of

#define USART2 (*(USART_t *) 0x0840)

they'll have

#define UART2 UART2
extern volatile UART UART2 __attribute__((__sfr__));

With the actual addresses being defined at link time.  This can make it harder for the compiler to optimize some things (like the upper half address being shared by "many" peripherals), but helps allow them to distribute libraries in binary form.  I'm waiting to see how much of this is propagated to the AVR and SAM chips...