I'll check the Forum postings later on this morning to see if you found something.
Don't hurry back. It will take me some time to dissect the EEPROM dumps. They don't look correct to me - which is promising - but I can't figure out how some of the stuff in there got there!
@Wingineer19 - BTW - If you had put a quarter of your effort so far into Tachyon instead, you would be finished and working on the next version of your software, without the need for any kind of fancy memory expansion. Just saying. (dig dig )
Perhaps, but you would have to account for the time necessary to come up to speed on Forth, as I haven't done any type of even rudimentary Forth programming in nearly 30 years.
However, it's ability to immediately test and debug the Word without having to go through the C compiling, linking, and debugging process would no doubt speed things up.
I've not ruled out ultimately using Forth, but right now I'm too lazy to ramp up on it, so while I insanely continue struggling and stumbling through my C program with XMM memory, I'm also working with @RossH to shake out some bugs and add some new features to Catalina that no doubt would benefit other users of the compiler. So from that perspective I see it as a 360-win scenario.
Don't hurry back. It will take me some time to dissect the EEPROM dumps. They don't look correct to me - which is promising - but I can't figure out how some of the stuff in there got there!
I took a look at a couple more programs.
One was Sumeria.c, which compiled to a little less than 64KB. I uploaded it to my Project Board and it seems to work OK.
Thinking that maybe we're looking at a 64KB limit issue, I grabbed Startrek.c and compiled it to 88KB. I uploaded it to the Project Board, and it seems to work fine too.
So much for the 64KB limitation theory.
I went back and reviewed the MenuTest.c program. It works fine using XMM SRAM. I again recompiled it to include the EEPROM loader, with a total size a bit more than 71KB. I uploaded it to the Project Board, and it still doesn't work. A lot of crazy characters before locking up the screen.
We have one program less than 64KB that works.
Another one that's nearly 90KB that works.
And one that's around 71KB that doesn't work with the EEPROM loader, but does work with XMM SRAM. This program uses the 4-Port serial driver, while the other two use the TTY driver.
Could the different serial drivers cause an issue?
I have confirmed that the EEPROM is being programmed correctly. The stuff I saw in there that I couldn't understand seems to be parts of Tachyon, left in the EEPROM because Catalina only programs the sections of EEPROM it uses - and they were all ok.
You can confirm this if you like by adding -d to the payload command, and verifying which parts of the EEPROM Catalina is actually programming, using a command like:
payload EEPROM program.binary -d
For example, here is what I see (adjust the -p parameter to suit your port):
The areas I couldn't explain were all in those areas not programmed (e.g. in the "skipping Null" sections).
I also now think that the program may be loading correctly from the EEPROM, because apart from the fact that we had smaller programs execute correctly, your program seemed to run correctly once. Also, I just re-read this snippet (my bold):
It just puts a bunch of garbage on the screen. If you hit a key the initial Main Menu appears, but then it locks up after that. No further response.
To get far enough to display the menu, the program code must have loaded correctly (at least up to that point). The fact that you see garbage on the sceeen beforehand means there is some Hub RAM memory corruption. It may be some peculiar hardware interaction between your XMM RAM and your EEPROM, such that reading from one and writing to the other is causing corruption, but which only occurs for larger programs (we know it works for smaller programs). To test this, we can try a slightly larger program - one that is known to work when compiled as SMALL and executed from the EEPROM - my old favorite startrek.c, which is in your "demos" folder.
To do this, use commands like:
cd demos
catalina startrek.c -lc -lm -C CUSTOM -C SMALL -C CACHED_1K -C EEPROM -C TTY
payload EEPROM startrek.binary -i
If this works, we can keep trying larger and larger programs.
Another possibility is that it is something specific to your program. Here are a few things we can try:
1. The cache might be getting corrupted if you are running low on Hub RAM. Can you please try compiling your program with a 1K cache and loading it - i.e. something like:
2. There may be some destructive interaction between the specific plugins you use and the 3rd stage EEPROM loader. For me to investigate this, I will need a copy of your current program source code so that I can recompile it for my platform and investigate.
Perhaps, but you would have to account for the time necessary to come up to speed on Forth, as I haven't done any type of even rudimentary Forth programming in nearly 30 years.
However, it's ability to immediately test and debug the Word without having to go through the C compiling, linking, and debugging process would no doubt speed things up.
I've not ruled out ultimately using Forth, but right now I'm too lazy to ramp up on it, so while I insanely continue struggling and stumbling through my C program with XMM memory, I'm also working with @RossH to shake out some bugs and add some new features to Catalina that no doubt would benefit other users of the compiler. So from that perspective I see it as a 360-win scenario.
I was actually taking that into account because it is not like learning a language, and then trying to use it. With Forth as you would know, you use it, you learn it. Start small at the bottom and then incrementally the routines that you write become the tools to test out and debug the system. While it may seem slow at first, your rewards are received as you go, and productivity increases proportionally.
I was actually taking that into account because it is not like learning a language, and then trying to use it. With Forth as you would know, you use it, you learn it. Start small at the bottom and then incrementally the routines that you write become the tools to test out and debug the system. While it may seem slow at first, your rewards are received as you go, and productivity increases proportionally.
My Forth friend would agree with you 100%. He despised C and couldn't understand why anyone would want to mess with such an horrific language
Ok - got the sources, and they compile ok. I have to go out for a few hours, but I'll start investigating when I get back.
It looks like getting the s4 serial driver to work with this is a lost cause.
Yes, I also suspected the 4 port serial driver, which I am looking at now. It is a direct port of a Spin driver, and I think its use of Hub RAM is conflicting with other plugins in a way that only really shows up when it is being used by a largish program which is being loaded using the EEPROM loader.
However, don't worry - if that is all the problem amounts to, it is quite fixable.
My Forth friend would agree with you 100%. He despised C and couldn't understand why anyone would want to mess with such an horrific language
Without knocking Forth, people use C because (apart from a few now well-known "gotchas") it is actually a very small, simple and straighforward language.
Also, being the longest-lived "universal" language, you find that in many cases much of what you need already exists somewhere.
Without knocking Forth, people use C because (apart from a few now well-known "gotchas") it is actually a very small, simple and straighforward language.
Also, being the longest-lived "universal" language, you find that in many cases much of what you need already exists somewhere.
Also, C is scaleable.
Yes, I've been programming in C for quite some time now and am quite comfortable with it. Like any computer language, it took time to get used to. At my former employer it's the only language I used for embedded systems work.
Many years ago I had a short course on Forth, did a little bit of programming using it, found it interesting, but never did an in-depth dive on it. Eventually I would like to revisit it, but now it appears that Python is the going thing, so I guess I need to look at it as well...
Yes, I also suspected the 4 port serial driver, which I am looking at now. It is a direct port of a Spin driver, and I think its use of Hub RAM is conflicting with other plugins in a way that only really shows up when it is being used by a largish program which is being loaded using the EEPROM loader.
However, don't worry - if that is all the problem amounts to, it is quite fixable.
It looks like excellent progress has been made today, as apparently we narrowed the problem down to the 4-Port serial driver.
I have some questions about your EEPROM loader, as well as your XEPROM API, and their potential integration into the FLiP module with external memory, but that can wait for another day.
And with that being said, I'm going to call it a night.
I found a problem with the initialization of the 4 port serial driver. The symptoms I see are similar to what you saw - i.e. you get some Smile on the screen, then the main menu comes up, but then the program freezes.
What I think is happening is that the 3 currently unused ports (ports 1, 2 & 3) were not being initialized, and are interfering with the one currently used port (port 0). It seems likely that when you load the program serially the relevant portion of Hub RAM is usually zero, but when you load from EEPROM this memory is used by the EEPROM loader itself and is being set to something that is causing the problem. The fix was to just zero this memory during initialization of the serial4 plugin.
I have attached a new version of Catalina_FullDuplexSerial4FC.spin which does this - put it in your target directory, then recompile your program and let me know how it goes.
Ross.
P.S. When you do need to use the other 3 serial ports, be aware that you will need to edit the file "Extras.spin" in the target directory. It should be fairly clear what you need to do, but ask if you have any questions.
P.P.S. I noticed while investigating that there is a later version of the 4 port serial driver, which fixes a few minor issues (unrelated to the one I just found, which was entirely my own fault!). I will include the later version in the next release.
P.P.P.S While messing about, I tried all the caching options - 1K, 2K, 4K and 8K. They all seem to work with your program now, whereas I think you had trouble with 8K before? Also, I had to use the XEPROM XMM option, since I don't have your XMM RAM hardware, so I can confirm that this works as well with your program. This will also be in the next release.
I found a problem with the initialization of the 4 port serial driver. The symptoms I see are similar to what you saw - i.e. you get some Smile on the screen, then the main menu comes up, but then the program freezes.
Yeah, what I saw was that it was repeatedly writing "Parallax Miniplate Participant" so fast that it was flickering on the screen. When I hit a key, the Main Menu came up, and then froze. So the problem was consistent across platforms.
What I think is happening is that the 3 currently unused ports (ports 1, 2 & 3) were not being initialized, and are interfering with the one currently used port (port 0). It seems likely that when you load the program serially the relevant portion of Hub RAM is usually zero, but when you load from EEPROM this memory is used by the EEPROM loader itself and is being set to something that is causing the problem. The fix was to just zero this memory during initialization of the serial4 plugin.
I have attached a new version of Catalina_FullDuplexSerial4FC.spin which does this - put it in your target directory, then recompile your program and let me know how it goes.
Ross.
It works! I'm elated!
P.S. When you do need to use the other 3 serial ports, be aware that you will need to edit the file "Extras.spin" in the target directory. It should be fairly clear what you need to do, but ask if you have any questions.
To be on the safe side, I went ahead and defined the other S4 pins within the Extras.spin file: S4.AddPort(0,31,30,-1,-1,0,0,115200)
S4.AddPort(1,17,16,-1,-1,0,0,115200)
S4.AddPort(2,15,14,-1,-1,0,0,115200)
S4.AddPort(3,13,12,-1,-1,0,0,115200)
P.P.P.S While messing about, I tried all the caching options - 1K, 2K, 4K and 8K. They all seem to work with your program now, whereas I think you had trouble with 8K before?
Well, I just tried other cache options, and all work except for the 8K. So the problem remains
Also, I had to use the XEPROM XMM option, since I don't have your XMM RAM hardware, so I can confirm that this works as well with your program. This will also be in the next release.
Since you brought up the subject of XEPROM, and recalling that I recently said this:
I have some questions about your EEPROM loader, as well as your XEPROM API, and their potential integration into the FLiP module with external memory, but that can wait for another day.
Now is as good a time as any to go there.
I want to focus on the FLiP module, so let's have a discussion about EEPROM physical memory mapping.
If we had a single, large EEPROM (like 256KB) that replaced the existing 64KB on the FLiP, we would have a contiguous block of EEPROM memory that physically maps from $00000 to $3FFFF. So, your EEPROM loader is free to use whatever segments within this space to do its thing. Likewise, the XEPROM API is free to execute my Program Code from anywhere within this block, as specified by your compiling process.
Keeping the 64KB EEPROM on the FLiP module, however, introduces a problem. Although I would like to actually replace this 64KB with 256KB, I don't want to risk damage to the module (which is likely if I tried).
So, my only option is to add the 256KB EEPROM externally. But the 256KB EEPROM only has a single Device Address Bit, A2, which effectively allows me to map the EEPROM from address space $0000 to $3FFFF, or from $4000 to $7FFFF.
I can't choose the former because it overlaps and conflicts with the existing 64KB EEPROM space used by the FLiP, so I must choose the latter.
With our two EEPROMs, we now have this physical addressing: $0000_0000 to $0000_FFFF (Internal 64KB EEPROM)
$0001_0000 to $0003_FFFF (Nothing)
$0004_0000 to $0007_FFFF (External 256KB EEPROM)
As you can see, this arrangement is not contiguous, and thus poses a problem.
Unless, of course, there's a way to provide Addressing information to both the EEPROM Loader, and the XEPROM API, telling them that I only want to use that external 256KB memory to store/load/execute my Program Code, and not mess with the internal 64KB memory.
Somewhere within your EEPROM Loader and XEPROM API there has to be a constant or variable that specifies the starting address of the Program Code.
Within the XEPROM API Definition file, I found this:
' This file contains definitions for using EEPROM as XMM. The EEPROM must
' be larger than 32k to be used for XMM (note that a 64k EEPROM is better
' used as CMM or LMM, which can be done using just the EEPROM loader).
'
}
'============================= XMM DEFINITIONS =================================
'
' XMM Base Address. Catalina currently requires one contiguous block
' of XMM RAM - Note that this is the internal hardware address, not
' the address the Catalina XMM Kernel uses:
'
XMM_BASE_ADDRESS = $0000_0000 ' XMM adddressing from 0
'
' XMM RW & RO Base Addresses - Note that these are the addresses used
' by the Catalina XMM Kernel - they typically start AFTER the last
' Hub address:
'
XMM_RW_BASE_ADDRESS = $0000_8000 ' Read-Write Base address (not used)
'
XMM_RO_BASE_ADDRESS = $0000_8000 ' Read-Only Base address
'
' XMM RW & RO Sizes (in bytes):
'
XMM_RW_SIZE = -1 ' Read-Write Size (not used)
'
' The following symbol is currently used only by the XMM RAM Test program
' (which is not really relevant for executing XMM code from EEPROM) but it
' may eventually be used elsewhere, so it should be set. It is currently set
' for a 128k EEPROM:
'
XMM_RO_SIZE = $0002_0000 ' Read-Only Size (for a a 128k EEPROM)
'
' This value determines the size of the cache index:
'
CACHE_INDEX_LOG2 = 7 ' log2 of entries in cache index
'
'========================== END OF XMM DEFINITIONS =============================
So it appears that: XMM_RO_BASE_ADDRESS = $0000_8000
does specify the starting address, while: XMM_RO_SIZE = $0002_0000
sets the EEPROM size.
Does this mean that if I do this: XMM_RO_BASE_ADDRESS = $0004_0000
and this: XMM_RO_SIZE = $0004_0000
that the XEPROM code will execute from the 256KB EEPROM?
If so, that's fantastic.
How do I convey this Addressing information to the actual EEPROM Loader?
It would need to know this regardless of whether it will ultimately have the XEPROM API execute Program Code from the 256KB EEPROM itself, or if it instead copies the EEPROM Program Code over to the SRAM for execution by the SRAM XMM API.
So I guess the question is, how do you tell the EEPROM Loader where to store the actual Program Code, and is there a way to tell it to store it in the external 256KB EEPROM?
P.P.S. I noticed while investigating that there is a later version of the 4 port serial driver, which fixes a few minor issues (unrelated to the one I just found, which was entirely my own fault!). I will include the later version in the next release.
Just as long as you keep your new s4_txcheck() function, all should be well
To be on the safe side, I went ahead and defined the other S4 pins within the Extras.spin file: S4.AddPort(0,31,30,-1,-1,0,0,115200)
S4.AddPort(1,17,16,-1,-1,0,0,115200)
S4.AddPort(2,15,14,-1,-1,0,0,115200)
S4.AddPort(3,13,12,-1,-1,0,0,115200)
Yes, that looks ok. Note that the newer version of the 4 port serial driver seems to include bug fixes for the 3 upper ports, mostly to do with the RTS/CTS handling (which it seems from the above you don't intend to use) - but in any case I will have that version out soon.
Well, I just tried other cache options, and all work except for the 8K. So the problem remains
I will look at that again when I have some time. It may be related to your XMM API code.
I want to focus on the FLiP module, so let's have a discussion about EEPROM physical memory mapping.
I had a quick look at the FLiP module. It should be supported "out of the box", but I may add a new symbol for it (-C FLIP) in the next release.
If we had a single, large EEPROM (like 256KB) that replaced the existing 64KB on the FLiP, we would have a contiguous block of EEPROM memory that physically maps from $00000 to $3FFFF. So, your EEPROM loader is free to use whatever segments within this space to do its thing. Likewise, the XEPROM API is free to execute my Program Code from anywhere within this block, as specified by your compiling process.
All correct.
Keeping the 64KB EEPROM on the FLiP module, however, introduces a problem. Although I would like to actually replace this 64KB with 256KB, I don't want to risk damage to the module (which is likely if I tried).
So, my only option is to add the 256KB EEPROM externally. But the 256KB EEPROM only has a single Device Address Bit, A2, which effectively allows me to map the EEPROM from address space $0000 to $3FFFF, or from $4000 to $7FFFF.
I can't choose the former because it overlaps and conflicts with the existing 64KB EEPROM space used by the FLiP, so I must choose the latter.
With our two EEPROMs, we now have this physical addressing: $0000_0000 to $0000_FFFF (Internal 64KB EEPROM)
$0001_0000 to $0003_FFFF (Nothing)
$0004_0000 to $0007_FFFF (External 256KB EEPROM)
As you can see, this arrangement is not contiguous, and thus poses a problem.
Yes, it would be a problem. However, that problem goes away if you use a FLASH chip instead of an EEPROM. Catalina would then work with without much effort - just a fairly simple new XMM API. Catalina already has such an API for a module that is essentially just a FLASH chip - look at the FlashPoint SuperQuad API.
It is possible you could use an EEPROM in this way as long as it is on its own I2C bus - i.e. 2 pins. But why not use a FLASH chip?
Unless there's a way to provide Addressing information to both the EEPROM Loader, and the XEPROM API, telling them that I only want to use that external 256KB memory to store/load/execute my Program Code, and not mess with the internal 64KB memory.
Simple - don't use the XEPROM API, use a new FLASH API.
Somewhere within your EEPROM Loader and XEPROM API there has to be a constant or variable that specifies the starting address of the Program Code.
Within the XEPROM API Definition file, I found this:
' This file contains definitions for using EEPROM as XMM. The EEPROM must
' be larger than 32k to be used for XMM (note that a 64k EEPROM is better
' used as CMM or LMM, which can be done using just the EEPROM loader).
'
}
'============================= XMM DEFINITIONS =================================
'
' XMM Base Address. Catalina currently requires one contiguous block
' of XMM RAM - Note that this is the internal hardware address, not
' the address the Catalina XMM Kernel uses:
'
XMM_BASE_ADDRESS = $0000_0000 ' XMM adddressing from 0
'
' XMM RW & RO Base Addresses - Note that these are the addresses used
' by the Catalina XMM Kernel - they typically start AFTER the last
' Hub address:
'
XMM_RW_BASE_ADDRESS = $0000_8000 ' Read-Write Base address (not used)
'
XMM_RO_BASE_ADDRESS = $0000_8000 ' Read-Only Base address
'
' XMM RW & RO Sizes (in bytes):
'
XMM_RW_SIZE = -1 ' Read-Write Size (not used)
'
' The following symbol is currently used only by the XMM RAM Test program
' (which is not really relevant for executing XMM code from EEPROM) but it
' may eventually be used elsewhere, so it should be set. It is currently set
' for a 128k EEPROM:
'
XMM_RO_SIZE = $0002_0000 ' Read-Only Size (for a a 128k EEPROM)
'
' This value determines the size of the cache index:
'
CACHE_INDEX_LOG2 = 7 ' log2 of entries in cache index
'
'========================== END OF XMM DEFINITIONS =============================
So it appears that: XMM_RO_BASE_ADDRESS = $0000_8000
does specify the starting address, while: XMM_RO_SIZE = $0002_0000
sets the EEPROM size.
Does this mean that if I do this: XMM_RO_BASE_ADDRESS = $0004_0000
and this: XMM_RO_SIZE = $0004_0000
that the XEPROM code will execute from the 256KB EEPROM?
If so, that's fantastic.
Sorry to disappoint, but most of those constants are not used anywhere except in the RAM Test code. I originally defined them and used them, then discovered that there was really no need for most of them. Even their use in the RAM Test code is probably unnecessary.
How do I convey this Addressing information to the actual EEPROM Loader?
I don't know of any means to specify Addressing information to the Loader telling it where to get the Program Code from EEPROM...
It would need to know this regardless of whether it will ultimately be executing Program Code from the 256KB EEPROM itself using the XEPROM API, or if it simply needs to ship the Program Code to SRAM for execution by the SRAM XMM API.
So I guess the question is, how do you tell the EEPROM Loader where to store the actual Program Code, and is there a way to tell it to store it in the external 256KB EEPROM?
The short answer is "no".
The longer answer is "maybe, if you were willing to do a lot of work"
But the best answer is to just use a FLASH chip (or an EEPROM) on its own I2C bus. Is there a specific reason you don't want to use this option? Is it just to save the 2 pins?
So I guess the question is, how do you tell the EEPROM Loader where to store the actual Program Code, and is there a way to tell it to store it in the external 256KB EEPROM?
The longer answer is "maybe, if you were willing to do a lot of work"
But the best answer is to just use a FLASH chip (or an EEPROM) on its own I2C bus. Is there a specific reason you don't want to use this option? Is it just to save the 2 pins?
Yes, reducing (or ideally eliminating) the number of pins required to access external memory could allow me to discard some multiplexers and latches needed to access other devices the propeller will be working with, thus reducing circuit complexity.
The program execution speed will be the determining factor, though, as to whether or not I can go with the I2C EEPROM approach or the Flash one. There's going to be a lot of UART serial traffic the prop will have to manage, so the I2C approach might not be able to keep up, even with an 8K cache enabled.
An indicator could be how fast you saw the various MenuTest screens updating when you were running XEPROM. If the GPS Command Screen was updating pretty quickly then there's a chance the EEPROM approach might work. If it was moving at a snail's pace, then Flash wins.
Bottom line, it sounds like what I want to do for this test, namely executing Program Code from the external EEPROM, could be accomplished if I write the Flash API to work with it instead of a Flash chip. Which is what I've been assuming all along, and was supposed to be working on this week. I was just hoping I could take a short cut if your XEPROM API would let me do that instead.
Of course I could still run the test using my USB Project Board, which has the 256KB EEPROM installed instead of the 64KB one, if the XEPROM API was working. I just tried doing that using the XEPROM API you posted, but Catalina aborted the compiling process with a lot of errors:
I know you cautioned me that it probably wouldn't work, but I wanted to try it anyway. My bad
Oh, is there a particular reason why you mentioned using a separate I2C bus instead of the one currently used by the internal 64KB EEPROM and the external 256KB one?
I thought I would be able to adjust the addressing within the Flash API in order to direct traffic to the external 256KB EEPROM on the bus?
Of course I could still run the test using my USB Project Board, which has the 256KB EEPROM installed instead of the 64KB one, if the XEPROM API was working. I just tried doing that using the XEPROM API you posted, but Catalina aborted the compiling process with a lot of errors:
However, the XEPROM API needs a few tweaks to various other files in the target directory. Wait till the next release to use it.
Oh, is there a particular reason why you mentioned using a separate I2C bus instead of the one currently used by the internal 64KB EEPROM and the external 256KB one?
I thought I would be able to adjust the addressing within the Flash API in order to direct traffic to the external 256KB EEPROM on the bus?
I'm not sure about this one. I don't know enough about I2C. I guess if you don't need to access the EEPROM after boot time, the same I2C bus can be used for exclusive access to the other EEPROM just by using the appropriate device address. If so, then this is probably your answer.
@Wingineer19 - pssst - this guy is as crazy as you
@RossH - pssst - this guy is as crazy as you
Is there an echo in here?
But if eeprom is only being accessed at 100kHz rates surely it would benefit if it could read at 1MHz rates.
The existing I2C driver should work at 400khz if the EEPROM supports it. Beyond that we'd just have to try it and see. Just like EEPROMs larger than 128kb, I don't think EEPROMs supporting 1MHz bus speeds were around when this driver was written, but it might be able to support it. It's probably worth a try.
However, the advantages of faster bus speeds are not as dramatic as you might think, because of the use of the cache. With a large enough cache, doubling the bus speed only gives you a small improvement. Of course, it depends on how linear the code is - if the code consists of small functions or loops that can fit entirely into the cache, you may get no improvement at all.
@Wingineer19 - pssst - this guy is as crazy as you
@RossH - pssst - this guy is as crazy as you
@"Peter Jakacki" - you're talking to yourself again
LOL. I just now saw this after I got back from dinner. Too much excitement here!
But if eeprom is only being accessed at 100kHz rates surely it would benefit if it could read at 1MHz rates.
We know the AT24CM02 can support 1MHz bus speed. Tachyon proved that a couple of days ago once I lowered the pullup resistors to around 2K each.
Btw, it would be fairly easy to replace the eeprom without damage. It's only 8 pins and desolders with a hot iron and a blob of solder.
For a normal person, yes. In my case, I would likely break the circuit board in half, while simultaneously covering everything with an entire spool of solder
If only there was a P1X1 module that had 256KB EEPROM installed...
An L2 cache in hub ram could hold a larger chunk which would leverage sequential read speeds. What size is your cache and how is it organised?
Cache size can be 1K, 2K, 4K or 8K of Hub RAM. Organized as pages of 8 - 8K bytes, configurable depending on the cache size and the platform.
For more detail I'd have to refer to the code.
EDIT: I just realized you could go up to a page size of 8K if you reduced the cache to a single page. Not that you would, but I think the code supports it.
I'm not sure about this one. I don't know enough about I2C. I guess if you don't need to access the EEPROM after boot time, the same I2C bus can be used for exclusive access to the other EEPROM just by using the appropriate device address. If so, then this is probably your answer.
I'm pretty sure it will work just as long as the API sends the proper address values to confine access between $0004_0000 and $0007_FFFF on the bus.
I guess I will find out once I write the Flash (EEPROM) API...
Cluso99 already has tiny P8XBlade2 modules and could supply them with 256kB I'm sure but I have a ton of various modules I have designed such as the P8 which also has Flash. What are your requirements in terms of size, power, I/O etc?
BTW, you would be surprised how easy it is to remove a small SMD component. Blob some solder onto both sides of the chip and then with a hot iron and a larger tip and some more solder just run that tip on either side a couple of times and the chip falls off. Hot air from a gas iron works well too and you just pick up the part with tweezers. Failing that just cut the leads of the old chip with a exacto pen by pressing on the pins so that the package comes loose and then use a solder blob on a big tip to draw the remnants off the board in one quick action.
An L2 cache in hub ram could hold a larger chunk which would leverage sequential read speeds. What size is your cache and how is it organised?
Cache size can be 1K, 2K, 4K or 8K of Hub RAM. Organized as pages of 8 - 8K bytes, configurable depending on the cache size and the platform.
For more detail I'd have to refer to the code.
EDIT: I just realized you could go up to a page size of 8K if you reduced the cache to a single page. Not that you would, but I think the code supports it.
The 512KB SRAMs I use consist of two, 256KB SRAMs on the same die. I believe they will support sequential access up to the 256KB limit, in which case you must terminate the process and restart since you can't cross the die boundary.
Looking at the 256KB AT24CM02 EEPROM, it appears to support sequential reads up to the maximum 256KB limit, then rolls back over to location $0. Page writes are limited to 256 bytes each.
Comments
Don't hurry back. It will take me some time to dissect the EEPROM dumps. They don't look correct to me - which is promising - but I can't figure out how some of the stuff in there got there!
Perhaps, but you would have to account for the time necessary to come up to speed on Forth, as I haven't done any type of even rudimentary Forth programming in nearly 30 years.
However, it's ability to immediately test and debug the Word without having to go through the C compiling, linking, and debugging process would no doubt speed things up.
I've not ruled out ultimately using Forth, but right now I'm too lazy to ramp up on it, so while I insanely continue struggling and stumbling through my C program with XMM memory, I'm also working with @RossH to shake out some bugs and add some new features to Catalina that no doubt would benefit other users of the compiler. So from that perspective I see it as a 360-win scenario.
I took a look at a couple more programs.
One was Sumeria.c, which compiled to a little less than 64KB. I uploaded it to my Project Board and it seems to work OK.
Thinking that maybe we're looking at a 64KB limit issue, I grabbed Startrek.c and compiled it to 88KB. I uploaded it to the Project Board, and it seems to work fine too.
So much for the 64KB limitation theory.
I went back and reviewed the MenuTest.c program. It works fine using XMM SRAM. I again recompiled it to include the EEPROM loader, with a total size a bit more than 71KB. I uploaded it to the Project Board, and it still doesn't work. A lot of crazy characters before locking up the screen.
We have one program less than 64KB that works.
Another one that's nearly 90KB that works.
And one that's around 71KB that doesn't work with the EEPROM loader, but does work with XMM SRAM. This program uses the 4-Port serial driver, while the other two use the TTY driver.
Could the different serial drivers cause an issue?
I have confirmed that the EEPROM is being programmed correctly. The stuff I saw in there that I couldn't understand seems to be parts of Tachyon, left in the EEPROM because Catalina only programs the sections of EEPROM it uses - and they were all ok.
You can confirm this if you like by adding -d to the payload command, and verifying which parts of the EEPROM Catalina is actually programming, using a command like:
For example, here is what I see (adjust the -p parameter to suit your port):
The areas I couldn't explain were all in those areas not programmed (e.g. in the "skipping Null" sections).
I also now think that the program may be loading correctly from the EEPROM, because apart from the fact that we had smaller programs execute correctly, your program seemed to run correctly once. Also, I just re-read this snippet (my bold):
To get far enough to display the menu, the program code must have loaded correctly (at least up to that point). The fact that you see garbage on the sceeen beforehand means there is some Hub RAM memory corruption. It may be some peculiar hardware interaction between your XMM RAM and your EEPROM, such that reading from one and writing to the other is causing corruption, but which only occurs for larger programs (we know it works for smaller programs). To test this, we can try a slightly larger program - one that is known to work when compiled as SMALL and executed from the EEPROM - my old favorite startrek.c, which is in your "demos" folder.
To do this, use commands like:
If this works, we can keep trying larger and larger programs.
Another possibility is that it is something specific to your program. Here are a few things we can try:
1. The cache might be getting corrupted if you are running low on Hub RAM. Can you please try compiling your program with a 1K cache and loading it - i.e. something like:
2. There may be some destructive interaction between the specific plugins you use and the 3rd stage EEPROM loader. For me to investigate this, I will need a copy of your current program source code so that I can recompile it for my platform and investigate.
We'll get there in the end!
Yes, I think it may be related to the plugin you use. Something is interacting badly with the 3rd stage loader.
As I said in the last email, can you post your entire source code so I can investigate?
I posted both Sumeria and Startrek earlier (see previous post), and both of them worked fine.
But I used the TTY serial driver when compiling them. My MenuTest program uses the 4-Port serial driver. Check your emails. I decided to email them to you instead of posting them here on the Forum.
Let me know if there's any problems getting it to compile
Ok - got the sources, and they compile ok. I have to go out for a few hours, but I'll start investigating when I get back.
However, I changed the code to use the tty functions instead of the s4 ones, and it works fine.
Here's the sample GPS Command Screen
And here's the sample GPS Raw Data Screen (The display is real, the data is fake -- for now):
I went into the CduPort.c file and changed all s4 references to tty.
Under Code::Blocks I went to Project >> Build options >> libtty instead of libserial4.
Then recompiled, uploaded to the Project Board, and the Menus work fine.
Unfortunately, for this Project I need at least 3 serial ports (CduPort, GpsPort, WiFiPort), which compels me to use the s4 library.
The question, then, is how and why is the s4 driver messing with the EEPROM loader (or vice versa)…
I was actually taking that into account because it is not like learning a language, and then trying to use it. With Forth as you would know, you use it, you learn it. Start small at the bottom and then incrementally the routines that you write become the tools to test out and debug the system. While it may seem slow at first, your rewards are received as you go, and productivity increases proportionally.
My Forth friend would agree with you 100%. He despised C and couldn't understand why anyone would want to mess with such an horrific language
Yes, I also suspected the 4 port serial driver, which I am looking at now. It is a direct port of a Spin driver, and I think its use of Hub RAM is conflicting with other plugins in a way that only really shows up when it is being used by a largish program which is being loaded using the EEPROM loader.
However, don't worry - if that is all the problem amounts to, it is quite fixable.
Without knocking Forth, people use C because (apart from a few now well-known "gotchas") it is actually a very small, simple and straighforward language.
Also, being the longest-lived "universal" language, you find that in many cases much of what you need already exists somewhere.
Also, C is scaleable.
Many years ago I had a short course on Forth, did a little bit of programming using it, found it interesting, but never did an in-depth dive on it. Eventually I would like to revisit it, but now it appears that Python is the going thing, so I guess I need to look at it as well...
It looks like excellent progress has been made today, as apparently we narrowed the problem down to the 4-Port serial driver.
I have some questions about your EEPROM loader, as well as your XEPROM API, and their potential integration into the FLiP module with external memory, but that can wait for another day.
And with that being said, I'm going to call it a night.
Well, I think I have some good news ...
I found a problem with the initialization of the 4 port serial driver. The symptoms I see are similar to what you saw - i.e. you get some Smile on the screen, then the main menu comes up, but then the program freezes.
What I think is happening is that the 3 currently unused ports (ports 1, 2 & 3) were not being initialized, and are interfering with the one currently used port (port 0). It seems likely that when you load the program serially the relevant portion of Hub RAM is usually zero, but when you load from EEPROM this memory is used by the EEPROM loader itself and is being set to something that is causing the problem. The fix was to just zero this memory during initialization of the serial4 plugin.
I have attached a new version of Catalina_FullDuplexSerial4FC.spin which does this - put it in your target directory, then recompile your program and let me know how it goes.
Ross.
P.S. When you do need to use the other 3 serial ports, be aware that you will need to edit the file "Extras.spin" in the target directory. It should be fairly clear what you need to do, but ask if you have any questions.
P.P.S. I noticed while investigating that there is a later version of the 4 port serial driver, which fixes a few minor issues (unrelated to the one I just found, which was entirely my own fault!). I will include the later version in the next release.
P.P.P.S While messing about, I tried all the caching options - 1K, 2K, 4K and 8K. They all seem to work with your program now, whereas I think you had trouble with 8K before? Also, I had to use the XEPROM XMM option, since I don't have your XMM RAM hardware, so I can confirm that this works as well with your program. This will also be in the next release.
S4.AddPort(0,31,30,-1,-1,0,0,115200)
S4.AddPort(1,17,16,-1,-1,0,0,115200)
S4.AddPort(2,15,14,-1,-1,0,0,115200)
S4.AddPort(3,13,12,-1,-1,0,0,115200)
Well, I just tried other cache options, and all work except for the 8K. So the problem remains Since you brought up the subject of XEPROM, and recalling that I recently said this: Now is as good a time as any to go there.
I want to focus on the FLiP module, so let's have a discussion about EEPROM physical memory mapping.
If we had a single, large EEPROM (like 256KB) that replaced the existing 64KB on the FLiP, we would have a contiguous block of EEPROM memory that physically maps from $00000 to $3FFFF. So, your EEPROM loader is free to use whatever segments within this space to do its thing. Likewise, the XEPROM API is free to execute my Program Code from anywhere within this block, as specified by your compiling process.
Keeping the 64KB EEPROM on the FLiP module, however, introduces a problem. Although I would like to actually replace this 64KB with 256KB, I don't want to risk damage to the module (which is likely if I tried).
So, my only option is to add the 256KB EEPROM externally. But the 256KB EEPROM only has a single Device Address Bit, A2, which effectively allows me to map the EEPROM from address space $0000 to $3FFFF, or from $4000 to $7FFFF.
I can't choose the former because it overlaps and conflicts with the existing 64KB EEPROM space used by the FLiP, so I must choose the latter.
With our two EEPROMs, we now have this physical addressing:
$0000_0000 to $0000_FFFF (Internal 64KB EEPROM)
$0001_0000 to $0003_FFFF (Nothing)
$0004_0000 to $0007_FFFF (External 256KB EEPROM)
As you can see, this arrangement is not contiguous, and thus poses a problem.
Unless, of course, there's a way to provide Addressing information to both the EEPROM Loader, and the XEPROM API, telling them that I only want to use that external 256KB memory to store/load/execute my Program Code, and not mess with the internal 64KB memory.
Somewhere within your EEPROM Loader and XEPROM API there has to be a constant or variable that specifies the starting address of the Program Code.
Within the XEPROM API Definition file, I found this: So it appears that:
XMM_RO_BASE_ADDRESS = $0000_8000
does specify the starting address, while:
XMM_RO_SIZE = $0002_0000
sets the EEPROM size.
Does this mean that if I do this:
XMM_RO_BASE_ADDRESS = $0004_0000
and this:
XMM_RO_SIZE = $0004_0000
that the XEPROM code will execute from the 256KB EEPROM?
If so, that's fantastic.
How do I convey this Addressing information to the actual EEPROM Loader?
It would need to know this regardless of whether it will ultimately have the XEPROM API execute Program Code from the 256KB EEPROM itself, or if it instead copies the EEPROM Program Code over to the SRAM for execution by the SRAM XMM API.
So I guess the question is, how do you tell the EEPROM Loader where to store the actual Program Code, and is there a way to tell it to store it in the external 256KB EEPROM?
Just as long as you keep your new s4_txcheck() function, all should be well
It is possible you could use an EEPROM in this way as long as it is on its own I2C bus - i.e. 2 pins. But why not use a FLASH chip?
Simple - don't use the XEPROM API, use a new FLASH API. Sorry to disappoint, but most of those constants are not used anywhere except in the RAM Test code. I originally defined them and used them, then discovered that there was really no need for most of them. Even their use in the RAM Test code is probably unnecessary.
The short answer is "no".
The longer answer is "maybe, if you were willing to do a lot of work"
But the best answer is to just use a FLASH chip (or an EEPROM) on its own I2C bus. Is there a specific reason you don't want to use this option? Is it just to save the 2 pins?
Yes, that will be in the next release.
The program execution speed will be the determining factor, though, as to whether or not I can go with the I2C EEPROM approach or the Flash one. There's going to be a lot of UART serial traffic the prop will have to manage, so the I2C approach might not be able to keep up, even with an 8K cache enabled.
An indicator could be how fast you saw the various MenuTest screens updating when you were running XEPROM. If the GPS Command Screen was updating pretty quickly then there's a chance the EEPROM approach might work. If it was moving at a snail's pace, then Flash wins.
Bottom line, it sounds like what I want to do for this test, namely executing Program Code from the external EEPROM, could be accomplished if I write the Flash API to work with it instead of a Flash chip. Which is what I've been assuming all along, and was supposed to be working on this week. I was just hoping I could take a short cut if your XEPROM API would let me do that instead.
Of course I could still run the test using my USB Project Board, which has the 256KB EEPROM installed instead of the 64KB one, if the XEPROM API was working. I just tried doing that using the XEPROM API you posted, but Catalina aborted the compiling process with a lot of errors: I know you cautioned me that it probably wouldn't work, but I wanted to try it anyway. My bad
Oh, is there a particular reason why you mentioned using a separate I2C bus instead of the one currently used by the internal 64KB EEPROM and the external 256KB one?
I thought I would be able to adjust the addressing within the Flash API in order to direct traffic to the external 256KB EEPROM on the bus?
@RossH - pssst - this guy is as crazy as you
@"Peter Jakacki" - you're talking to yourself again
But if eeprom is only being accessed at 100kHz rates surely it would benefit if it could read at 1MHz rates.
Btw, it would be fairly easy to replace the eeprom without damage. It's only 8 pins and desolders with a hot iron and a blob of solder.
However, the XEPROM API needs a few tweaks to various other files in the target directory. Wait till the next release to use it.
I'm not sure about this one. I don't know enough about I2C. I guess if you don't need to access the EEPROM after boot time, the same I2C bus can be used for exclusive access to the other EEPROM just by using the appropriate device address. If so, then this is probably your answer.
The existing I2C driver should work at 400khz if the EEPROM supports it. Beyond that we'd just have to try it and see. Just like EEPROMs larger than 128kb, I don't think EEPROMs supporting 1MHz bus speeds were around when this driver was written, but it might be able to support it. It's probably worth a try.
However, the advantages of faster bus speeds are not as dramatic as you might think, because of the use of the cache. With a large enough cache, doubling the bus speed only gives you a small improvement. Of course, it depends on how linear the code is - if the code consists of small functions or loops that can fit entirely into the cache, you may get no improvement at all.
If only there was a P1X1 module that had 256KB EEPROM installed...
Cache size can be 1K, 2K, 4K or 8K of Hub RAM. Organized as pages of 8 - 8K bytes, configurable depending on the cache size and the platform.
For more detail I'd have to refer to the code.
EDIT: I just realized you could go up to a page size of 8K if you reduced the cache to a single page. Not that you would, but I think the code supports it.
I guess I will find out once I write the Flash (EEPROM) API...
BTW, you would be surprised how easy it is to remove a small SMD component. Blob some solder onto both sides of the chip and then with a hot iron and a larger tip and some more solder just run that tip on either side a couple of times and the chip falls off. Hot air from a gas iron works well too and you just pick up the part with tweezers. Failing that just cut the leads of the old chip with a exacto pen by pressing on the pins so that the package comes loose and then use a solder blob on a big tip to draw the remnants off the board in one quick action.
The 512KB SRAMs I use consist of two, 256KB SRAMs on the same die. I believe they will support sequential access up to the 256KB limit, in which case you must terminate the process and restart since you can't cross the die boundary.
Looking at the 256KB AT24CM02 EEPROM, it appears to support sequential reads up to the maximum 256KB limit, then rolls back over to location $0. Page writes are limited to 256 bytes each.