ATMEGA644 vrs SAM4S16B

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

I've been working with a few different AVR 8 bit MCU lately, and have found the support widespread and very helpful. Recently, I've created a breakout board with a SAM4S16B and have been trying my best at these ARM Cortex chips. I have written the following code in an attempt to merely get my bearings straight by testing basic functionality of the chip such as using the GPIO pins manually before branching off. I know that there are some scripts written that supposedly make controlling the registers directly unnecessary, but.. I'm trying to mess with them directly anyway for learning purposes and am unsure of why I cannot seem to enact any pin voltage changes. 0.o Does anyone have any pointers for me? What am I missing, doing wrong, or where are there any resources for learning about this?? The example projects for this chip don't seem to exist for C++ in Atmel Studio, or I'd use those to start with before asking you helpful, awesome people here..

/*
 * FINALMAYBE.cpp
 *
 * Created: 7/8/2014 3:43:26 PM
 *  Author: The Hammer
 */ 

#include "sam.h"

/**
 * \brief Application entry point.
 *
 * \return Unused (ANSI-C compatibility).
 */
int main(void)
{
    /* Initialize the SAM system */
    SystemInit();
	PIOA->PIO_WPMR |= (1<<0);				//WPEN bit
	PIOA->PIO_PDR = 0xFFFFFFFF;
	PIOA->PIO_OER = 0xFFFFFFFF;
	PIOA->PIO_PUDR = 0xFFFFFFFF;
	PIOA->PIO_PPDDR = 0xFFFFFFFF;
	PIOA->PIO_WPMR &= ~(1<<0);
	int ass = 1;
    while (1) 
	{
		//if (PIOA->PIOLOCKSR)
		//else if (ass==2)
		//{
			//PIOA->PIO_SODR |= (1<<1) | (1<<2);
			//PIOA->PIO_CODR |= (1<<2) | (1<<3);
			//PIOA->PIO_ODSR |= (1<<3);
			PIOA->PIO_CODR = 0xFFFFFFFF;
			//ass++;
		//}
        //TODO:: Please write your application code 
    }
}
This topic has a solution.
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Does anyone have any pointers for me? What am I missing, doing wrong,

Maybe you are doing it there (I'm too lazy to download the datasheet) but the usual difference between small 8 bit micros and big iron like AVR32 and ARM is that in the former all the peripherals like GPIO are enabled and ready to go at power on while in the big chips you norally have to mess with clock control registers to first enable a clock to the GPIO block before you can actually do anything with it.

Now maybe that's what WPMR is?? But if it is why do you turn it off after messing with the registers?

While I'm not a major fan of ASF I think the quickest way to learn what you need is to start an ASF GPIO example project then just burrow down through the layers of code until you reach the bit where it's actually setting the SFRs - then just lift that for your own code. As you'll find ASF is multi-layered and trying to dig down is "interesting".

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

This is a forum for AVR8 people.

A Google search for "PIOA sam4" uncovers, as the first hit, "Welcome to AT91SAM Community Discussions" www.at91.com

Most of the first page of hits seems to be "getting started" and "blinking LED" and such.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Exploring one of those hits, I find:

Quote:
Quick Start Guide for the SAM PIO driver

Workflow

Enable the module clock to the PIOA peripheral:
pmc_enable_periph_clk(ID_PIOA);
Set pin 23 direction on PIOA as output, default low level:
pio_set_output(PIOA, PIO_PA23, LOW, DISABLE, ENABLE);
Set pin 16 direction on PIOA as input, with pullup:
pio_set_input(PIOA, PIO_PA16, PIO_PULLUP);

Now, if it were me embarking on this I think I might indeed start with ASF and examples and such. Then I'd have something to dig into to see how ASF did the job.

Don't you have to set up the clocks? sysclk_init()

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

clawson wrote:
Quote:

Does anyone have any pointers for me? What am I missing, doing wrong,

Maybe you are doing it there (I'm too lazy to download the datasheet) but the usual difference between small 8 bit micros and big iron like AVR32 and ARM is that in the former all the peripherals like GPIO are enabled and ready to go at power on while in the big chips you norally have to mess with clock control registers to first enable a clock to the GPIO block before you can actually do anything with it.

Now maybe that's what WPMR is?? But if it is why do you turn it off after messing with the registers?

While I'm not a major fan of ASF I think the quickest way to learn what you need is to start an ASF GPIO example project then just burrow down through the layers of code until you reach the bit where it's actually setting the SFRs - then just lift that for your own code. As you'll find ASF is multi-layered and trying to dig down is "interesting".


So I've heard as far as ASF is concerned. Thank you for helping me out! The WPMR bit is apparently a register lock bit according to the datasheet which is set to protect registers from being accidentally modified. I have to read more into it I suppose, as I was reading deeper into it I've seen indications that the lock bit needs to be removed before every new locked register is modified possibly.. The whole making sure that the clock is started makes sense too though. A good place to take a look. Thanks again!

theusch wrote:
Exploring one of those hits, I find:
Quote:
Quick Start Guide for the SAM PIO driver

Workflow

Enable the module clock to the PIOA peripheral:
pmc_enable_periph_clk(ID_PIOA);
Set pin 23 direction on PIOA as output, default low level:
pio_set_output(PIOA, PIO_PA23, LOW, DISABLE, ENABLE);
Set pin 16 direction on PIOA as input, with pullup:
pio_set_input(PIOA, PIO_PA16, PIO_PULLUP);

Now, if it were me embarking on this I think I might indeed start with ASF and examples and such. Then I'd have something to dig into to see how ASF did the job.

Don't you have to set up the clocks? sysclk_init()


I would be under the impression that the clock wasn't necessary if there were no peripherals attached to the PIO pins, but that's likely a folly assumption considering you could set certain pins as GPIO and some as Peripheral controlled.. Thank you as well, hopefully we'll get this figured out!

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

The gpio is a peripheral block. As such, it has a clock. In the ARM sphere, generally every block has power and clock enables. If you try to access a block that isn't powered or clocked, you'll get a hardware exception that usually consists of an infinite while loop. In the debugger you'll get an error if you try to look at the registers of a block that isn't powered or clocked.

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

I just looked back at my first ever SAM4 program that alternately flashed the two LEDs and it says:

#include 

#define MY_LED (PIO_PC10_IDX)
#define OTHER_LED (PIO_PC17_IDX)

bool foo;
volatile int count;

const char flashtext[] = "Now is the time for all good men";
char ramarray[] = {1,2,3,4,5,6,7,8,9,0,2,3,4,5,6,7,8};

int main (void)
{
        board_init();
        /* Initialize the system clock */
        sysclk_init();
        ioport_init();
        ioport_set_pin_dir(MY_LED, IOPORT_DIR_OUTPUT);
        ioport_set_pin_dir(OTHER_LED, IOPORT_DIR_OUTPUT);
        // Insert application code here, after the board has been initialized.
        while(1) {
                if (foo) {
                        ioport_set_pin_level(MY_LED, false);
                        ioport_set_pin_level(OTHER_LED, true);
                }
                else {
                        ioport_set_pin_level(MY_LED, true);
                        ioport_set_pin_level(OTHER_LED, false);
                }
                foo = !foo;
                delay_ms(100);
        }
}

Some of that was just me "messing about" but I think the key thing there is the ioport_init() before anything else dealing with the GPIO. When I use VisualAssist to delve into the depths of that call then about 5 or 6 levels down one finally arrives at:

uint32_t pmc_enable_periph_clk(uint32_t ul_id)
{
        if (ul_id > MAX_PERIPH_ID) {
                return 1;
        }

        if (ul_id < 32) {
                if ((PMC->PMC_PCSR0 & (1u << ul_id)) != (1u << ul_id)) {
                        PMC->PMC_PCER0 = 1 << ul_id;
                }
#if (SAM3S || SAM3XA || SAM4S)
        } else {
                ul_id -= 32;
                if ((PMC->PMC_PCSR1 & (1u << ul_id)) != (1u << ul_id)) {
                        PMC->PMC_PCER1 = 1 << ul_id;
                }
#endif
        }

        return 0;
}

So I suggest you need something that fiddles with PMC->PMC_PCER0/1 before you can do the PIOA stuff. I think PCER0 is for PORTA/PORTB and PCER1 for PORTC perhaps?

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

I suppose I should apologize for placing this thread where I did. In retrospect it doesn't seem to fit this forum correctly, though I figured it would wind up taking shape into a bit of a comparison. :oops:

Kartman wrote:
The gpio is a peripheral block. As such, it has a clock. In the ARM sphere, generally every block has power and clock enables. If you try to access a block that isn't powered or clocked, you'll get a hardware exception that usually consists of an infinite while loop. In the debugger you'll get an error if you try to look at the registers of a block that isn't powered or clocked.

Interesting. I'm surprised that this sort of thing isn't more clearly labeled in the datasheets. The datasheets for these ARM chips seem overly complex, and very unhelpful for explaining the basics. Considering that they seem to be condensed to deal with many variants of the chip I'm very surprised by this, as well as a lot of the Atmel AVR chips I've been working with seem to have very helpful detailed datasheets for a single chip variant (not including different physical packages). I feel like I'm just starting out with MCU again. lol

clawson wrote:
I just looked back at my first ever SAM4 program that alternately flashed the two LEDs and it says:

#include 

#define MY_LED (PIO_PC10_IDX)
#define OTHER_LED (PIO_PC17_IDX)

bool foo;
volatile int count;

const char flashtext[] = "Now is the time for all good men";
char ramarray[] = {1,2,3,4,5,6,7,8,9,0,2,3,4,5,6,7,8};

int main (void)
{
        board_init();
        /* Initialize the system clock */
        sysclk_init();
        ioport_init();
        ioport_set_pin_dir(MY_LED, IOPORT_DIR_OUTPUT);
        ioport_set_pin_dir(OTHER_LED, IOPORT_DIR_OUTPUT);
        // Insert application code here, after the board has been initialized.
        while(1) {
                if (foo) {
                        ioport_set_pin_level(MY_LED, false);
                        ioport_set_pin_level(OTHER_LED, true);
                }
                else {
                        ioport_set_pin_level(MY_LED, true);
                        ioport_set_pin_level(OTHER_LED, false);
                }
                foo = !foo;
                delay_ms(100);
        }
}

Some of that was just me "messing about" but I think the key thing there is the ioport_init() before anything else dealing with the GPIO. When I use VisualAssist to delve into the depths of that call then about 5 or 6 levels down one finally arrives at:

uint32_t pmc_enable_periph_clk(uint32_t ul_id)
{
        if (ul_id > MAX_PERIPH_ID) {
                return 1;
        }

        if (ul_id < 32) {
                if ((PMC->PMC_PCSR0 & (1u << ul_id)) != (1u << ul_id)) {
                        PMC->PMC_PCER0 = 1 << ul_id;
                }
#if (SAM3S || SAM3XA || SAM4S)
        } else {
                ul_id -= 32;
                if ((PMC->PMC_PCSR1 & (1u << ul_id)) != (1u << ul_id)) {
                        PMC->PMC_PCER1 = 1 << ul_id;
                }
#endif
        }

        return 0;
}

So I suggest you need something that fiddles with PMC->PMC_PCER0/1 before you can do the PIOA stuff. I think PCER0 is for PORTA/PORTB and PCER1 for PORTC perhaps?


Wow, plenty of digging! :o This is extrordinarily helpful and straight to the point, thank you! :D

Now I've got some very good stuff to dig into!

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

The user manuals tell you about enabling clocks and power - But there is a lot to read. Even the gpio has plenty of configuration - pullups, pulldowns, interrupts then there's the event mechanism (if the chip has it) and drive strength and so on. Thus libraries like ASF to hide the evil - but then you need to learn exactly what a certain function actually does!
After a while you get used to the extra level of complexity - once you've set the stuff up, it's all much like an AVR or other 8bit micro.

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

clawson wrote:

So I suggest you need something that fiddles with PMC->PMC_PCER0/1 before you can do the PIOA stuff. I think PCER0 is for PORTA/PORTB and PCER1 for PORTC perhaps?

 

Brilliant! Actually, this is exactly what helped. I searched through the datasheet for PCER0, and it's first listing was under some clock information in some obscure portion. Literally entering those commands enabled the clocks for those peripherals, and allowed my other code to take effect! Thank you! I think this started me down the right path, and I'm going to be sticking with these SAM4 for my project. smiley

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

This is why I always try to find a simple working example (working as in I can compile and download it, and it works on my hardware!).  It can save vast amounts of time to find that one bit in that one register that you didn't realize you were supposed to set.