Towards BeagleBoard "CMOS RAM"
Pages: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ... 18
Dave Higton (281) 668 posts |
Just as we do now, look at disc address &C00 to see if it’s a RISC OS boot sector. Doing that and looking at partition types for a RISC OS partition are not mutually exclusive!
I repeat: there is no authority in charge of assigning disc format identifiers for use in partition tables. So the way we “get one assigned” is to take one, and, like reserved sectors, hope our use of it doesn’t clash with anyone else’s. That system has served the computing industry for decades now. |
Dave Higton (281) 668 posts |
A little bit more progress: I’ve calculated the addresses of all the MMCHS1 registers I need to access, using assembly language. It’s easy enough. However, I wrote all my application code in C, and I need to start integrating an appropriately modified version of that code with the HAL. I’ve got some undefined symbols that the linker is complaining of:
|
Jeffrey Lee (213) 6048 posts |
There’s no way that I know of to get an ordinary global to work properly; you’ll have to get access to everything using a pointer to a struct, or by writing assembler functions that return pointers to each variable directly. I think my advice would be the following: First, rearrange StaticWS so that the end looks like this: ASSERT (:INDEX:@) <= 1024 # (1024-(:INDEX:@)) CWorkSpace # 1024 SDMAWS # SDMA_WorkspaceSize HAL_WsSize * :INDEX:@ Note that you’ll have to delete the original SDMAWS line, and the NVRAMCache line (if you still have it). What this new layout will do is give you 1K of space at an offset of 1K from the sb register. So to make use of this space you’ll want to define a C structure as follows: typedef struct { char pad[1024]; int my,stuff,goes,here; } workspace; And change ’__global_reg(6) void *sb’ to ’__global_reg(6) workspace *sb’. Then (assuming all your globals are now members of the ‘workspace’ struct) you should be able to access them from anywhere via sb. This system isn’t perfect (there’s no method in place to detect when the ‘workspace’ struct grows over 2K in size and clobbers SDMAWS), but it’s orobably the best method we currently have available. Note that I chose an offset of 1K from sb to keep everything within the 4K LDR/STR range. But SDMAWS is pretty big (around 5K), so had to be moved to after the C workspace. In fact when you compile the code you should get an error when compiling s.SDMA; the ADR at line 111 needs changing to an ADRL. Hopefully once you move all your statics/globals into the workspace struct the _Mod$Reloc$Off linker error will go away. |
Dave Higton (281) 668 posts |
Jeffrey, I have to thank you again, and also apologise to you, because I’m going to make a bit more work for you – because I only understand part of what you wrote above. This is beyond my understanding and experience. I’m with you in general terms as to declaring a struct, and addressing it via v6, thus solving one of the linker errors. However, I don’t understand those pseudo-ops at the end of the workspace, I don’t understand why you want to create space for variables offset from v6 (why offset at all?), and I don’t know whether the above has any impact on the NVMemory cache, which is 2 kiB on its own. As soon as I put in any variable, my workspace (including NVMemory cache) is by definition over 2 kiB. If the cache is a separate entity, then there’s no problem. |
Jeffrey Lee (213) 6048 posts |
One of the problems with interworking C and assembler is that (to my knowledge) there’s no automated tool available to convert a C struct definition into an assembler structure, or vice-versa. This means that you can’t easily add space in StaticWS for C variables to be stored. So the approach I suggested above was to store both the assembler and C variables in the same structure, but organise the structure in such a way that the two sets of variables are stored seperately from each other. This system won’t allow C code to easily access assembler variables (or vice-versa), but it will help make sure that the memory used by the C variables doesn’t overlap the memory used by the assembler variables. From the perspective of the ARM code, v6 will point to a structure with the following layout: Offset Contents 0-1023 The majority of the ARM variables 1024-2047 All the C variables, but stored in an opaque block. The ARM code has no idea where each variable is stored within that block. 2048+ SDMAWS And from the perpsective of the C code, it points to a struct like this: typedef struct { char pad[1024]; // Offset 0-1023: The majority of the ARM variables, but stored in an opaque block. int my,stuff,goes,here; // Offset 1024+: All the C variables } workspace; The exact size of the C workspace struct doesn’t matter, as long as it doesn’t grow larger than 1K (i.e the offset at which CWorkSpace starts) plus the size of the CWorkSpace entry itself (currently 1K).
You’ve got to remember that when you’re in the HAL, v6 will almost always point to the same location – the HAL’s workspace. So when it comes time to decide where to store C variables, we have two choices – store them at a known position in the HAL workspace and access them directly via v6, or store them somewhere else and add an assembler function which will tell the C code where those variables are. The first choice results in slightly tricky workspace management, but results in better code (since the compiler can now use v6 instead of leaving it well alone), and is easier to integrate with existing C code (since you won’t need to pass a workspace struct pointer to each and every function that wants workspace access). And the reason why the C workspace has to be at an offset to v6 is quite simple – because it has minimum impact on the existing assembler. If you moved the assembler variables around too much then you’d have to change lots of ADRs to ADRLs. Plus the assembler code assumes that the boardconfig struct is stored at offset 0 from v6.
If you want to keep the NVMemory cache then you can easily add it to the C workspace struct. Just make sure that the size of the CWorkSpace entry in StaticWS is kept in check (i.e. increase it by 2K). Of course doing that will bump the start of SDMAWS to above the 4K LDR offset range, so you might get some compile errors. Looking at the code it looksl ike there are only a couple of ADRs that would need converting to ADRLs, so this shouldn’t be a big problem (and in fact when I just tried compiling with a 4K CWorkSpace size, there weren’t any compile errors at all) If you want any variables (e.g. the cache) to be accessible by both C and assembler then I’d recommend placing them at the start of the C workspace area (i.e. just after the 1K ‘pad’ array in the C struct, and just before the CWorkSpace line in hdr.StaticWS). That way (assuming the two struct definitions are kept in sync) it’ll be easy for both pieces of code to access the variables. Don’t worry about decreasing the size of the CWorkSpace entry when you do this; all that really matters is that the size of the C-only variables are less than the size of CWorkSpace. |
Dave Higton (281) 668 posts |
Well, I’ve not managed to get the magic incantations right yet. Here’s what I get: cc -zM -zps1 -c -depend !Depend -ff -fah -o o.NVMem c.NVMem Norcroft RISC OS ARM C vsn 5.68 [25 Jun 2009] "c.NVMem", line 7: Serious error: type disagreement for 'NVMem_workspace' "c.NVMem", line 7: Error: linkage disagreement for 'NVMem_workspace' - treated as 'extern' "c.NVMem", line 7: Fatal internal error: rd_decl/init(0x160800) Internal inconsistency: either resource shortage or compiler fault. If you cannot alter your program to avoid this failure, please contact your supplier NVMem_workspace is extern. |
Jeffrey Lee (213) 6048 posts |
That might be your problem then (assuming NVMem_workspace is what you’ve renamed sb to in the C code). For me, this works: __global_reg(6) workspace *NVMem_workspace; But this results in an ordinary compiler error (storage class ’__global_reg’ incompatible with ‘extern’): extern __global_reg(6) workspace *NVMem_workspace; |
Jeffrey Lee (213) 6048 posts |
Hmm – it looks like you’ve done something like this, as it will generate the exact same internal inconsistency error for me: typedef struct { ... } workspace; extern workspace *NVMem_workspace; __global_reg(6) void *NVMem_workspace; |
Dave Higton (281) 668 posts |
I think I can see what I’ve done wrong. It’ll have to wait until tonight, though. Oh, the suspense… |
Trevor Johnson (329) 1645 posts |
Indeed… and I hope you get a good turn-out for tomorrow’s meeting ! |
Steve Revill (20) 1361 posts |
Sounds like another one to add to the bug tracker? |
Dave Higton (281) 668 posts |
The big step forward is that the C now compiles. (I have no idea yet whether it will work.) The step back: SDMA fails with one ADR out of range error (no surprise, and easy to fix), but five ASSERT errors. I’ve just wasted a long time failing to get grep to work, but I’ve got it going now, and I’m on the case. |
Jeffrey Lee (213) 6048 posts |
Those asserts might just be down to everything going wrong when the ADR failed to compile, so I’d start by fixing that and then see if any of the others still fail. |
Jeffrey Lee (213) 6048 posts |
Your wish is my command, although the inconsistent way that formatting is handled has once again turned the bug report into an unintelligible mess :( |
Jess Hampshire (158) 865 posts |
Does that mean that the standard partition sector lives in a place untouched by an ADFS format? ie, you could format a drive under 3.7 to 2GB then add the partition sector and mark the first 2GB as ADFS, and then have other partitions only visible to a partition aware version of RO5? |
Dave Higton (281) 668 posts |
I believe so. If you generalise that to partitions of DOS types, I think it has always been true that it is possible to have an ADFS-formatted section at the start, with boot sector at byte address &C00, with the normal partition table near the top of the first sector, and with those partitions placed after the RISC OS section. So long as the other OS doesn’t overwrite the RISC OS boot sector – which is something that I think has come in more recently – then all can coexist without interference. Extrapolate from that to the case where all the partitions are of type RISC OS. |
Dave Higton (281) 668 posts |
Well, I can only get it to compile if I don’t address anything within the workspace. If I do, I get this error: cc -zM -zps1 -c -depend !Depend -ff -fah -o o.NVMem c.NVMem Norcroft RISC OS ARM C vsn 5.68 [25 Jun 2009] "c.NVMem", line 50: Serious error: illegal left operand to '.' c.NVMem: 0 warnings, 0 errors, 1 serious error The line in question is: printf ("PRCM_mapped = %X\n", NVMem_workspace.PRCM_mapped); and PRCM_mapped is a uint variable within the struct. As far as I can see, that should be correct. Any ideas? |
Jeffrey Lee (213) 6048 posts |
You’re going to kick yourself for this one – NVMem_workspace is a pointer, so you should be using |
Dave Higton (281) 668 posts |
Indeed I did, metaphorically speaking. I posted and shut down to go to bed. While I was cleaning my teeth, the realisation dawned. :-( I’ve made the change this morning, and it builds OK. |
Dave Higton (281) 668 posts |
It even works, sort of… all I did from the C was to print out the contents of a couple of locations. They are clearly not the right locations, but I can look at that tonight. Is there any good reason why I can’t substitute my own value for v6 before I call my C, assuming I restore it afterwards? |
Jeffrey Lee (213) 6048 posts |
You’d need to restore it before you call any of the HAL functions. E.g. printf internally uses HAL_DebugTX. |
Dave Higton (281) 668 posts |
Good answer. Thanks. In fact I’m wondering if the simplest answer is to pass a pointer to the workspace as an argument to all my calls to the C, then I don’t need to go about rearranging the static workspace at all. |
Dave Higton (281) 668 posts |
I didn’t have the energy to do much last night, but I have confirmed that passing a pointer to my workspace in a1 works. As a matter of interest it’s between 5 kB and 6 kB above v6. So, tonight and this weekend, I hope to start talking to the SD/MMC interface from C code in the HAL. |
Dave Higton (281) 668 posts |
OK, we’re cooking again. I have begun to port the application C to the HAL. It’s a slow process so far, but I am getting the same results as when it was an application. I think the porting process should speed up later on when I get to the higher level stuff. |
Dave Higton (281) 668 posts |
How do I call a HAL function from within the HAL? Silly question. I call the relevant function. |
Pages: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ... 18