Author Topic: Atmel SAM D example config (no ASF)  (Read 9445 times)

0 Members and 2 Guests are viewing this topic.

Offline Dragon88Topic starter

  • Regular Contributor
  • *
  • Posts: 88
Atmel SAM D example config (no ASF)
« on: September 03, 2015, 01:35:26 am »
Hi

I have some SAM D10C devices (not the Xplained board, just bare chips) that I am working with. I have programmed one using the example ASF blink project. That works fine. I have modified the example to do various things and that all works fine too. The problem is that ASF creates a real mess of files and includes to hide all of the configuration. I don't want that. I want to know the entire configuration process myself, code it myself, etc. I have tried to strip away the unnecessary junk that ASF creates, but I think a better solution is to start from scratch. A non-ASF example of configuring a SAM chip would be helpful.

Anyone have a link to such an example?

Or does "everyone" use the toolchain? I know the ARM world is very different from AVRs, but 5 lines of code to configure a pin as an output in RIDICULOUS. Three to five include files to set up the clock is RIDICULOUS.  And so is 20% of RAM being occupied just to blink an LED. :palm:

Thanks
 

Offline retrolefty

  • Super Contributor
  • ***
  • Posts: 1648
  • Country: us
  • measurement changes behavior
Re: Atmel SAM D example config (no ASF)
« Reply #1 on: September 03, 2015, 05:31:29 am »
Hi

I have some SAM D10C devices (not the Xplained board, just bare chips) that I am working with. I have programmed one using the example ASF blink project. That works fine. I have modified the example to do various things and that all works fine too. The problem is that ASF creates a real mess of files and includes to hide all of the configuration. I don't want that. I want to know the entire configuration process myself, code it myself, etc. I have tried to strip away the unnecessary junk that ASF creates, but I think a better solution is to start from scratch. A non-ASF example of configuring a SAM chip would be helpful.

Anyone have a link to such an example?

Or does "everyone" use the toolchain? I know the ARM world is very different from AVRs, but 5 lines of code to configure a pin as an output in RIDICULOUS. Three to five include files to set up the clock is RIDICULOUS.  And so is 20% of RAM being occupied just to blink an LED. :palm:

Thanks

 I'm sure the ARM platform is what and where industry is going for many good reasons, but for this hardware side hobbyist I will stay with the AVR 8 bit family for my projects.
« Last Edit: September 03, 2015, 05:36:02 am by retrolefty »
 

Offline senso

  • Frequent Contributor
  • **
  • Posts: 951
  • Country: pt
    • My AVR tutorials
Re: Atmel SAM D example config (no ASF)
« Reply #2 on: September 03, 2015, 11:23:03 am »
The RAM usage is due to the stack/heap allocation, ARM is stupid in that regard..
I have been trying to use a SAMR21, and the datasheet is crap, the documentation is a disgrace, ASF is a mismatch of libs, no documentation whatsoever, just doxygen lists of the .h files, cool, what does this function does?
Try it, throw parameters into that, see how it barfs..
 

Offline Bassman59

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: Atmel SAM D example config (no ASF)
« Reply #3 on: September 03, 2015, 09:18:52 pm »
The RAM usage is due to the stack/heap allocation, ARM is stupid in that regard..
I have been trying to use a SAMR21, and the datasheet is crap, the documentation is a disgrace, ASF is a mismatch of libs, no documentation whatsoever, just doxygen lists of the .h files, cool, what does this function does?
Try it, throw parameters into that, see how it barfs..

For shits and grins, you should submit tech-support requests.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4315
  • Country: us
Re: Atmel SAM D example config (no ASF)
« Reply #4 on: September 03, 2015, 10:42:09 pm »
I've been gradually moving the SAMD10 Blink example to a non-ASF form, and adding Arduino-like functionality (say what you want about Arduino, but implementing the "core" is a good way to learn a bunch of stuff about a new chip family.)

I've got clock_init() replaced, pinMode(), digitalWrite(), Polled UART, millis/micros/delay/etc (using the RTC)
A program that uses them all is about 1.5k.  Which is pretty good, since the original was over 2k to do just the blink.
There are some useful threads over in the SAMD subsection of AVRFreaks.

You don't actually have to do much to get an LED blinking; setting up the core clock is about it (and you COULD default to a lot more than I do here...)

Code: [Select]
void system_clock_init()
{
#ifdef USEPLL
#define EXTCLK_DIV ((EXTCLK_FREQ/(2*F_INTERM)) - 1)  // Slightly complicated
    //Enable the 8MHz oscillator input from SAMD10 XMini
    SYSCTRL->XOSC.reg = (SYSCTRL_XOSC_ENABLE);
   
    //Wait for the crystal oscillator to start up
    while((SYSCTRL->PCLKSR.reg & (SYSCTRL_PCLKSR_XOSCRDY)) == 0);
       
    //Set flash wait state to 1, which we need to do at 48MHz
    REG_NVMCTRL_CTRLB |= (NVMCTRL_CTRLB_RWS(1));
   
    //Configure the DPLL

    SYSCTRL->DPLLCTRLA.reg = 0;    // Defaults!

    /*
     * The output of DPLL is supposed to be between 48MHz and 96MHz.
     * By setting the PLL output to 2*F_CPU, we have easy acess to
     * most of the "interesting" frequencies between 24MHz and 48MHz
     * Lower F_CPU can be obtained by increasing the GCLK0 divisor.
     */
    SYSCTRL->DPLLRATIO.reg = SYSCTRL_DPLLRATIO_LDR(2*F_CPU/F_INTERM);
    SYSCTRL->DPLLCTRLB.reg = SYSCTRL_DPLLCTRLB_DIV(EXTCLK_DIV) | /* Refclock divider */
        SYSCTRL_DPLLCTRLB_REFCLK(SYSTEM_CLOCK_SOURCE_DPLL_REFERENCE_CLOCK_XOSC);
    SYSCTRL->DPLLCTRLA.reg = SYSCTRL_DPLLCTRLA_ENABLE;

    while(!(SYSCTRL->DPLLSTATUS.reg & (SYSCTRL_DPLLSTATUS_CLKRDY | SYSCTRL_DPLLSTATUS_LOCK)) ==
                                      (SYSCTRL_DPLLSTATUS_CLKRDY | SYSCTRL_DPLLSTATUS_LOCK));
   
    //For generic clock generator 0, select the DPLL Clock as input, divide by 2
    GCLK->GENDIV.reg = ((2 << GCLK_GENDIV_DIV_Pos) | (0 << GCLK_GENDIV_ID_Pos));
    GCLK->GENCTRL.reg = ((0 << GCLK_GENCTRL_ID_Pos) | (GCLK_SOURCE_FDPLL << GCLK_GENCTRL_SRC_Pos)| (GCLK_GENCTRL_GENEN));
    GCLK->CLKCTRL.reg = ((GCLK_CLKCTRL_GEN_GCLK0) | (GCLK_CLKCTRL_CLKEN)) ;
#endif /* USEPLL */
}

/*
 * Map Arduino pin numbers to hardware specific values.
 * In the case of the D10, all the pins bits in a single GPIO port
 * so it's efficient to map to bit numbers (which an ARM can easily
 * convert to a bitmask, since it has a barrel shifter.)
 * -1 means the digital pin doesn't exist.
 */

 const int8_t digital_pin_to_pinno[] = {
  11, 10, 16, 17,
  27, 25, 30, 31,
  -1, -1, 23, 22,
  24,  9, 02, 03,
  04, 05, 06, 07,
  15, 14
};

/*
 * digitalWrite(pinno, level)
 * This is logically similar to the ASF function port_pin_set_output_level(),
 * but uses a different mechanism for mapping the "pinno" to the port/bit.
 */

void digitalWrite(uint8_t pinno, uint8_t level)
{
  PortGroup *const port_base = &(PORT->Group[0]); /* port_get_group_from_gpio_pin(1); */ // any pin will work.
  uint32_t pin_mask  = (1UL << (digital_pin_to_pinno[pinno]));
 
  if (level) {
    port_base->OUTSET.reg = pin_mask;
  } else {
    port_base->OUTCLR.reg = pin_mask;
  }
}

void pinMode(uint8_t pinno, uint8_t direction)
{
    PortGroup *const port_base = &(PORT->Group[0]); /* port_get_group_from_gpio_pin(1); */ // any pin will work.
    uint32_t pin_mask  = (1UL << (digital_pin_to_pinno[pinno]));
   
    if (direction == OUTPUT) {
        port_base->DIRSET.reg = pin_mask;
        } else {
        port_base->DIRCLR.reg = pin_mask;
    }
}
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4315
  • Country: us
Re: Atmel SAM D example config (no ASF)
« Reply #5 on: September 03, 2015, 11:00:10 pm »
Quote
The RAM usage is due to the stack/heap allocation, ARM is stupid in that regard..
Most of it is just the stack, which shows up explicitly in BSS in the ARM compiles, rather than just have the SP set to the "end of ram" by the init code.   I wouldn't really call this "stupid"; it's just different.  There is also 40 bytes of "clock  configuration instance", in case your code needs to know how the clock is configured because you forgot, or something...
 

Offline Dragon88Topic starter

  • Regular Contributor
  • *
  • Posts: 88
Re: Atmel SAM D example config (no ASF)
« Reply #6 on: September 03, 2015, 11:36:55 pm »
I've been gradually moving the SAMD10 Blink example to a non-ASF form

Excellent. I will take a look at this. Thanks.

 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4315
  • Country: us
Re: Atmel SAM D example config (no ASF)
« Reply #7 on: September 04, 2015, 12:23:47 am »
I've uploaded the whole thing to here: https://github.com/WestfW/SAMD10-experiments
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4315
  • Country: us
Re: Atmel SAM D example config (no ASF)
« Reply #8 on: September 04, 2015, 05:00:27 am »
(hmm.  Note that my clock initialization code uses the 8MHz Xin input provided by the Xplained board, but PROBABLY not present on a bare-chip based board.)
 

Offline Bassman59

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: Atmel SAM D example config (no ASF)
« Reply #9 on: September 04, 2015, 05:00:25 pm »
I've been gradually moving the SAMD10 Blink example to a non-ASF form

I've been stripping ASF down to the bare minimum for the SAM3 devices. Basically, it's all about shitcanning everything but the "drivers," which are pretty much what I'd write myself for doing the low-level peripheral access. I've removed all of the device-abstraction cruft from the drivers, so it only applies to the SAM3 devices and is straightforward. Some of the "services" have been retained, too, since they're useful (a lot are not!), but again layers of abstraction have been removed.

It's a work in progress. I suppose I'll post it somewhere when it's all complete.
 

Offline Dragon88Topic starter

  • Regular Contributor
  • *
  • Posts: 88
Re: Atmel SAM D example config (no ASF)
« Reply #10 on: September 04, 2015, 09:31:22 pm »
(hmm.  Note that my clock initialization code uses the 8MHz Xin input provided by the Xplained board, but PROBABLY not present on a bare-chip based board.)

Setting up external clocks is quite easy, even on a bare chip. As much as I dislike all of the garbage ASF creates, conf_clocks.h is a good file. Just go in and enable what you want. All you need to use the DFLL at 48MHz for the main clock is a 32.768 kHz crystal and load capacitors connected to A08 and A09. Here are the modifications needed in conf_clocks.h to use the DFLL if you are interested:

Code: [Select]
/* System clock bus configuration */
#  define CONF_CLOCK_CPU_CLOCK_FAILURE_DETECT     false
#  define CONF_CLOCK_FLASH_WAIT_STATES            1
#  define CONF_CLOCK_CPU_DIVIDER                  SYSTEM_MAIN_CLOCK_DIV_1
#  define CONF_CLOCK_APBA_DIVIDER                 SYSTEM_MAIN_CLOCK_DIV_1
#  define CONF_CLOCK_APBB_DIVIDER                 SYSTEM_MAIN_CLOCK_DIV_1

...

/* SYSTEM_CLOCK_SOURCE_XOSC32K configuration - External 32KHz crystal/clock oscillator */
#  define CONF_CLOCK_XOSC32K_ENABLE               true
#  define CONF_CLOCK_XOSC32K_EXTERNAL_CRYSTAL     SYSTEM_CLOCK_EXTERNAL_CRYSTAL
#  define CONF_CLOCK_XOSC32K_STARTUP_TIME         SYSTEM_XOSC32K_STARTUP_65536
#  define CONF_CLOCK_XOSC32K_AUTO_AMPLITUDE_CONTROL  false
#  define CONF_CLOCK_XOSC32K_ENABLE_1KHZ_OUPUT    false
#  define CONF_CLOCK_XOSC32K_ENABLE_32KHZ_OUTPUT  true
#  define CONF_CLOCK_XOSC32K_ON_DEMAND            false
#  define CONF_CLOCK_XOSC32K_RUN_IN_STANDBY       true

...

/* SYSTEM_CLOCK_SOURCE_DFLL configuration - Digital Frequency Locked Loop */
#  define CONF_CLOCK_DFLL_ENABLE                  true
#  define CONF_CLOCK_DFLL_LOOP_MODE               SYSTEM_CLOCK_DFLL_LOOP_MODE_CLOSED
#  define CONF_CLOCK_DFLL_ON_DEMAND               true

...

/* DFLL closed loop mode configuration */
#  define CONF_CLOCK_DFLL_SOURCE_GCLK_GENERATOR   GCLK_GENERATOR_1
#  define CONF_CLOCK_DFLL_MULTIPLY_FACTOR         (48000000/32768)
#  define CONF_CLOCK_DFLL_QUICK_LOCK              true
#  define CONF_CLOCK_DFLL_TRACK_AFTER_FINE_LOCK   true
#  define CONF_CLOCK_DFLL_KEEP_LOCK_ON_WAKEUP     true
#  define CONF_CLOCK_DFLL_ENABLE_CHILL_CYCLE      true
#  define CONF_CLOCK_DFLL_MAX_COARSE_STEP_SIZE    (0x1f / 8)
#  define CONF_CLOCK_DFLL_MAX_FINE_STEP_SIZE      (0xff / 8)

...

/* Configure GCLK generator 0 (Main Clock) */
#  define CONF_CLOCK_GCLK_0_ENABLE                true
#  define CONF_CLOCK_GCLK_0_RUN_IN_STANDBY        true
#  define CONF_CLOCK_GCLK_0_CLOCK_SOURCE          SYSTEM_CLOCK_SOURCE_DFLL
#  define CONF_CLOCK_GCLK_0_PRESCALER             1
#  define CONF_CLOCK_GCLK_0_OUTPUT_ENABLE         false

/* Configure GCLK generator 1 */
#  define CONF_CLOCK_GCLK_1_ENABLE                true
#  define CONF_CLOCK_GCLK_1_RUN_IN_STANDBY        false
#  define CONF_CLOCK_GCLK_1_CLOCK_SOURCE          SYSTEM_CLOCK_SOURCE_XOSC32K
#  define CONF_CLOCK_GCLK_1_PRESCALER             1
#  define CONF_CLOCK_GCLK_1_OUTPUT_ENABLE         true
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4315
  • Country: us
Re: Atmel SAM D example config (no ASF)
« Reply #11 on: September 05, 2015, 12:38:13 am »
Quote
conf_clocks.h is a good file.
Meh;  there are examples for running the DFLL from a 32kHz crystal, and the config file is "almost there" to start with.   But I didn't find it very intuitive to (say) configure a 32MHz main clock based on the 8MHz Xin input (the Xplained mini has neither a crystal, not a place to mount one.)  And the LED_TOGGLE example will shrink by over 800 bytes of code just by getting rid of the ASF clock functions.  I consider 800 bytes a relatively significant chunk on a processor family with 16k max...  (OTOH, it's more intuitive now that I've gotten more familiar with how the clocking works.)

It seems to be the ASF *_init() functions that are most bloated by unnecessary abstraction.  You pass them a datastructure containing all the information about all the sub-features that you are NOT interested in, and then it picks its way through a decision tree that is also capable of handling all of the sub-features.  And it's a shame, because (as I've complained before, over in the one-dollar STM32 thread) in theory you could pass a set of constants to an inline function, and have the compiler remove most of that code at compile time.  Or maybe a C++ template could do something similar (C++ being significantly better at handling data structures with a lot of user-specifiable fields with default values.)  But that's not the way the code is written, and not the way it is documented to be used.
 

Offline Dragon88Topic starter

  • Regular Contributor
  • *
  • Posts: 88
Re: Atmel SAM D example config (no ASF)
« Reply #12 on: September 05, 2015, 01:11:37 am »
It's a good file in that it shows examples of each clock configuration. Certainly the many bytes of clock setup files need to be stripped out once you settle on one. Though I'm sure Atmel just wants you to use ASF, and if you run out of flash, upgrade to a more expensive chip...

To be honest though, I'm playing around with a STM32 and CooCox IDE, and it's 100x less bloated than Atmel Studio. It will be a struggle now to get back in there and slog through ASF garbage...
 

Offline Dragon88Topic starter

  • Regular Contributor
  • *
  • Posts: 88
Re: Atmel SAM D example config (no ASF)
« Reply #13 on: September 05, 2015, 01:33:02 pm »
Against my better judgment I'm back at it.

I have gotten program memory usage down, but the RAM usage is still very high for a blinky program. What's up with this? Is it "normal" for this ARM device?

Code: [Select]
Program Memory Usage : 2236 bytes   13.6 % Full
Data Memory Usage : 1096 bytes   26.8 % Full
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4315
  • Country: us
Re: Atmel SAM D example config (no ASF)
« Reply #14 on: September 05, 2015, 04:38:22 pm »
It's the stack, which defaults to 1024 bytes (and which has been pointed out several times now.)
on an AVR, the stack pointer would be initialized to "the end of memory" without actually allocating any space to it.
On an ARM, you can theoretically detect when the stack and heap collide (or prevent this...)
The stack size can be changed in the linker script (look for STACK_SIZE) or by adding a magic gcc command to set linker symbols (
-Xlinker --defsym=__stack_size__=0x100 )

 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf