// if settings weren't patched in, set to a default
if (_clkfreq == 0) _clkfreq = 24000000;
if (_dbgbaud == 0) _dbgbaud = DBG_UART_BAUD;
Setting that memory location is the memory location that is changed when it gets uploaded so whatever is there is fine and should be the default values.
_clkfreq = 200000000;
_clkmode = 0x14c00f8;
_Program = 0x4c4c3250;
_Program1 = 0x4d56;
// configure clock to run at the speed selected
hubset(0);
hubset(_clkmode); // clock config (20,000,000 * 10)
waitx(177340);
r = _clkfreq / 1000000 - 1;
_clkmode |= (r << 8) | 3;
hubset(_clkmode); // set clock pll
This is the new code that sets the clock up before things get going so baud rate and other items are correct.
Is 24Mhz the right value here. I set mine to 200Mhz.
I set it up this way on purpose: library code should not make any assumptions about the hardware it is running on. Imagine someone builds a board that has an odd clock configuration that those equations/setup won't work for (for example, I did this on P1--I'd use a 5MHz cmos oscillator instead of a crystal because they were smaller and nicer for layout, which required using a non-standard clock configuration). We don't want the library to restrict what the hardware clock can be, so the library should just set up the hardware in a default state: RC fast running at 20+ MHz (I found 24 MHz to be the real value, at least on my board), and a default UART of 2Mbps. Then the application layer can change it to whatever is desired, OR for convenience, the desired clock frequency, mode, and UART can be patched into the binary via loadp2.
So in my code, if nothing is patched in, set up a default that is guaranteed to work across all hardware (use the internal clock), but let patching override if necessary (loadp2 will always set 0x14, 0x18, and 0x1c when patching). And _clkfreq and _dbgbaud need to be set otherwise other code that relies on knowing the clock frequency won't work, like setting up UART or waiting in a loop.
The compiler should be setup to work with Parallaxes product line and be ready to run at some designed configuration. The end user should not need code in his program to setup the board.
I hate patching or suppling config parameters for defaults that should already be there.
@iseries The hope is that this will extend beyond parallax's product line--such that Propeller 2 can be used beyond just hobbyists, and make it's way into real products (that was why I started this whole effort in the first place). And that requires customizability to work with any supported hardware configuration, not just what parallax makes for their eval boards. And if you don't do any patching or anything, it will run fine, in the chip's default configuration, just not using the PLL/crystal. If using the pll is a desired run mode for the user (which it will be for basically all users), then they need to the software to match the hardware they want to run. But how the PLL is configured can vary greatly, so it shouldn't be restricted in the library, otherwise the library will need to change any time a new clock type comes is used. I feel like that's a pretty typical approach for all embedded products. I used an XMC4700 not too long ago and it was the same deal: set up the clock configuration registers in software to match the hardware design.
@Rayman I updated the examples, they should all work now (I got rid of the incomplete ones, but the 4 that are there should work now). One thing to be careful of: a simple while(1); statement to block will get optimized out. If you want to block, put a waitx in the while loop so that it doesn't remove the loop. That's why you were seeing that weird behavior; the while(1) would fall through and the chip would do something undetermined.
@n_ermosh Thanks, that seems to fix it, makes sense I guess.
Visual Studio Pro is complaining about things like this: #define dirh(pin) asm volatile ("dirh %0" : : "ri"((int)pin))
Thinks it's missing a parenthesis, but it's not and compiles fine.
That's odd--yeah the parentheses are lined up and VSCode doesn't complain about that for me--seems like it's trying to guess what that line will do with a different compiler? maybe it expects a different syntax for asm statements? either way, sounds like something specific to your visual studio setup.
I could not get your example to work. I think it wanted to compile the program natively and not use the batch file.
VScode works much better and allows me to set the compiler to clang. I also can see all my programs and just pick one and compile it and then run it.
I changed all the propeller includes to use functions and documented them. This helps with code prompting and completion as you can see from the picture.
Got patching to work so now I don't have to set it in the program and everything works out of the box.
@iseries Sorry it didn't work for you. Maybe it was in the wrong configuration? It should be "Debug" and "x86" to work... I've seen it switch to "x64" sometimes for some reason and stop working...
BTW: cogstart() isn't returning the cog# for me. Just gives 1. I think that may be why @n_ermosh removed that output from the demo.
The file size is small because the elf file doesn't store the zeros only the data that goes in that section. The loadp2 code loads all the zeros though.
I guess if the stack size and heap size were set to zero it wouldn't do that.
It looks like when I first tried out lld a couple years ago, NOLOAD would actually remove the section from the elf file. At some point, the behavior of NOLOAD changed in LLD and the section is now included and marked to not be loaded with the SHT_NOBITS flag in the section header. But looks like loadp2 doesn't check for that and loads the section anyway. Updating loadp2 might be the best solution here, in which case I'll take a stab at it and make a PR. @ersmith is that expected behavior for loadp2 to still load a section even if it is flagged with SHT_NOBITS?
David Betz wrote the elf file code way back for the P1. From what I can tell there is only a TYPE code that is checked to see if is a one or not which indicates loadable code.
In my example there is 220 bytes of code that needs to be loaded but it marks the section as needing 487k of memory so don't know what should be done.
In my program I use the file size and not the memory size and just load that and skip the zeros.
Yeah--that's initially what I was thinking, but I'm curious if it will break something somewhere else, although for an embedded system, if it's not in the elf file, then it shouldn't be loaded, so probably okay to just do it. I'm seeing if there's a solution with making the linker set memsz correctly. But for now, that's a feasible solution.
Right, so data at the end of the file will not get zeroed out and just left to whatever was there. Since I think it's the stack and heap pointer there should be no issue.
Could maybe you just have a pointer to the end of the program and then just set the Heap and Stack based on that and not have a section.
Mike
PS I have tested several programs of different sizes and have found no issues.
Comments
I fixed most of those issues, but need to redo it for a pull request.
Mike
This code does not need to be this way:
Setting that memory location is the memory location that is changed when it gets uploaded so whatever is there is fine and should be the default values.
This is the new code that sets the clock up before things get going so baud rate and other items are correct.
Is 24Mhz the right value here. I set mine to 200Mhz.
Mike
I set it up this way on purpose: library code should not make any assumptions about the hardware it is running on. Imagine someone builds a board that has an odd clock configuration that those equations/setup won't work for (for example, I did this on P1--I'd use a 5MHz cmos oscillator instead of a crystal because they were smaller and nicer for layout, which required using a non-standard clock configuration). We don't want the library to restrict what the hardware clock can be, so the library should just set up the hardware in a default state: RC fast running at 20+ MHz (I found 24 MHz to be the real value, at least on my board), and a default UART of 2Mbps. Then the application layer can change it to whatever is desired, OR for convenience, the desired clock frequency, mode, and UART can be patched into the binary via loadp2.
So in my code, if nothing is patched in, set up a default that is guaranteed to work across all hardware (use the internal clock), but let patching override if necessary (loadp2 will always set 0x14, 0x18, and 0x1c when patching). And _clkfreq and _dbgbaud need to be set otherwise other code that relies on knowing the clock frequency won't work, like setting up UART or waiting in a loop.
On that fundamental fact I disagree.
The compiler should be setup to work with Parallaxes product line and be ready to run at some designed configuration. The end user should not need code in his program to setup the board.
I hate patching or suppling config parameters for defaults that should already be there.
But so be it, if that's what you're doing.
Mike
@iseries The hope is that this will extend beyond parallax's product line--such that Propeller 2 can be used beyond just hobbyists, and make it's way into real products (that was why I started this whole effort in the first place). And that requires customizability to work with any supported hardware configuration, not just what parallax makes for their eval boards. And if you don't do any patching or anything, it will run fine, in the chip's default configuration, just not using the PLL/crystal. If using the pll is a desired run mode for the user (which it will be for basically all users), then they need to the software to match the hardware they want to run. But how the PLL is configured can vary greatly, so it shouldn't be restricted in the library, otherwise the library will need to change any time a new clock type comes is used. I feel like that's a pretty typical approach for all embedded products. I used an XMC4700 not too long ago and it was the same deal: set up the clock configuration registers in software to match the hardware design.
@Rayman I updated the examples, they should all work now (I got rid of the incomplete ones, but the 4 that are there should work now). One thing to be careful of: a simple
while(1);
statement to block will get optimized out. If you want to block, put awaitx
in the while loop so that it doesn't remove the loop. That's why you were seeing that weird behavior; the while(1) would fall through and the chip would do something undetermined.@n_ermosh Thanks, that seems to fix it, makes sense I guess.
Visual Studio Pro is complaining about things like this:
#define dirh(pin) asm volatile ("dirh %0" : : "ri"((int)pin))
Thinks it's missing a parenthesis, but it's not and compiles fine.
That's odd--yeah the parentheses are lined up and VSCode doesn't complain about that for me--seems like it's trying to guess what that line will do with a different compiler? maybe it expects a different syntax for asm statements? either way, sounds like something specific to your visual studio setup.
VSCode complains about it for me, It even doesn't like volatile.
Mike
In VSC, there's a few config variables that you need to set your compiler type. Usually it can autoconfigure itself if you just provide compiler path.
I'd assume(?) that VS has a similar setting. somewhere.
@Rayman ,
I could not get your example to work. I think it wanted to compile the program natively and not use the batch file.
VScode works much better and allows me to set the compiler to clang. I also can see all my programs and just pick one and compile it and then run it.
I changed all the propeller includes to use functions and documented them. This helps with code prompting and completion as you can see from the picture.
Got patching to work so now I don't have to set it in the program and everything works out of the box.
Mike
@iseries Sorry it didn't work for you. Maybe it was in the wrong configuration? It should be "Debug" and "x86" to work... I've seen it switch to "x64" sometimes for some reason and stop working...
BTW: cogstart() isn't returning the cog# for me. Just gives 1. I think that may be why @n_ermosh removed that output from the demo.
@Rayman ,
Right, my cogstart does return the cog number were as the one you have just returned 1 - true;
Changing it x86 did the trick. Don't get code prompting though?
Also, it looks like bloating is back. The program size is small but the load size is back 507k. Looking into it.
Mike
@iseries Which kind of code prompting do you mean? It all seems to work for me...
Did you overload cogstart() ? Do you have a different propeller.h with that in it?
@Rayman ,
Yes, I rewrote all of propeller.h and propeller.c to provide code prompting. I also went through simpletools and simplei2c.
Mike
Well, I guess the bloat never left.
The file size is small because the elf file doesn't store the zeros only the data that goes in that section. The loadp2 code loads all the zeros though.
I guess if the stack size and heap size were set to zero it wouldn't do that.
Mike
Huh. Those sections are marked as “NOLOAD” yet it still includes them to be loaded? Odd.
@Rayman i updated my propeller.h to also return cog #. Mike and I need to do some work to merge our propeller.c and propeller.h to be more consistent
It looks like when I first tried out lld a couple years ago, NOLOAD would actually remove the section from the elf file. At some point, the behavior of NOLOAD changed in LLD and the section is now included and marked to not be loaded with the SHT_NOBITS flag in the section header. But looks like loadp2 doesn't check for that and loads the section anyway. Updating loadp2 might be the best solution here, in which case I'll take a stab at it and make a PR. @ersmith is that expected behavior for loadp2 to still load a section even if it is flagged with SHT_NOBITS?
David Betz wrote the elf file code way back for the P1. From what I can tell there is only a TYPE code that is checked to see if is a one or not which indicates loadable code.
In my example there is 220 bytes of code that needs to be loaded but it marks the section as needing 487k of memory so don't know what should be done.
In my program I use the file size and not the memory size and just load that and skip the zeros.
Mike
To load smaller elf files you only need to change two lines of code in loadp2.c:
Mike
Yeah--that's initially what I was thinking, but I'm curious if it will break something somewhere else, although for an embedded system, if it's not in the elf file, then it shouldn't be loaded, so probably okay to just do it. I'm seeing if there's a solution with making the linker set memsz correctly. But for now, that's a feasible solution.
Right, so data at the end of the file will not get zeroed out and just left to whatever was there. Since I think it's the stack and heap pointer there should be no issue.
Could maybe you just have a pointer to the end of the program and then just set the Heap and Stack based on that and not have a section.
Mike
PS I have tested several programs of different sizes and have found no issues.
Sample Test program for SD card support.
SD card with some files required.
Mike
What code is this using for SD access?
FatFs is really nice... Hope it's that.
@Rayman ,
Yep, that's the one I used.
Mike
@iseries Is this already in the github repo?
Trying to compile ACK, I get an error on _Bool ...
Tried adding #include <stdbool.h>, but that didn't help.
Is there a way to fix this?
@Rayman ,
Did you check the order of your includes? _Bool needs to be defined.
Mike
Ok, maybe I'm doing something wrong with include order.
Was able to fix by adding this:
From a google search. Seems C99 has it but C90 doesn't...
If I recall, bool/_Bool was made native in C99.
Getting an error trying to compile the ACK file "ack_core_lifecycle.c", that looks like this:
Any idea what might be causing that?