SAMR21 some doubts about stack size and ASF usage

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

Good evening, so some days ago I finally got my real crash-start into the ARM world with a pair of SAM R21 xplained pro boards, getting the Peer2Peer LWMesh example working was the fastest thing in the world, and provides instant gratification and amazement with the IC's.

But here comes the doubt train:

For curiosity I tried to read the RSSI value from the radio, and even adding all the source folders again this simple piece of code slapped into the while(1) loop:

char buff[32];
uint8_t rssi = phyReadRegister(PHY_ED_LEVEL_REG);
sprintf(buff, "RSSI: %i\r\n", rssi);
sio2host_rx((uint8_t)buff, sizeof(buff));

Always gives this error:

Error	1	implicit declaration of function 'phyReadRegister' [-Werror=implicit-function-declaration]	C:\Users\Ename\Documents\Atmel Studio\6.2\GETTING-STARTED1\APPS_PEER2PEER1\src\Peer2Peer.c	241	3	APPS_PEER2PEER1
Warning	2	nested extern declaration of 'phyReadRegister' [-Wnested-externs]	C:\Users\Ename\Documents\Atmel Studio\6.2\GETTING-STARTED1\APPS_PEER2PEER1\src\Peer2Peer.c	241	3	APPS_PEER2PEER1

 

I want to understand the LWMesh to use it into some projects, but its not starting well, also is there some sort of intro to the ASF libs, or reading the help files is the best I can do, sometimes I wonder what functions are even provided, pooking around the .h files always answers that but I think there might be a better list of all the functions, which brings me to another question, should I use the ASF or go straight for the bare metal registers?

The interrupt/ISR implementations feel a bit Arduinesque with the use of ASF, I'm more used to the ISR(ISR_vect) from the 8biters, all the callback mumbo-jumbo seems a bit bloated.

 

Another doubt is, how can I change the initial stack/heap size, a empty project uses 8Kb of RAM, thats 1/4 of the total RAM of the chip, and its such a waste, I have already tried this:

-Wl,--defsym,__stack_size__=0x1000

From this:

http://www.atmel.com/images/atme...

 

But changing the stack size value and recompiling achieves nothing, is there some other way?

 

Best regards, and thanks for your help.

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

I'm a fan of the bare-registers approach, but it's certainly a lot more work to get basic things working. Took about 2 days of code bashing and datasheet-cursing to get a couple of Xplained R21s talking, but very satisfying when I got it working. If your application requires a mesh network, then it would be very hard not to recommend using the ASF, as this would be intense to re-create.

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

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
implicit declaration of function 'phyReadRegister'

Tells you exactly what's wrong. You are calling a function in the absence of a declaration. It's the same if you use:

int main(void) {
    printf("hello");
}

If I do that I get:

$ avr-gcc -c -Wall -mmcu=atmega16 -Os avr.c -o avr.o
avr.c: In function ‘main’:
avr.c:2:2: warning: implicit declaration of function ‘printf’

However if I use:

#include <stdio.h>

int main(void) {
    printf("hello");
}

the warning goes away because stdio.h contains a declaration of what printf() "looks like" so the compiler then knows how to call it when it reaches that line in main().

 

Implicit declaration usually means you forgot to #include the .h file where the function is declared.

 

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

I think I'm not supposed to use that function, I have included dozens of .h to no avail(even going to the definition, them to the definition .h file, including it and still the implicit declaration), it sort of works using this:

uint8_t buff[32];
uint8_t rssi_data = PHY_EdReq();
sprintf(buff, "RSSI: %i\r\n", rssi_data);
sio2host_tx(buff, sizeof(buff));

 

Always prints 165 or something around that, but its a start.

 

Now regard the ASF/LWMesh, the developper guide seems to have everything needed, but I would like some list with all the functions that I should use, because creating a project creates dozens of folders, and .h and .c files, with lots of somethingConf, should I peek all those Conf files or better leave them alone?

 

Best regards

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

I have included dozens of .h to no avail

It's not just a case of #include anything you can think of. You have to #include the one that actually contains the declaration. There are various search tools (I use grep) you can use to search through a number of files to see where a string such as "physReadRegister" lives.

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

Thanks Clawson, for now I will start a fresh project and start poking around the i2c, ports and pins, timers, pwm and all that jazz, any ideas about changing the stack/heap size, 8Kb of RAM is way to much ram used for nothing.

 

EDIT:

That was easy.

Just went to ASF/sam0/utils/linker_scripts/samr21/gcc/samr21g18a_flash.ld and then edited this line:

/* The stack size used by the application. NOTE: you need to adjust according to your application. */
STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : DEFINED(__stack_size__) ? __stack_size__ : 0x2000;

Changed the 0x2000 to 0x800 and it finally worked as expected, now if the micro starts acting crazy I might need to bump this up.

Last Edited: Thu. Jul 30, 2015 - 10:33 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

there are tools and DIY methods to get a good estimate on stack size needed.

Hard part is heap, if used at all.

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

It looks to me like phyReadRegister() is a "private" support function for phy.c; the only prototype is in phy.c itself, AND it's declared as "static" (documented that way, too.  Only mentioned in the "phy.c source code documentation", and not in the API documentation.

 

Since phy.c and phy.h are included in your individual project, you're free to change that, or add a wrapper...

 

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

 

Here's what I've done in the past...

Assuming there's a 1KHz or so systick interrupt...

In that ISR, add a couple lines of code to keep the stack usage depth max.. a watermark if you will.

If the stack grows downward in addresses, at each clock interrupt, record the stack pointer if it is less than the last-stored. Init this static var to the highest, say 0xFFFFFFFF as a uint32_t.

 

If you can't directly access the stack pointer easily, just create a local variable "int dummyvar" in the clock ISR. The take the address of dummyvar (&dummyvar) instead of the stack pointer. Close enough.

 

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

So the actual proper way of setting up the stack is to set initial SP to the end of RAM and let it grow until it meets your data. I have no idea why ASF allocates stack this way. It makes 0 sense to me.

 

The problem you are having with 100's of files is because of ASF, LwMesh was designed to be lightweight, and it is. But everything that touches ASF immediately turns into loads of bloatware. Standalone version is still available for download http://www.atmel.com/tools/LIGHT... .

 

And yes, you should not use phyReadRegister() directly. It can put the radio into unknown state if called from an inappropriate state. LwMesh has a naming conventions (screwed up by ASF, of course). All function that start from lower-case prefix are private. All functions that start with capital letters are public.

NOTE: I no longer actively read this forum. Please ask your question on www.eevblog.com/forum if you want my answer.

Last Edited: Wed. Aug 19, 2015 - 06:18 AM