Using Atmel SAM Devices - Page 1
Forum section: electronics / general

author: BocaDev
author_rank: Contributor
timestamp: September 22, 2018, 06:42:54 pm
content: I have a few basic questions about Atmel SAM devices.Is it better to work with ASF and forget the GUI interface START? Or perhaps is it the other way around?Also is it possible to switch between one and the other during development? I'm not finding a way to do it, but I may not be doing something correctly.For example, I'm working on the SAMC21 and I find that setting the clocks in START to be pretty straight forward and all the oscillators combinations have been working as expected. I finally settled on using the external 32KHz oscillator running as the ref. into the PLL running at 24MHz. Works great!Then I moved onto the START ADC (async) example and found the EOC interrupt function was completely empty for retrieving conversion results. Not very helpful. I even found a post on the Atmel community board about this problem, but after 4 years since that post, the START ADC example has never been corrected. Is this a common problem with START. It would be nice if they had a link on each configuration page to report errors. What is the best way to report START page errors?So I then thought I would try my hand at using ASF. After several days of kicking the dog in frustration, I found it to be very convoluted.Is it me or are other Atmel SAM sport-fans users having the same experience? So what's the best way to get these devices setup and running so one can get on with the programming in hand? I'm beginning to think the best path is to program these chips during startup is at the register level (OMG).Thank you for any inputs and suggestions.

author: ataradov
author_rank: Super Contributor
timestamp: September 22, 2018, 08:07:24 pm
content: What to use is a matter of personal preference. You already studied both frameworks to a certain extent - pick the one you like more. There are incremental changes and bug fixes over time, but don't just sit and expect one or the other will get much better over time.It is impossible to switch sides mid-development. You have to pick one or the other.Start is probably a better way to go long term, since even now there is no ASF port for some newer devices.It is not hard at all to use the device on a register level, and that's what I personally do. I have a number of simple starter project that you can use herehttps://github.com/ataradov/mcu-starter-projects

author: BocaDev
author_rank: Contributor
timestamp: September 22, 2018, 11:06:17 pm
content: QuoteThanks ataradov,I'll go look into your starter project. Probably just what I need to get beyond the chip setup phase of development.

author: ataradov
author_rank: Super Contributor
timestamp: September 22, 2018, 11:10:19 pm
content: Quote from: BocaDev on September 22, 2018, 11:06:17 pmThere are also lots of other projects there that use Atmel SAM parts. There is probably nothing for C21 specifically, since I have not used this part a lot, but all devices are very close in spirit can the code is reasonably easy to port.I also have lots of scattered samples for various peripherals, but they are not published anywhere. But if you get stuck on something - just ask, I may have an answer.

author: BocaDev
author_rank: Contributor
timestamp: September 24, 2018, 03:15:03 pm
content: ataradov,Where I am coming to a stop is trying to get the ADC to work in async. I configured it using START however I see nothing within the results register when I have a breakpoint on the callback. Results register is zero.Is there any other working examples available for using the ADC in async that I may use as a guide? Hopefully without START or ASF.Thanks

author: ataradov
author_rank: Super Contributor
timestamp: September 24, 2018, 04:10:27 pm
content: Here is an example. I re-wrote it to be asynchronous from a synchronous implementation without testing, but it should work. This example assumes that you initiate every single conversion. If you want a free-running mode, then you will have to set FREERUN bit and initiate the first conversion in the adc_init() function.Let me know if this does not work and I will test it.Code:HAL_GPIO_PIN(ADC, A, 2)//-----------------------------------------------------------------------------void adc_init(void){HAL_GPIO_ADC_in();HAL_GPIO_ADC_pmuxen(HAL_GPIO_PMUX_B);MCLK->APBCMASK.reg |= MCLK_APBCMASK_ADC0;GCLK->PCHCTRL.reg = GCLK_PCHCTRL_GEN(0) | GCLK_PCHCTRL_CHEN;while (0 == (GCLK->PCHCTRL.reg & GCLK_PCHCTRL_CHEN));ADC0->CTRLA.reg = ADC_CTRLA_SWRST;while (ADC0->CTRLA.reg & ADC_CTRLA_SWRST);ADC0->REFCTRL.reg = ADC_REFCTRL_REFSEL_INTVCC2 | ADC_REFCTRL_REFCOMP;ADC0->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV32;ADC0->CTRLC.reg = ADC_CTRLC_RESSEL_16BIT;ADC0->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_128;ADC0->INPUTCTRL.reg = ADC_INPUTCTRL_MUXPOS_AIN0 | ADC_INPUTCTRL_MUXNEG(0x18/*GND*/);// ADC0->CALIB.reg = ADC_CALIB_BIAS_CAL(NVM_READ_CAL(ADC_BIASCAL)) |// ADC_CALIB_LINEARITY_CAL(NVM_READ_CAL(ADC_LINEARITY));ADC0->INTENSET.reg = ADC_INTENSET_RESRDY;NVIC_EnableIRQ(ADC0_IRQn);ADC0->CTRLA.reg = ADC_CTRLA_ENABLE;}//-----------------------------------------------------------------------------int adc_read(void){ADC0->SWTRIG.reg = ADC_SWTRIG_START;}//-----------------------------------------------------------------------------void irq_handler_adc0(void){int data = ADC0->RESULT.reg;// TODO: use data}

author: BocaDev
author_rank: Contributor
timestamp: September 24, 2018, 06:32:16 pm
content: Thanks ataradov, I will give this a try today or tomorrow and let you know how I made out.Alan

author: BocaDev
author_rank: Contributor
timestamp: September 24, 2018, 07:49:47 pm
content: ataradovI added the ADC example you provided and I am not having any results. My program is:Code:#include <stdlib.h>#include <stdint.h>#include <stdbool.h>#include <string.h>#include "samc21.h"#include "hal_gpio.h"#define_nop()asm("nop")#defineF_CPU24000000HAL_GPIO_PIN(LED, A, 15)HAL_GPIO_PIN(BUTTON, A, 28)HAL_GPIO_PIN(UART_TX, A, 22)HAL_GPIO_PIN(UART_RX, A, 23)HAL_GPIO_PIN(ADC, A, 2)//-----------------------------------------------------------------------------void adc_init(void){HAL_GPIO_ADC_in();HAL_GPIO_ADC_pmuxen(HAL_GPIO_PMUX_B);MCLK->APBCMASK.reg |= MCLK_APBCMASK_ADC0;GCLK->PCHCTRL.reg = GCLK_PCHCTRL_GEN(0) | GCLK_PCHCTRL_CHEN;while (0 == (GCLK->PCHCTRL.reg & GCLK_PCHCTRL_CHEN));ADC0->CTRLA.reg = ADC_CTRLA_SWRST;while (ADC0->CTRLA.reg & ADC_CTRLA_SWRST);ADC0->REFCTRL.reg = ADC_REFCTRL_REFSEL_INTVCC2 | ADC_REFCTRL_REFCOMP;ADC0->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV32;ADC0->CTRLC.reg = ADC_CTRLC_RESSEL_16BIT;ADC0->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_128;ADC0->INPUTCTRL.reg = ADC_INPUTCTRL_MUXPOS_AIN0 | ADC_INPUTCTRL_MUXNEG(0x18/*GND*/);// ADC0->CALIB.reg = ADC_CALIB_BIAS_CAL(NVM_READ_CAL(ADC_BIASCAL)) |// ADC_CALIB_LINEARITY_CAL(NVM_READ_CAL(ADC_LINEARITY));ADC0->INTENSET.reg = ADC_INTENSET_RESRDY;NVIC_EnableIRQ(ADC0_IRQn);ADC0->CTRLA.reg = ADC_CTRLA_ENABLE;}//-----------------------------------------------------------------------------void adc_read(void){ADC0->SWTRIG.reg = ADC_SWTRIG_START;}//-----------------------------------------------------------------------------void irq_handler_adc0(void){data = ADC0->RESULT.reg;// TODO: use data}//----------------------------------------------------------------------------static void sys_int(void){// Set flash wait states to maximum for 24 MHz operationNVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_RWS(1) | NVMCTRL_CTRLB_MANW;// Switch to 48MHz clock and divide by 2OSCCTRL->OSC48MDIV.reg = OSCCTRL_OSC48MDIV_DIV(1);}//----------------------------------------------------------------------------int main(void){sys_int();adc_init();adc_read();while(1){}}I'm not receiving any interrupts. Should I have added a NVIC_EnableIRQ(ADC0_IRQn); at the end of adc_init?

author: ataradov
author_rank: Super Contributor
timestamp: September 24, 2018, 08:07:52 pm
content: You never call adc_read() in your code.Also, what startup files you are using? Mine or from ASF? The IRQ handler function name must match the one in the vector table.EDIT: I see that you do call adc_read(), missed it. Let me create a complete test project.

author: matseng
author_rank: Frequent Contributor
timestamp: September 24, 2018, 10:24:14 pm
content: I just want to say that thanks to Ataradovs SAM project collection at GitHub I could ignore both ASF and Start and do it the "proper" register-way instead.Well... Almost, I use the hal_gpio macros, but that's only half-cheating and actually make the code more readable.

author: ataradov
author_rank: Super Contributor
timestamp: September 24, 2018, 10:38:07 pm
content: Here is a complete example that uses ADC with interrupts and prints the results on a serial port. This was tested on a real board and works for me.

author: BocaDev
author_rank: Contributor
timestamp: September 25, 2018, 06:31:08 pm
content: Hi ataradov,I am having issues with setting breakpoints in main.c. In fact, I can not even start debugging and break at main. I can run the program and see the LED flashing and pressing the button causing the blink rate to change, but I am unable to set any breakpoints.Do I have something setup wrong?

author: ataradov
author_rank: Super Contributor
timestamp: September 25, 2018, 06:33:53 pm
content: Go into the project settings and under the compiler tab check that debugging level is set to maximum.

author: BocaDev
author_rank: Contributor
timestamp: September 25, 2018, 06:59:38 pm
content: That did it. It was set for none which explains the problem. Never had that issue before but I now know to look for this.Thanks,Alan

author: BocaDev
author_rank: Contributor
timestamp: September 25, 2018, 07:30:07 pm
content: Hi Alex,I see your first name is Alex and that you live in the silicon valley area, you should be working for Atmel in offering help to their customers.I imported your main program having the ADC code and a print out added as a bonus! It is just working fine and I really appreciate all the help you have provided me.I should be good now and able to get on with my main task, with the help of following your examples.Thanks again,Alan

author: ataradov
author_rank: Super Contributor
timestamp: September 25, 2018, 07:59:18 pm
content: Quote from: BocaDev on September 25, 2018, 07:30:07 pmI do. It says this much on my site linked from my profile here

author: BocaDev
author_rank: Contributor
timestamp: September 25, 2018, 08:19:06 pm
content: OK, I clicked on the Globe and found your sitehttps://taradov.com/, very nice!May I be bold and ask just what you do at Atmel?Alan

author: ataradov
author_rank: Super Contributor
timestamp: September 25, 2018, 08:20:08 pm
content: Quote from: BocaDev on September 25, 2018, 08:19:06 pmApplications engineering and customer support mostly.

author: BocaDev
author_rank: Contributor
timestamp: September 25, 2018, 08:44:58 pm
content: Well you have been good on the customer support area. I can attest to that.I like using your startup example you gave me to begin building on. How should I start a new project in Atmel Studio without Atmel adding in their startup code? Or should I start there and clear out their stuff, then add your framework? How to handle your library file, etc.

author: ataradov
author_rank: Super Contributor
timestamp: September 25, 2018, 08:48:17 pm
content: Quote from: BocaDev on September 25, 2018, 08:44:58 pmNo idea. I think there is an option to start with a clean project. But AS has a nasty habit of not putting header files along with the project. It tries to use header files from the packs, so if you archive the project, you won't get the whole thing.Quote from: BocaDev on September 25, 2018, 08:44:58 pmYou already have my projects. Just start with that. This is exactly why they exist - I got annoyed with how hard it is to start with a clean slate.

author: BocaDev
author_rank: Contributor
timestamp: September 26, 2018, 01:20:56 pm
content: I will use your framework.Thanks again for all your help Alex.

author: BocaDev
author_rank: Contributor
timestamp: September 26, 2018, 09:26:01 pm
content: AlexWhen you did the ADC testing, was that on the SAMC21 Xplained Pro board?That is what I am testing with here and when I ground ADC0 input, I'm not getting a readings of 0. This is on the analog header, pin labeled A0 (PB09).Alan

author: ataradov
author_rank: Super Contributor
timestamp: September 26, 2018, 09:35:14 pm
content: Yes, I was testing it on C21 Xpro.If you have a different board, then you need to adjust the pins accordingly. The code is written to read the pin PA02 (AIN).You would need to change HAL_GPIO_PIN(ADC... and ADC0->INPUTCTRL.reg assignment. Everything else should be the same.

author: BocaDev
author_rank: Contributor
timestamp: September 27, 2018, 05:24:44 pm
content: I got it working now.I was grounding all of the A/D input on the A/D connector while taking readings, however the channel you selected in your test code was on an A/D channel over on the D/A output connector. That caught me off-guard!Thanks,Alan

author: ataradov
author_rank: Super Contributor
timestamp: September 27, 2018, 05:35:10 pm
content: What board are you using?

author: BocaDev
author_rank: Contributor
timestamp: September 28, 2018, 02:36:44 pm
content: I am using the Atmel SMART SAMC21 Xplained pro board. If you look at the top left of the picture below, the connector block with 6 female connection are labeled A0, A1, A2, A3, A4, A5 for the A/D connections. I had tried grounding all 6 inputs while looking at the serial output on a terminal to observe a 0x0000 reading. Non of these pins were changing the output.After investigation, my board has an additional connector (not shown in the picture) mounted next to the ADC connector labeled DAC-OUT. That is where I found the PA02 signal your code had selected as the ADC channel. The C21 Xplained Pro user guide (08/2016) on page 5 does have the board picture which shows the DAC-OUT connector. I believe Atmel was trying to accommodate the Arduino shields, however the 6 Arduino A/D lines are not mapped as 1:1. That is, A0 on a Arduino board is not mapped to AD0 on the SAMC21 board.My next goal is to scan 6 channel inputs continuously and for the ADC results to be quickly stored within memory via DMA. This is my next challenge to see if I can get that up and running. Any words of wisdom here would be greatly appreciated.Thanks,Alan

author: ataradov
author_rank: Super Contributor
timestamp: September 28, 2018, 04:17:17 pm
content: Ok, I see. I basically ignore the Arduino connectors.All my code uses signals available on connectors EXT1-3. How well that maps to Arduino I don't know.Do a 6 channel configuration and read the results manually first. Then add the DMA. Both things on their own are relatively simple. But debugging both at the same time may be hard.

author: BocaDev
author_rank: Contributor
timestamp: September 28, 2018, 05:37:09 pm
content: Yes that is what I am going to do. I'll build a resistor network feeding each A/D channel a different voltage. Next I'll run a slow manual scan outputting each channel onto the terminal to prove the channel mux is working. Then, if I need DMA speed, I'll step into that task. Should be interesting work.Thanks for your time Alex, you have done a great job!Alan