Thanks for all that. I think I am getting closer to a solution.
I'd like to think about an absolute minimalist plugin. All it does is tells Catalina that it can keep running. To do this I understand it needs to write a zero somewhere. If the plugin knows the location of the registry, and it is running in cog 7, what is the location of the long in which to write that zero?
I am guessing here, but is it one of registry+7, or registry-7, or registry+14, or registry-14, or registry+15, or registry-15, or some other location?
Hi Dr_A,
Look at the minimalist target which is in the custom directory, and the demo programs that use it in the custom_demo directory - see the README.TXT file in that directory for more details.
These demo programs use Catalina_Plugin.spin from the custom directory. This is a complete - but quite simple - example of a plugin. It should answer all your questions.
Don't assume your code is at fault. It could well be a Catalina issue. When I get time I'l check out all the cases where a C compiler is supposed to guarantee memory is initialized to zero. But if you do find clue, please let me know!
Ross.
Hi Ross,
I spent some time stripping out all of the code in xbasic except the simple line editor and at first I thought that made the problem go away but then I pressed the reset switch on my C3 and it wouldn't work anymore. I've attached the simpler code to this message. I've read over the code and I don't see any memory problems but I may have missed something. In any case this will provided a simpler program that illustrates the problem I'm having. I will continue to look at this myself to see if I've made some dumb blunder.
Thanks for your patience. Truth be told, this is the one last bit of code that will enable Catalina to do all the things Kyedos can do. But I have known this last little bit was going to be complicated, so I have been putting off asking it for the last 4 months. Partly because I was afraid it could not be done, and partly because I was trying to postpone doing the coding.
It is time to get this working!
What I specifically want to do is get the LCD working on the dracblade, but there are all the digital IO ports as well, and so in a more generic sense, what I want to do is enable a cog to take over propeller pins 1-12 while running in XMM mode. That involves temporarily pausing Catalina.
Let's strip this right down to bare essentials. Start a XMM C program and issue a cog_stop to cogs 0,1,3,4,5,6 This just leaves catalina itself running in cog 2.
Now I want to pause Catalina. I found some code in "complex_test.c"
the first instruction in the main is
reg = _registry();
and yes I imagine we are going to need this.
next is
cog = _locate_plugin(LMM_DUM);
I'm not sure what this does, and it is using LMM instead of XMM, but maybe it is relevant. We shall see because the next line is
use_plugin(10);
This might be the missing piece of the puzzle. Not sure what 10 is, and not sure if "use_plugin" is an internal C command or hidden somewhere in one of the "include" files, but it looks promising.
Next line is
_unregister_plugin(cog);
well now we have gone too far, because we are unregistering the plugin.
You said earlier that calling a plugin will pause Catalina. Do any of the above functions do this? Or is it something else that pauses Catalina?
Once Catalina is paused, I am assuming that there is a location somewhere in hub ram where a cog can change a variable to restart Catalina.
I am really sorry I can't grasp what is going on with plugins. I may not need to, but perhaps to explain a bit more what is complicated, and what I can't seem to find in the manual, there are examples of spin code, and each line of spin code seems quite obvious what it does - write to a registry location, interact with a service call. But I don't understand the big picture. Where is this Spin code used? Catalina is a C program, so what is Spin doing there in the first place? I have some theories. Maybe the Spin is some code that is run via an separate spin interpreter cog (as discussed in the thread talking about Zog and Spin interacting). Maybe this Spin is part of Catalina itself, and once customised, requires a recompilation of Catalina to be used? Or maybe this Spin is included in a C program, in some sort of hybrid code?
I'm really sorry not to be able to grasp this concept, but having written 10 cogjects now, I just can't see how you can have any Spin code at all in a C program, surely it has to be pure PASM?
For example, I see this line of code in a program called "Catalina_Plugin.Spin", in a PUB called "start"
and the purpose of that line of code is completely clear and obvious. It sends over some parameterrs including one that is bit shifted. Simple.
Yet I cannot see how you can have any PUB code as part of a "plugin".
So - this is my problem really, as I just don't understand how plugins work.
But at the same time, I don't think I need to. I think that the solution to the problem I need to solve comes down to just two lines of code. One is a line in C, and one is a line of code in PASM.
The line of code in C is a function call that pauses Catalina until a certain hub memory location changes its value. I don't know what that function is, but I think it must be one of the lines of code either above or in some of the demo code.
And the second line of code is a line of code in PASM that will be a "wrlong" and will write a value to a location in hub near to the value of "registry". This will restart Catalina.
Drac: I can see the topic of discussion for the OZ SA UPE next week will be Catalina Plugins. This is because I have been doing a small bit of C coding and need to load my own plugins
Hopefully you can explain it to me simply.
You said earlier that calling a plugin will pause Catalina. Do any of the above functions do this? Or is it something else that pauses Catalina?
It's much simpler than that. I posted earlier an example of code that will "pause" Catalina. I used the HMI plugin as an example, and posted the code that results from a t_char function call - specifically:
int _short_plugin_request (long plugin_type, long code, long param) {
return _sys_plugin (plugin_type, (code<<24) + (param & 0x00FFFFFF));
}
Any Catalina program that makes any _sys_plugin service request is "paused" in the _sys_plugin call itself until the plugin it calls tells it that it can continue. The parameter to the request (in this case (code<<24)+param & 0x00FFFFFF) ) is placed into the registry request block that belongs to the plugin with type plugin_type (in this case that would have to be LMM_HMI - see the plugin types defined in catalina_plugin.h). Specifically, the parameter is written to the request long of the request block, and if the plugin needs to return a result, it should be written to the response long.
The request value written must always be non-zero. All plugins must (at least occasionally) check their request long. The plugin can do whatever it likes with the request, but when it wants the kernel to continue from its paused state it does so by by writing a zero into the request long. Normally this indicates the request is complete, but this is not necessarilly the case - the plugin can carry on processing the request after it has allowed the kernel to continue if it needs to.
Note that you can also make a service call to a specific cog - just set bit 8 in the first parameter to the _sys_plugin function call - e.g:
int _cog_plugin_request (long cog, long code, long param) {
return _sys_plugin (cog + 0x80, (code<<24) + (param & 0x00FFFFFF));
}
I allow this to cater for cases where there may multiple instances of the same plugin type running.
Once Catalina is paused, I am assuming that there is a location somewhere in hub ram where a cog can change a variable to restart Catalina.
Yes - as described above, this is the first long of the request block assigned to the plugin. Set it to zero to restart the kernel that made the service request
I am really sorry I can't grasp what is going on with plugins. I may not need to, but perhaps to explain a bit more what is complicated, and what I can't seem to find in the manual, there are examples of spin code, and each line of spin code seems quite obvious what it does - write to a registry location, interact with a service call. But I don't understand the big picture. Where is this Spin code used?
There is no SPIN code used, except (special case!) at boot time while Catalina sets things up for the kernel. There, I sometimes use SPIN code to do things, and sometimes PASM code. But once the kernel starts, everything can (must!) be done in C or PASM code.
Catalina is a C program, so what is Spin doing there in the first place?
Since the Propeller effectively always boots into SPIN, Catalina uses SPIN as a means of starting the kernel. Each Catalina target is a SPIN program - it's job is to load the plugins, then start the kernel. Once the kernel is started, no Spin runs thereafter (unless you manually start another Spin interpreter in a free cog).
I have some theories. Maybe the Spin is some code that is run via an separate spin interpreter cog (as discussed in the thread talking about Zog and Spin interacting). Maybe this Spin is part of Catalina itself, and once customised, requires a recompilation of Catalina to be used? Or maybe this Spin is included in a C program, in some sort of hybrid code?
No - you can manually start another SPIN interpreter - but unless you do so, no SPIN runs once the kernel is started.
I'm really sorry not to be able to grasp this concept, but having written 10 cogjects now, I just can't see how you can have any Spin code at all in a C program, surely it has to be pure PASM?
As I described above - there is no SPIN interpreter running once the kernel is started.
and the purpose of that line of code is completely clear and obvious. It sends over some parameterrs including one that is bit shifted. Simple.
Yet I cannot see how you can have any PUB code as part of a "plugin".
That line is executed only on the very first load, while the target (a SPIN program) is still setting things up for the kernel, and before the kernel is running. If you look at the complex_example.c in custom_demo, you can see an example of loading, registering and unregistering a plugin entirely from C (except the registering part is currently commented out, since this example plugin registers itself).
But at the same time, I don't think I need to. I think that the solution to the problem I need to solve comes down to just two lines of code. One is a line in C, and one is a line of code in PASM.
The line of code in C is a function call that pauses Catalina until a certain hub memory location changes its value. I don't know what that function is, but I think it must be one of the lines of code either above or in some of the demo code.
The line you are looking for is any call to _sys_plugin. That's why I keep saying you will have to reinvent a similar mechanism if you don't use plugins.
And the second line of code is a line of code in PASM that will be a "wrlong" and will write a value to a location in hub near to the value of "registry". This will restart Catalina.
The line you are looking for is the line that writes a zero to the plugin's request long - in the example plugin in the custom target (i.e. Catalina_Plugin.spin) this is the PASM line labelled done_service.
I hope this helps. I really think you should use plugins - they are both simple and convenient, and support for them is "built-in" to Catalina at a very low level. However, if you decide to use another mechanism, you could develop one based on locks instead of memory locations. If all I had needed to do was "pause" the kernel temporarily, I might have used locks instead - the registry-based mechanism that Catalina uses is more complex, but it allows for the passing and returning of arbitrary data in addition to a simple pause/continue function.
I spent some time stripping out all of the code in xbasic except the simple line editor and at first I thought that made the problem go away but then I pressed the reset switch on my C3 and it wouldn't work anymore. I've attached the simpler code to this message. I've read over the code and I don't see any memory problems but I may have missed something. In any case this will provided a simpler program that illustrates the problem I'm having. I will continue to look at this myself to see if I've made some dumb blunder.
Thanks,
David
Hi David,
Thanks - I'll have a look at this example and see if I can figure out what the problem is. Might not be today though!
How would I go about adding a mouse? The mouse is connected to the standard demo board pins and it works with Spin code. However, I have a feeling that because the original Dracblade did not have a mouse, the code does not include a mouse. In the compilation, there is reference to a VGA_nomouse.
What would I change to use a driver but with a mouse?
Hi Dr_A,
There a a couple of files that need changing. I have attached updated ones - just unzip them into your target directory (over the existing ones). Note that these files change the default behaviour to including the mouse driver. if you use these files but decide you DON'T want a mouse, you will have to add -D NO_MOUSE to all your compilation commands.
I assume your mouse is connected to pin 24 & 25. If not, change MOUSE_PIN in the DRACBLADE section of Catalina_Common.spin.
Is there any way to get around the fact that specifying "-DFOO" or "-D FOO" on the Catalina command line causes the symbol "__CATALINA_FOO" to be defined while compiling the C code? This behavior is totally unlike any other C compiler and makes it difficult to use conditionals in C code that work the same when compiled with a variety of compilers. I suspect I might be able to use the syntax "-W-DFOO" or maybe "-W-D FOO" to accomplish this but that's rather ugly and I'm not even sure the second example would work. It might be best of Catalina were changed to interpret -D in the defacto standard way and to use some other switch to control Catalina target options.
For instance, GCC uses "-m" for machine-dependant options.
Just an update - there is definitely a problem with the caching XMM driver on the C3. I haven't quite tracked it down yet, but I hope to have it fixed in a day or two. Your abbreviated program helped a lot - thanks!
As to your question about conditionals - just use -W-DFOO. If you really dislike having to add the -W, then call lcc directly. The catalina program is really just a wrapper for lcc. To see the lcc command catalina generates, use the -v switch. For example, you will see that the command:
The original few releases of Catalina actualy worked this way (i.e. there was no catalina program - you instead called lcc directly) but I had lots of complaints that the command line was too complex, so I wrote the catalina wrapper to simplify it. But using it is entirely optional, and you are always free to call lcc directly if you prefer. This is documented in the Catalina reference manual.
I think I've finally tracked down the problem on the C3. It wasn't the cache after all - I simply wasn't copying the read/write segments correctly from the SPI Flash to the SPI RAM on program startup.
Can you verify the enclosed file fixes the problem? Just unzip this file over the existing version in your target directory. Then rebuild everything (including the utilities folder).
If this file works ok, then I'll tidy it up and issue a proper patch release (along with a couple of other very minor fixes).
I think I've finally tracked down the problem on the C3. It wasn't the cache after all - I simply wasn't copying the read/write segments correctly from the SPI Flash to the SPI RAM on program startup.
Can you verify the enclosed file fixes the problem? Just unzip this file over the existing version in your target directory. Then rebuild everything (including the utilities folder).
If this file works ok, then I'll tidy it up and issue a proper patch release (along with a couple of other very minor fixes).
Ross.
Hi Ross,
I tried this new code. First, I copied this to my target directory and then I rebuilt the utilities directory using the recommended "build_all C3 CACHED_4K FLASH" command and finally I rebuilt xbasic from scratch. I tried downloading this with payload several times all with the same result.
payload -p 13 -t 1000 XMM bin/xbasic.binary
Using Propeller (version 1) on port COM13 for first upload
Using port COM13 for subsequent uploads
Warning: no sync received for addr 00039a00
Warning: no sync received for addr 00039a00
Warning: no sync received for addr 00039a00
Warning: no sync received for addr 00039a00
Warning: no sync received for addr 00039a00
Error: too many retries for addr 00039a00
I tried this new code. First, I copied this to my target directory and then I rebuilt the utilities directory using the recommended "build_all C3 CACHED_4K FLASH" command and finally I rebuilt xbasic from scratch. I tried downloading this with payload several times all with the same result.
payload -p 13 -t 1000 XMM bin/xbasic.binary
Using Propeller (version 1) on port COM13 for first upload
Using port COM13 for subsequent uploads
Warning: no sync received for addr 00039a00
Warning: no sync received for addr 00039a00
Warning: no sync received for addr 00039a00
Warning: no sync received for addr 00039a00
Warning: no sync received for addr 00039a00
Error: too many retries for addr 00039a00
Did I miss a step somewhere?
Thanks,
David
That's odd - I rebuilt xbasic as well, and it worked for me. Can you zip up and post your actual xbasic binary here? I'll investigate it tonight.
What gets written to C3 flash when I use payload to load a program? Is it just the entire contents of the .binary file? I'm asking because I'd like to convert my zogload program into a loader for Catalina.
That's odd - I rebuilt xbasic as well, and it worked for me. Can you zip up and post your actual xbasic binary here? I'll investigate it tonight.
Ross.
I'm afraid I've continued to update xbasic so it is a little different from the one you built. I'm kind of tired tonight but I'm going to try this again in the morning to see if there is some mistake I made in applying your patch. The odd thing is that xbasic worked with the pre-release version of Catalina 3.0. I'm not sure why it is having trouble with the official release.
What gets written to C3 flash when I use payload to load a program? Is it just the entire contents of the .binary file?
Yes, you first just throw the appropriate platform-dependent loader (e.g. XMM.binary compiled with the appropriate options) at the Propeller's built-in loader, then when the Prop restarts you throw the entire binary file at the platform-dependent loader. On some platforms this second load can use the same port as the first load, but on other platforms (e.g. those that use the HX512 SRAM card) a different port must be used for the second load.
The platform-dependent loader is always a normal binary, and this load is always done using the Parallax binary load protocol.
The second binary can be either a normal binary or a Catalina LMM or XMM binary, and this load is done using the Catalina binary load protocol. The platform-dependent loader knows how to decode the different program types and memory layouts on the fly, and store the appropriate sections in the appropriate places (e.g. SPI Flash, SPI RAM or Hub RAM) depending on the memory layout specified in the binary file. Or at least it will when it is working properly! :frown:
The Catalina binary load protocol is described in the Catalina Reference Manual (pp 79).
I'm afraid I've continued to update xbasic so it is a little different from the one you built. I'm kind of tired tonight but I'm going to try this again in the morning to see if there is some mistake I made in applying your patch. The odd thing is that xbasic worked with the pre-release version of Catalina 3.0. I'm not sure why it is having trouble with the official release.
It doesn't really matter how the binary was produced - I just want one that is known to fail. The error message you are getting indicates it is the loader itself which is crashing when attempting to write a specific protocol packet to SPI Flash. I can't think of any reason why this should be the case - especially since I can successfully load much larger binaries on my C3. Possibly there is a corner case somewhere in my byte stuffing or LRC checking that only occurs when a specific sequence of binary data is received.
I've done a clean installation of Catalina 3.0, copied the fixed version of the flash hub loader to the target directory, then recompiled the utilities folder and all my catalyst programs. I also recompiled the latest version I have of xbasic.
Every program I have now loads and runs perfectly on the C3. I can load them using the Payload serial loader or the Catalyst SD card loader - it even fixes a problem with the vi text editor that I hadn't gotten around to looking at yet!
I don't know what could be causing your problem except for an SPI Flash hardware failure, but if you can post a binary file that won't load, I'll investigate further.
The Catalina binary load protocol is described in the Catalina Reference Manual (pp 79).
I'm sorry. I guess I wasn't clear. I don't want to implement the Catalina load protocol. All I really want to know is the layout of data in the flash after a load is complete. That way I can use my own flash writing code to write an image into the C3 flash and use your Flash_Loader.binary loader to load it from flash on reset. So, I guess what I'm really asking is how Flash_Loader.binary works. What is the layout of code and data that it expects to find in the flash?
I'm sorry. I guess I wasn't clear. I don't want to implement the Catalina load protocol. All I really want to know is the layout of data in the flash after a load is complete. That way I can use my own flash writing code to write an image into the C3 flash and use your Flash_Loader.binary loader to load it from flash on reset. So, I guess what I'm really asking is how Flash_Loader.binary works. What is the layout of code and data that it expects to find in the flash?
Thanks,
David
Ok. It differs according to the memory model and segment layout being used - but for Flash programs you only need to worrry about two of the seven supported layouts - for programs that are to be stored in Flash, layout 3 is used for LARGE programs, and layout 4 is used for SMALL programs.
Basically, the difference is that layout 3 arranges the segments as (init,data,code,cnst) and layout 4 arranges them as (cnst,init,data,code).
When LARGE programs are stored in Flash, the code and cnst segments are stored at their correct addresses for execution. Then, starting on the next sector boundary (i.e. hex $200 boundary) I store the sectors containing the init & data segments.
When SMALL programs are stored in Flash, the code segment is stored at its correct address for execution, then (again on the next sector boundary) I store the sectors containins the cnst, init & data segments.
The segments embedded in the stored sectors need to be relocated before the program can be run - this is the job of the Hub Flash loader, which is loaded into Hub RAM for execution once the Flash programming is complete. Alternatively, it can be run from EEPROM (this is really the main part of the Flash_Boot program - the remainder simply loads various device drivers the program might need).
I don't bother fully decoding the sectors containing the segments that need to be relocated - I just store them as they arrive serially, or as they are read from the SD card. This simplifies the process of storing them in Flash quite significantly, and allows the loader to fit it into a single cog. The Hub Flash loader will later extract and relocate the actual segments from the stored sectors - either to SPI RAM (LARGE) or Hub RAM (SMALL).
The segment layout being used and segment table itself is always stored in the first sector of the code segment. You'll see this referred to in the code as the "prologue". You need to use this information to figure out where in the binary data stream the segments start and finish. Interpreting the values in this table is also layout dependent - for examples of how to do this, see the code starting around line 2455 of the catbind program.
I've done a clean installation of Catalina 3.0, copied the fixed version of the flash hub loader to the target directory, then recompiled the utilities folder and all my catalyst programs. I also recompiled the latest version I have of xbasic.
Every program I have now loads and runs perfectly on the C3. I can load them using the Payload serial loader or the Catalyst SD card loader - it even fixes a problem with the vi text editor that I hadn't gotten around to looking at yet!
I don't know what could be causing your problem except for an SPI Flash hardware failure, but if you can post a binary file that won't load, I'll investigate further.
Ross.
I'm beginning to think you might be right about my SPI flash. That would be bad news since, as you know, the flash chip isn't replacable on the C3. I find that sometimes my loads fail and sometimes they succeed. I've played with it more this morning and I have been able to get xbasic to load and run. However, I can't seem to get SD card access to work after a reset when I program Flash_Boot into my C3. The xbasic interpreter comes up but 'load' doesn't work, it just hangs. This may be because I'm building it wrong though. I used the following command:
build_all C3 CACHED_4K FLASH SD
in the utilities directory. Should that be sufficient? I have to admit that I'm confused about when build_all is necessary. I had originally thought that I only had to do it once to select the board I was going to use, in this case the C3. Now I guess I also need to run it if I change the cache size and if I decide I want to use the SD card in my program. What I'm not sure about now is if I will get an SD driver in every program I build since I specified "SD" to get Flash_Boot built correctly. Should I consider running build_all to be part of the build process for every program and add it to the makefile?
Oops, sorry! I had intended to attach my latest xbasic source code to the last message. Here it is. The xbasic directory has a makefile that should build the full xbasic compiler/runtime using Catalina. The xbasic/xbedit directory has a makefile that will build only the simpler editor with no compiler and runtime for testing purposes.
I'm beginning to think you might be right about my SPI flash. That would be bad news since, as you know, the flash chip isn't replacable on the C3. I find that sometimes my loads fail and sometimes they succeed. I've played with it more this morning and I have been able to get xbasic to load and run. However, I can't seem to get SD card access to work after a reset when I program Flash_Boot into my C3. The xbasic interpreter comes up but 'load' doesn't work, it just hangs. This may be because I'm building it wrong though. I used the following command:
build_all C3 CACHED_4K FLASH SD
in the utilities directory. Should that be sufficient?
Yes that should work - it's how I do it. I'll do some more testing on this scenario tonight.
I have to admit that I'm confused about when build_all is necessary. I had originally thought that I only had to do it once to select the board I was going to use, in this case the C3. Now I guess I also need to run it if I change the cache size and if I decide I want to use the SD card in my program. What I'm not sure about now is if I will get an SD driver in every program I build since I specified "SD" to get Flash_Boot built correctly. Should I consider running build_all to be part of the build process for every program and add it to the makefile?
Thanks,
David
I guess I could document this better
For the C3, the built_all script in the utilities folder builds two utility programs - XMM.binary and Flash_Boot.binary.
You need to rebuild XMM.binary to match whatever cache size the programs it loads will use, so the CACHED and FLASH options must match what you used when you built the programs it will be used to load (BTW, the same is true of the Catalyst loader, should you ever build that).
Any other options you specify to build_all (like SD) only apply to the Flash_Boot.binary - they tell it what drivers to load before it executes the program stored in Flash. It is not necessary that Flash_Boot be built with the same options as the program was built originally - you can actually change the cache size or HMI drivers in Flash_Boot if you want. This is possible because what is stored in Flash is entirely above Catalina's Hardware Abstraction Layer, and what Flash_Boot loads is entirely below it. Of course, if the program is expecting some speciifc plugins to be present at run time (such as floating point plugins) then a version of them has to be loaded - but you can change which version.
Maybe I should have a separate build script for each utility - it might make things more obvious.
Oops, sorry! I had intended to attach my latest xbasic source code to the last message. Here it is. The xbasic directory has a makefile that should build the full xbasic compiler/runtime using Catalina. The xbasic/xbedit directory has a makefile that will build only the simpler editor with no compiler and runtime for testing purposes.
Something odd is happening. I've finally been able to flash xbasic into the SPI flash on my C3 board and it ran the first time I downloaded it using payload. I then tried typing "payload Flash_Boot" to write the boot program into EEPROM and after that completed xbasic worked too. However, if I press the reset button, even though xbasic comes up, the SD card file I/O doesn't seem to work and I can't load 'test.bas' from the SD card. Any idea why it would behave differently after reset than after it was initially loaded?
Comments
Hi Dr_A,
Look at the minimalist target which is in the custom directory, and the demo programs that use it in the custom_demo directory - see the README.TXT file in that directory for more details.
These demo programs use Catalina_Plugin.spin from the custom directory. This is a complete - but quite simple - example of a plugin. It should answer all your questions.
Ross.
It is the loose cogs we are worried about !! I know there are a few of us that have them - we must or we woud be doing something else with our lives
Hi Ross,
I spent some time stripping out all of the code in xbasic except the simple line editor and at first I thought that made the problem go away but then I pressed the reset switch on my C3 and it wouldn't work anymore. I've attached the simpler code to this message. I've read over the code and I don't see any memory problems but I may have missed something. In any case this will provided a simpler program that illustrates the problem I'm having. I will continue to look at this myself to see if I've made some dumb blunder.
Thanks,
David
Thanks for your patience. Truth be told, this is the one last bit of code that will enable Catalina to do all the things Kyedos can do. But I have known this last little bit was going to be complicated, so I have been putting off asking it for the last 4 months. Partly because I was afraid it could not be done, and partly because I was trying to postpone doing the coding.
It is time to get this working!
What I specifically want to do is get the LCD working on the dracblade, but there are all the digital IO ports as well, and so in a more generic sense, what I want to do is enable a cog to take over propeller pins 1-12 while running in XMM mode. That involves temporarily pausing Catalina.
Let's strip this right down to bare essentials. Start a XMM C program and issue a cog_stop to cogs 0,1,3,4,5,6 This just leaves catalina itself running in cog 2.
Now I want to pause Catalina. I found some code in "complex_test.c"
the first instruction in the main is
and yes I imagine we are going to need this.
next is
I'm not sure what this does, and it is using LMM instead of XMM, but maybe it is relevant. We shall see because the next line is
This might be the missing piece of the puzzle. Not sure what 10 is, and not sure if "use_plugin" is an internal C command or hidden somewhere in one of the "include" files, but it looks promising.
Next line is
well now we have gone too far, because we are unregistering the plugin.
You said earlier that calling a plugin will pause Catalina. Do any of the above functions do this? Or is it something else that pauses Catalina?
Once Catalina is paused, I am assuming that there is a location somewhere in hub ram where a cog can change a variable to restart Catalina.
I am really sorry I can't grasp what is going on with plugins. I may not need to, but perhaps to explain a bit more what is complicated, and what I can't seem to find in the manual, there are examples of spin code, and each line of spin code seems quite obvious what it does - write to a registry location, interact with a service call. But I don't understand the big picture. Where is this Spin code used? Catalina is a C program, so what is Spin doing there in the first place? I have some theories. Maybe the Spin is some code that is run via an separate spin interpreter cog (as discussed in the thread talking about Zog and Spin interacting). Maybe this Spin is part of Catalina itself, and once customised, requires a recompilation of Catalina to be used? Or maybe this Spin is included in a C program, in some sort of hybrid code?
I'm really sorry not to be able to grasp this concept, but having written 10 cogjects now, I just can't see how you can have any Spin code at all in a C program, surely it has to be pure PASM?
For example, I see this line of code in a program called "Catalina_Plugin.Spin", in a PUB called "start"
and the purpose of that line of code is completely clear and obvious. It sends over some parameterrs including one that is bit shifted. Simple.
Yet I cannot see how you can have any PUB code as part of a "plugin".
So - this is my problem really, as I just don't understand how plugins work.
But at the same time, I don't think I need to. I think that the solution to the problem I need to solve comes down to just two lines of code. One is a line in C, and one is a line of code in PASM.
The line of code in C is a function call that pauses Catalina until a certain hub memory location changes its value. I don't know what that function is, but I think it must be one of the lines of code either above or in some of the demo code.
And the second line of code is a line of code in PASM that will be a "wrlong" and will write a value to a location in hub near to the value of "registry". This will restart Catalina.
Any help here would be most appreciated,
Cheers, Drac.
Hopefully you can explain it to me simply.
The request value written must always be non-zero. All plugins must (at least occasionally) check their request long. The plugin can do whatever it likes with the request, but when it wants the kernel to continue from its paused state it does so by by writing a zero into the request long. Normally this indicates the request is complete, but this is not necessarilly the case - the plugin can carry on processing the request after it has allowed the kernel to continue if it needs to.
Note that you can also make a service call to a specific cog - just set bit 8 in the first parameter to the _sys_plugin function call - e.g: I allow this to cater for cases where there may multiple instances of the same plugin type running.
Yes - as described above, this is the first long of the request block assigned to the plugin. Set it to zero to restart the kernel that made the service request There is no SPIN code used, except (special case!) at boot time while Catalina sets things up for the kernel. There, I sometimes use SPIN code to do things, and sometimes PASM code. But once the kernel starts, everything can (must!) be done in C or PASM code. Since the Propeller effectively always boots into SPIN, Catalina uses SPIN as a means of starting the kernel. Each Catalina target is a SPIN program - it's job is to load the plugins, then start the kernel. Once the kernel is started, no Spin runs thereafter (unless you manually start another Spin interpreter in a free cog). No - you can manually start another SPIN interpreter - but unless you do so, no SPIN runs once the kernel is started. As I described above - there is no SPIN interpreter running once the kernel is started. That line is executed only on the very first load, while the target (a SPIN program) is still setting things up for the kernel, and before the kernel is running. If you look at the complex_example.c in custom_demo, you can see an example of loading, registering and unregistering a plugin entirely from C (except the registering part is currently commented out, since this example plugin registers itself). The problem is that you seem to believe it is much more complicated than it actually is! Okay! Good idea! The line you are looking for is any call to _sys_plugin. That's why I keep saying you will have to reinvent a similar mechanism if you don't use plugins. The line you are looking for is the line that writes a zero to the plugin's request long - in the example plugin in the custom target (i.e. Catalina_Plugin.spin) this is the PASM line labelled done_service.
I hope this helps. I really think you should use plugins - they are both simple and convenient, and support for them is "built-in" to Catalina at a very low level. However, if you decide to use another mechanism, you could develop one based on locks instead of memory locations. If all I had needed to do was "pause" the kernel temporarily, I might have used locks instead - the registry-based mechanism that Catalina uses is more complex, but it allows for the passing and returning of arbitrary data in addition to a simple pause/continue function.
Ross.
Hi David,
Thanks - I'll have a look at this example and see if I can figure out what the problem is. Might not be today though!
Ross.
How would I go about adding a mouse? The mouse is connected to the standard demo board pins and it works with Spin code. However, I have a feeling that because the original Dracblade did not have a mouse, the code does not include a mouse. In the compilation, there is reference to a VGA_nomouse.
My compile batch file is this:
and a printout of the compilation is thus:
What would I change to use a driver but with a mouse?
Hi Dr_A,
There a a couple of files that need changing. I have attached updated ones - just unzip them into your target directory (over the existing ones). Note that these files change the default behaviour to including the mouse driver. if you use these files but decide you DON'T want a mouse, you will have to add -D NO_MOUSE to all your compilation commands.
I assume your mouse is connected to pin 24 & 25. If not, change MOUSE_PIN in the DRACBLADE section of Catalina_Common.spin.
Ross.
For instance, GCC uses "-m" for machine-dependant options.
Just an update - there is definitely a problem with the caching XMM driver on the C3. I haven't quite tracked it down yet, but I hope to have it fixed in a day or two. Your abbreviated program helped a lot - thanks!
As to your question about conditionals - just use -W-DFOO. If you really dislike having to add the -W, then call lcc directly. The catalina program is really just a wrapper for lcc. To see the lcc command catalina generates, use the -v switch. For example, you will see that the command: Is equivalent to the command: If you don't plan to use the symbols Catalina automatically defines for you, you can simplify this a little to: The original few releases of Catalina actualy worked this way (i.e. there was no catalina program - you instead called lcc directly) but I had lots of complaints that the command line was too complex, so I wrote the catalina wrapper to simplify it. But using it is entirely optional, and you are always free to call lcc directly if you prefer. This is documented in the Catalina reference manual.
Ross.
Ross.
I tried it and it seems to work fine. Thanks for the suggestion!
I think I've finally tracked down the problem on the C3. It wasn't the cache after all - I simply wasn't copying the read/write segments correctly from the SPI Flash to the SPI RAM on program startup.
Can you verify the enclosed file fixes the problem? Just unzip this file over the existing version in your target directory. Then rebuild everything (including the utilities folder).
If this file works ok, then I'll tidy it up and issue a proper patch release (along with a couple of other very minor fixes).
Ross.
Hi Ross,
I tried this new code. First, I copied this to my target directory and then I rebuilt the utilities directory using the recommended "build_all C3 CACHED_4K FLASH" command and finally I rebuilt xbasic from scratch. I tried downloading this with payload several times all with the same result.
Did I miss a step somewhere?
Thanks,
David
That's odd - I rebuilt xbasic as well, and it worked for me. Can you zip up and post your actual xbasic binary here? I'll investigate it tonight.
Ross.
What gets written to C3 flash when I use payload to load a program? Is it just the entire contents of the .binary file? I'm asking because I'd like to convert my zogload program into a loader for Catalina.
Thanks,
David
I'm afraid I've continued to update xbasic so it is a little different from the one you built. I'm kind of tired tonight but I'm going to try this again in the morning to see if there is some mistake I made in applying your patch. The odd thing is that xbasic worked with the pre-release version of Catalina 3.0. I'm not sure why it is having trouble with the official release.
The platform-dependent loader is always a normal binary, and this load is always done using the Parallax binary load protocol.
The second binary can be either a normal binary or a Catalina LMM or XMM binary, and this load is done using the Catalina binary load protocol. The platform-dependent loader knows how to decode the different program types and memory layouts on the fly, and store the appropriate sections in the appropriate places (e.g. SPI Flash, SPI RAM or Hub RAM) depending on the memory layout specified in the binary file. Or at least it will when it is working properly! :frown:
The Catalina binary load protocol is described in the Catalina Reference Manual (pp 79).
Ross.
It doesn't really matter how the binary was produced - I just want one that is known to fail. The error message you are getting indicates it is the loader itself which is crashing when attempting to write a specific protocol packet to SPI Flash. I can't think of any reason why this should be the case - especially since I can successfully load much larger binaries on my C3. Possibly there is a corner case somewhere in my byte stuffing or LRC checking that only occurs when a specific sequence of binary data is received.
Ross.
I've done a clean installation of Catalina 3.0, copied the fixed version of the flash hub loader to the target directory, then recompiled the utilities folder and all my catalyst programs. I also recompiled the latest version I have of xbasic.
Every program I have now loads and runs perfectly on the C3. I can load them using the Payload serial loader or the Catalyst SD card loader - it even fixes a problem with the vi text editor that I hadn't gotten around to looking at yet!
I don't know what could be causing your problem except for an SPI Flash hardware failure, but if you can post a binary file that won't load, I'll investigate further.
Ross.
Thanks,
David
Ok. It differs according to the memory model and segment layout being used - but for Flash programs you only need to worrry about two of the seven supported layouts - for programs that are to be stored in Flash, layout 3 is used for LARGE programs, and layout 4 is used for SMALL programs.
Basically, the difference is that layout 3 arranges the segments as (init,data,code,cnst) and layout 4 arranges them as (cnst,init,data,code).
When LARGE programs are stored in Flash, the code and cnst segments are stored at their correct addresses for execution. Then, starting on the next sector boundary (i.e. hex $200 boundary) I store the sectors containing the init & data segments.
When SMALL programs are stored in Flash, the code segment is stored at its correct address for execution, then (again on the next sector boundary) I store the sectors containins the cnst, init & data segments.
The segments embedded in the stored sectors need to be relocated before the program can be run - this is the job of the Hub Flash loader, which is loaded into Hub RAM for execution once the Flash programming is complete. Alternatively, it can be run from EEPROM (this is really the main part of the Flash_Boot program - the remainder simply loads various device drivers the program might need).
I don't bother fully decoding the sectors containing the segments that need to be relocated - I just store them as they arrive serially, or as they are read from the SD card. This simplifies the process of storing them in Flash quite significantly, and allows the loader to fit it into a single cog. The Hub Flash loader will later extract and relocate the actual segments from the stored sectors - either to SPI RAM (LARGE) or Hub RAM (SMALL).
The segment layout being used and segment table itself is always stored in the first sector of the code segment. You'll see this referred to in the code as the "prologue". You need to use this information to figure out where in the binary data stream the segments start and finish. Interpreting the values in this table is also layout dependent - for examples of how to do this, see the code starting around line 2455 of the catbind program.
Ross.
I'm beginning to think you might be right about my SPI flash. That would be bad news since, as you know, the flash chip isn't replacable on the C3. I find that sometimes my loads fail and sometimes they succeed. I've played with it more this morning and I have been able to get xbasic to load and run. However, I can't seem to get SD card access to work after a reset when I program Flash_Boot into my C3. The xbasic interpreter comes up but 'load' doesn't work, it just hangs. This may be because I'm building it wrong though. I used the following command:
build_all C3 CACHED_4K FLASH SD
in the utilities directory. Should that be sufficient? I have to admit that I'm confused about when build_all is necessary. I had originally thought that I only had to do it once to select the board I was going to use, in this case the C3. Now I guess I also need to run it if I change the cache size and if I decide I want to use the SD card in my program. What I'm not sure about now is if I will get an SD driver in every program I build since I specified "SD" to get Flash_Boot built correctly. Should I consider running build_all to be part of the build process for every program and add it to the makefile?
Thanks,
David
For the C3, the built_all script in the utilities folder builds two utility programs - XMM.binary and Flash_Boot.binary.
You need to rebuild XMM.binary to match whatever cache size the programs it loads will use, so the CACHED and FLASH options must match what you used when you built the programs it will be used to load (BTW, the same is true of the Catalyst loader, should you ever build that).
Any other options you specify to build_all (like SD) only apply to the Flash_Boot.binary - they tell it what drivers to load before it executes the program stored in Flash. It is not necessary that Flash_Boot be built with the same options as the program was built originally - you can actually change the cache size or HMI drivers in Flash_Boot if you want. This is possible because what is stored in Flash is entirely above Catalina's Hardware Abstraction Layer, and what Flash_Boot loads is entirely below it. Of course, if the program is expecting some speciifc plugins to be present at run time (such as floating point plugins) then a version of them has to be loaded - but you can change which version.
Maybe I should have a separate build script for each utility - it might make things more obvious.
Ross.
Thanks David, I'll investigate further tonight.
Ross.