Register access only working outside of my while(1)

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

So I finally got my Xplained 21 yesterday and have been playing with it mostly trying to understand the hardware abstraction 

With my AVR microcontrollers I would start off by doing as much as i could by accessing the registers directly , I am attempting to do the same with this board

However youll see in the code below that the things i have commented out do not work in the while 1 loop , not even the function call to that very efficient delay. 

my defines are to the correct memory addresses and offsets , funny thing is if i put them outside of the while(1)  loop they work as expected... so i know the memory mapping is right. 

Again this is just for my personal learning purposes , but i would like to understand why? 

And yes I can get a proper delay with the systick handler etc.. but even then nothing seems to work in my while loop

 

#include "sam.h"


#define myDIR		(*(( uint32_t*)(0x41004400)))
#define myOUTSET	(*(( uint32_t*)(0x41004418)))
#define myOUTCLR	(*(( uint32_t*)(0x41004414)))
#define myTOGGLE	(*(( uint32_t*)(0x4100441C)))
#define myPM		(*(( uint32_t*)(0x4000041C)))
#define myPMUX		(*(( uint32_t*)(0x40000434)))

//prototype
void my_efficient_delay(void);



void my_efficient_delay()
{
	 for (int x  = 0 ; x < 10000 ; x++);
	 
}


int main(void)
{
   
    SystemInit();
	
	PORT->Group[0].DIR.reg = 1<<8;
	//myDIR = 1<<8;
	 
	
   while(1)
   {
	
	 PORT->Group[0].OUTTGL.reg = 1<<8 ;
	//myTOGGLE  = 1<<8;
	  
	// my_efficient_delay();
	for (int x  = 0 ; x < 10000 ; x++);
	
 
	}
}

 

Last Edited: Thu. Oct 15, 2015 - 11:34 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

With ARM Cortex MCUs, one does not muck with registers like on an AVR.

Use vendor-provided Hardware Abstraction Libraries (HAL), for every peripheral I/O device on the chip.

AVR was bare-metal.

ARM, is not.

 

Takes a mindset change to drop the old AVR 8 bit habits.

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

You haven't defined your pointers as volatile, and your "efficient" delays are optimized away by nearly any version of gcc.

This code wouldn't work on an AVR, either.

 

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

eddieA6987 wrote:
So I finally got my Xplained 21

There is no such thing as an "Xplained 21" - I guess you mean either a SAMD21 Xplained Pro, or a SAMR21 Xplained Pro ?

 

trying to understand the hardware abstraction

But you aren't doing any abstraction - you are hacking directly with the registers!

 

stevech wrote:
AVR was bare-metal.

ARM, is not.

That, of course, is nonsense.

 

You can use hardware abstraction libraries on AVR (think Arduino) just as much as you can do direct register access on ARM.

 

However, I would certainly recommend that you at least start with ASF (Atmel's "hardware abstraction" library).

 

Then, if you really want to "dive down" into the arcane world of direct register access, you at least have working examples to explore ...

 

On at91.com, bptech wrote:

Seems to be a recurring theme - "I don't want to use ASF but <complex inner detail question about something easily solved by using ASF>.

 

See: http://www.at91.com/discussions/...

 

https://www.avrfreaks.net/comment...

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Aug 12, 2015 - 07:23 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Surely, "efficient delay" is an oxymoron ?

 

cheeky

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would certainly recommend that you at least start with ASF

 I have been having educational fun by gradually removing ASF invocations from SAMD10 XPlained Mini Examples...

https://www.avrfreaks.net/forum/s...

Most of that should apply to the SAMD21 as well.

 

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

westfw wrote:
educational fun

sounds like some kind of euphemism ... ?!

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There are header files with the register equates - no need to #define the addresses.
Using the structure to access the registers will most likely be more efficient than direct access. Look at the generated asm in the debugger.

For your delay, you might want to add volatile to the loop variable so the compiler doesn't optimise it out.

Last Edited: Wed. Aug 12, 2015 - 08:19 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
Using the structure to access the registers will most likely be more efficient than direct access

Eh??

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You haven't defined your pointers as volatile, and your "efficient" delays are optimized away by nearly any version of gcc.

This code wouldn't work on an AVR, either.

The point he's making in case you haven't grasped it is:

#define myDIR		(*((volatile uint32_t*)(0x41004400)))

etc.

 

Also:

void my_efficient_delay()
{
	 for (volatile int x  = 0 ; x < 10000 ; x++);
	 
}

While I wrote the following for AVR not ARM the fact is that they all use GCC and the same rules apply so have a read of this...

 

https://www.avrfreaks.net/forum/t...

 

The "issue" is that the compiler is ferocious when it comes to discarding what appears to be "pointless" code. "volatile" basically means "don't discard this, it must exist".

AVR was bare-metal.

ARM, is not.

As others have said, this is not a fixed rule. It's a personal choice. Some of us like programming ARM using bare-metal (because a lot of the library code is too abstracted). However as you've also found you don't need to #define a whole set of you own volatile pointers either. The device header files in the C library that comes with the SAM version of arm-gcc already have those things defined - no need to re-invent that wheel (as long as you are happy with the syntax Atmel chose for those header definitions).

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

awneil wrote:

Using the structure to access the registers will most likely be more efficient than direct access

Eh??

The base address of the structure will only be loaded once, while each individual address of single registers gets loaded.

https://www.avrfreaks.net/comment...

 

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

Andy, the header file has structures for the peripherals. It also has the addresses to access the registers directly (as opposed to base+offset lthat would be used with structures)

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

westfw wrote:
The base address of the structure will only be loaded once, while each individual address of single registers gets loaded.

Ah - I see; Provided you are doing consecutive accesses to the same "set" of registers represented by that struct.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bare metal

 

Prompts this question: https://www.avrfreaks.net/forum/w...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thumb2 has a 8 bit immediate load, so to load a 32bit pointer would take a few instructions. To get around this problem, there are 'literal pools' where the pointer values are stored (usually in flash). A pc relative load is used to load a register with the literal value.  The assembler supports this construct by providing a pseudo-op that appears like a 32bit immediate load but actually implements it using a literal pool. This requires a little bit of thought when writing in asm as your literal pool can't be located too far away and your code has to jump over it or otherwise avoid it. Arm have a good description of it on their website.

So using base+offset will most likely use less flash (each address is 32 bits!) and allow the compiler to hopefully keep the pointer in a register as well as being more cycle efficient.

Last Edited: Wed. Aug 12, 2015 - 10:47 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This requires a little bit of thought when writing in asm

So why write in Asm? The C compiler/linker knows all this stuff and arranges for the literals to be where it needs them to be.

 

With ARM you sometimes write the startup.S in Asm (though CMSIS for Cortex kind of negates the need for that these days) but after that there's very little reason to need to use Asm.

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

clawson wrote:
With ARM you sometimes write the startup.S in Asm (though CMSIS for Cortex kind of negates the need for that these days)

Indeed.

 

ASF doesn't use any ASM for the startup - it's all 'C'.

 

Again, you could take the ASF startup and use it with your own, non-ASF ("really bare metal") code - it isn't highly abstracted like the rest of ASF.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Cliff - there's always a good reason to write in asm - because you can!
Take ,for example, a 6502 emulator. I grabbed one written in C off the interwebs and did a little benchmark - on a 48MHz m0, around 125kHz. On a 100MHz R4, around 300kHz. Asm? Yet to find out. Some maniac has written one for a m4 in asm - he hails from your side of the pond and supposedly 18MHz on a 168MHz m4.

Note that i don't see myself writing ARM asm for my day job.

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

ASF doesn't use any ASM for the startup - it's all 'C'.

Yup that's the point I made in parentheses - back in the ARM7/ARM9 days we'd often have to write some startup.S but the way ARM have architected Cortex and CMSIS means that it's now all odne in much more accessible C and it's supplied "for free" - no need to write it like there was back in the old ARM days.

because you can!

You can:

 

climb everest

swim with crocodiles

go to a One Direction concert

watch X-factor/Britain's Got Talent/The Only Way is Essex/<insert name of inane drivel here>

...

 

Just because something is possible doesn't necessarily make it something that one really wants to do! cheeky

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

clawson wrote:
the way ARM have architected Cortex and CMSIS means that it's now all odne in much more accessible C

Well, it can all be done in 'C'.

 

interestingly enough, Keil (an ARM company) still does it in assembler - which is why I emphasised that ASF is all 'C'.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

There is no such thing as an "Xplained 21" - I guess you mean either a SAMD21 Xplained Pro, or a SAMR21 Xplained Pro ?

 

Surely you could of figured out what i was talking about??? everyone else did.   Throughout the forum i find your comments to be in the format of : quote this quote that of the original question ,  most of the time in successful attempts to be condescending , providing very very little help ,not to mention your proverbial quote from another forum about " not wanting to use ASF insert something here..." I'd much appreciate it if you'd not answer  comment on my questions. But you are free man do as you please. 

AVR was bare-metal.

ARM, is not.

But surely if  i dig back through structure of PORT_TYPE and furthermore structure of BIT type and REG type , then figure out all the DEFINES it boils down to bare metal

which is exactly where i got the addresses from. I assure you this is only for learning purposes , but I agree gotta kick the 8bit habits.

You haven't defined your pointers as volatile, and your "efficient" delays are optimized away by nearly any version of gcc.

That indeed must be the answer. I'd given optimization no mind , rookie mistake i suppose . 

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

Eddie, tech forums are full of people with Asperger traits and you've identified a repetitive one that just injects noise into the system. Sure, its annoying but I can't be too judgemental.

Anyways, this http://www.avrfreaks.net/forum/samd10-xplained-mini-questions-and-experiences-clocking-transitioning-pinmux
On msg #32 outlines the use of 'bare metal' register access using header file constants and a comparison between 'direct' access or access via the structure ( base+offset).

Last Edited: Wed. Aug 12, 2015 - 09:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yep, as above, there are a number of us that like accessing the registers directly and not using the ASF, we have proven conclusively that it can save a great deal of program space, but really, once you get your head around it, it's easier than figuring out the ASF. 

 

I would recommend using the already defined registers and bit names rather than redefining everything yourself. As others have pointed out, it's sometimes easy to miss things like all register definitions should be volatile.

 

Have a look through some of the other posts where we have uploaded code that access the registers directly, once you've had a look at this, you will pretty quickly figure out how to access all peripherals.

If you're using ASF, neither of us know what your code is really doing :)
Have I just solved your problem ? My bitcoin address: 1EpGuPa2VtUVWjGmgWRmFicNKMFZSGhfLr