Orange Pi
Tristan M. (2946) 1039 posts |
Phone posting so please forgive my terseness. |
Tristan M. (2946) 1039 posts |
Disregard my CallOSM comment. I got confused. Way too many files open at once. It helps to have the CAllOSM macro in the right file. I tried to use OSEntries.h from export/blahblahblah with #include “Global/OSEntries.h” It can’t find the file. That’s the format I used and later found it included the same way in the OMAP4 source in the kernel. What is the correct way of using this file for my uses? I’ve been thinking about it and CallOSM might be gcc portable because there’s no memory protection as such. If I could be bothered anyway. Probably just slapping the entry points into function pointers would do it. |
Jeffrey Lee (213) 6048 posts |
Sounds like you need to use the
Well yes, all it does is call a function pointer. You just need to be careful with the addressing schemes used. The table in the OS image header will store offsets (relative to the header); CallOSM will convert that to an actual address. There’s a second macro, CallOS, which just fetches a pre-computed address straight from the HAL workspace (but is only suitable for use once the HAL has initialised that table) |
Tristan M. (2946) 1039 posts |
Ooh. Good point about the addressing methods. Although the code exploded in a different way, I worked out how to #include files from the Export directory at least.
which caused:
Fair enough. At least I know it found a file. It’s late and I’m going to bed. HalEntries.h wasn’t added to the dynamic dependencies, and I don’t feel like working that out right now. It probably does need the path added like you said. Would that be “C:Global”? Probably a silly question to most. But I am working with a system which was totally foreign to me. I’m starting to work it out in bits and pieces. Shortcuts are still nice though! |
Jeffrey Lee (213) 6048 posts |
C:Global/HALEntries.h:22:0: error: ignoring #pragma force_top_level [-Werror=unknown-pragmas] Since you’re using -Wall + -Werror, that’s easy enough to fix. -Wno-unknown-pragmas.
Probably because the compilation failed. I know GCC does have some rules for what headers are/aren’t included in the dependencies, but I think that’s mostly based on whether you use quotes or angled brackets to include them.
Looking at the StdTools GNUmakefile I think you’ll want |
Tristan M. (2946) 1039 posts |
Odd. Thought I’d replied. -Wno-unknown-pragmas works. Thanks. Didn’t know about that. Haven’t messed with the other details yet. Was busy messing with adding more functionality to get it closer to doing something useful. On that subject… What magic makes the register aliases work? objasm isn’t recognising the v, a, etc register names. It just spits out “E Bad register name symbol”. What haven’t I included to make them work? I haven’t actually tested the code in forever but I’d rather get it to the point where it should be doing some interesting things and debug from there. It’s sort of up to AddRAM, which on it’s own isn’t much. I could probably “port” the code to assembly and have it go further in about 1/2 hour even with my poor assembly skills. But that’s not why I’m doing it. The way I see it, getting a decent amount of the HAL up and running in C can allow for some structure and modularity which could make porting more easily accessible to people that otherwise wouldn’t touch it. |
Jeffrey Lee (213) 6048 posts |
I’m not sure; chances are they’re only enabled if you specify an APCS option on the command line (since the assignments can be different depending on which APCS variant you specify). Normally the APCS variant should be specified automatically by the alias that’s set up by Library.ToolOptions.APCS-32. |
Tristan M. (2946) 1039 posts |
Thanks. You’ve given me a starting point. Something has been lost along the way. I fixed the longstanding broken symbol issue with one of my UART functions that I mentioned before. Removing a function from the return statement and adding a few extra steps fixed it. For some reason DDE’s linker tripped over on that. I have another question. I noticed OMAP3 and BCM2835 use the base address of 0xFC00 0000. This is post MMU init, surely because not everything has RAM to the top of the address space. So why is the RO “ROM” relocated to near the top of physical RAM if early in the HAL init it’s just going to be shuffled to the top of the address space by the MMU anyway? |
Jeffrey Lee (213) 6048 posts |
Correct. Theoretically the HAL should be fully position-independent; one of the original goals of the HAL was to make it OS-agnostic (or at least RISC OS version agnostic), so it shouldn’t make any assumptions about what logical address it gets mapped to. But in reality we always supply combined HAL + OS images, so as long as you’re careful with things pre-MMU you shouldn’t run into any problems by assuming a fixed logical base address.
There are a few things that relocating the ROM to the high or low end of physical RAM helps with:
IIRC the “relocate to high end” logic was originally borrowed from the Tungsten (Iyonix) HAL. It could have easily been the low end of RAM. |
Rick Murray (539) 13840 posts |
:-) I’ve lost count of the number of times I’ve “thrown something together” to test an idea, with the intention of going back and revising it later, and then not doing so “because it works perfectly well”. Everything is cool until one revisits the code years later and, like, “was I drunk when I wrote this?”. The worst thing of all is when something is refusing to work so lots of ideas get thrown at the issue until it works, but by then the comments might as well be for an entirely different program! |
Clive Semmens (2335) 3276 posts |
Whistles innocently… |
Tristan M. (2946) 1039 posts |
There’s thrown together and there’s what I have. The result of learning about something, and feeling my way with something new. At least my files are more comments than actual code so I can decipher the mess. This isn’t so much about software but I learned a few things about the Orange Pi PC and the AllWinner H3 in general this morning. UART debugging is the most I’ve ever had available to use on anything so I don’t feel as though I’m missing out on anything. However if I had the slightest idea of a way how to use a JTAG of some description on it, it’d be very useful. Progress is still being made by the way. I just had to leave it for a day because I fell into C types / pointers / lvalues hell while working on ROM relocation and consequent reset in C… because I’m quite probably insane. e: a misplaced ‘*’ can cause a lot of hassle in C. It theoretically gets as far as: It also has really basic UART support. TX and RX. Apparently it’s meant to fail silently with FIFO overflows? I’ll have to remove the checking code. |
Tristan M. (2946) 1039 posts |
I fed the OPi PC an OS image with partial HAL yesterday. Instant data abort before it even output the initial “Hello, world” to UART. U-boot stepped back in, running very slowly and rebooted the system. All I can think is I stepped on its toes. Time to go digging. |
Tristan M. (2946) 1039 posts |
Well, at least I can tell that it got as far as setting up the stack. This is just from the linked HAL binary without the ROM image. It failed earlier than it should have. It should have printed “Hello, world” to the UART, with a single ‘X’ before it as a basic sanity check. If I assume I’ve made a mistake and I broke the UART debugging output, the registers get even weirder. Assuming the HAL made it to the first step of copying everything to 0×7C00 0000, it has somehow ended up with the PC and LR too low in memory. This is going to be “fun”. There isn’t even a sane PC to use as reference. Time to add back some more hardwired debugging output, and feed a complete OS image to it again too. Oh, to add extra fun, it looks like at some point in the past few months they have shifted the loading address of linux up a little so there’s more to chase down. |
Jeffrey Lee (213) 6048 posts |
pc : [<75814944>] lr : [<40fffade>] reloc pc : [<418aa944>] lr : [<0d095ade>] Hmm. Is that version of u-boot running with the MMU enabled or something? It’s odd that it would give two sets of addresses like that (unless it’s just the crash recovery code which runs with the MMU enabled?) It’s probably worth including the SCTLR in your first bit of debug output, just in case there’s something unusual with the environment u-boot sets up. |
Tristan M. (2946) 1039 posts |
I believe you are correct. At some point in the past few months things have been changed. I didn’t see any documentation, however /boot/boot.cmd had something very telling. In the script, the kernel is being loaded at 0×0000 0000. Hope you don’t mind the spaces. I just find eight digits together a bit unpleasant. e: no, wait. Looking harder, what seems to happen is legacy kernels are loaded into a proper physical address. Mainline kernels perhaps load a small loader to the SRAM and then I guess it does the rest. So now I have to figure out why even the original demo program isn’t outputting to UART. |
Jeffrey Lee (213) 6048 posts |
Unless you’re able to find the magic option to disable the changes, I’d try and stick with the older u-boot, if possible. RISC OS isn’t designed to boot with the MMU enabled, so you’d need extra changes to make it work (either disable the MMU in your HAL or improve the OS’s boot). If your u-boot is a moving target then you can also expect to run into other problems every so often, e.g. peripherals which are powered on in one version but turned off in the next. That’s extra hassle that you won’t want to deal with when you’re still trying to get the OS up and running.
And there was me thinking that u-boot was meant to be the small loader :-) |
Tristan M. (2946) 1039 posts |
I swear I must be hallucinating. Earlier I tried it with the mainline SD card in. Didn’t work for me. Final time around, after manually comaring the binaries for the original blink.bin demo to make sure I had the right one (they were identical) I tried it and saw “Hello, World!”. That was with a 0×4100 0000 base address. So no MMU loaded. Okay so now it’s just back to my code being broken. Speaking of broken code, I manually pulled what I hope is the full compliment of files and made the tree for them. It’s just based off the OMAP3 CVS, and uses DDE27 and gcc4.7.4 It is a mess. I won’t pretend it’s not. I’m feeling my way with learning the internals of RO, the build system, writing a HAL, and making the whole mess work with gcc. if anyone is silly enough to try it, yes the makefile is meant to spit out all those warnings. I think I need to make a light stub for DDE or something so I can use everything at once. I didn’t clean the HAL, so there’s the linked binary and objects to look at in there. Also it should be in mixed, not castle. It’s just that’s where OMAP3 was. I haven’t changed it yet. |
Rick Murray (539) 13840 posts |
That’s what I thought on 23rd June 2016. And 19th December 2016. And 29th March 2017. Now I just wish I was hallucinating. [gets coat and shuffles away mumbling incoherently] |
Tristan M. (2946) 1039 posts |
I had to check those dates. Roughly what I thought they were. Personally I’d love to move to New Zealand, or Canada. e: I think I added the missing files now. It gave me a slightly different link this time. Don’t know which will work better. YMMV I guess. https://drive.google.com/open?id=0B0Wrq2By8rzWU3pBRk1KZW41YUE |
Tristan M. (2946) 1039 posts |
I probably won’t be able to have a go at fixing my mess for another couple of weeks, but I do have a few ideas. This is based off fuzzy recollection by the way. If I recall, a branch appeared to be landing a few words too high, missing the frame stuff for a C function. I need to revisit this and work out why. There is a possibility that at some point my C functions for reading and writing to memory broke. They did work, I swear! It’s trivial to substitute assembly routines again. It’s what I was using originally anyway. Using C for the hardware access is more of a proof of concept thing. Definitely not for efficiency! I might see if I can get an OpenOCD jtag setup going on it. Not sure how successful it would be. The pins are there on the OPi PC GPIO header. I think I mentioned that before. I saw OpenOCD seems to have been ported to ESP32, so that might be worth trying because of the higher clock speed than an esp8266. |
Tristan M. (2946) 1039 posts |
In a real time crunch right now, but I did revisit the code. Tore out some stuff and added some including assembly. I know it breaks really early after starting execution, but how early and why is still a little mysterious. The confusing thing is that the code near the beginning looks a lot like blink.bin’s code, yet the blink demo still works. |
Jeffrey Lee (213) 6048 posts |
Your code is “interesting”, to say the least. I know you’ve said before that you’ve been using C since the 90’s, but judging by the large number of comments throughout the source I get the feeling that you’re not yet fully comfortable with it. Likewise with the assembler sources (although that’s a bit more forgivable if you’re not familiar with system-level ARM assembler, or interworking C and ARM). A few bits that caught my eye: In the Notes file: CallOSM(entry, param){ ip = RO_Base + (entry*4); //4 bytes = 1 32 bit word. void (*HdrFn) (unsigned int); HdrFn = ip; //I think the "*4" is implicit in C - No it isn't - //adding it may be A Bad Idea (c) HdrFn( param ); } I know this is pseudocode, but it’s probably worth pointing out that it’s wrong just in case. The correct equivalent of CallOSM would be: CallOSM(entry, param){ // LDR ip, [v8, #$entry*4] ip = RO_Base + (entry*4); ip = *((int *) ip); // ADD pc, v8, ip HdrFn = RO_Base + ip; HdrFn( param ); } In s.Top, you effectively have the following: reset mov sp,#&40000000 add sp,sp,#&1000 MSR CPSR_c, #F32_bit+I32_bit+SVC32_mode There are some CPU registers which are “banked” so that they map to different physical registers in different CPU modes. In most modes this is R13, R14, and the SPSR. So if u-boot isn’t calling you in SVC mode, your SP setup is useless, because it will only be affecting whatever mode you were entered in. Next, RISCOS_AddRAM: ; extern void *RISCOS_AddRAM(unsigned int flags, void *start, void *end, uintptr_t sigbits, void *ref); ;r0 flags, r1 start address of RAM segment, r2 end address, r3 ???, r4 address of handle if it exists. ;so why is this only using from r0 to r3??? RISCOS_AddRAM ;So these should be correct already. ;mvn r3, #0 ;mov r0, #0 ;str r1,[sp, #-4]! ;I don't understand this. Is it putting sp -4 in r1? CallOSM OS_AddRAM str r0,[sp] ;return data in current stack pointer? mov pc, lr ;branch back.
roio.c: //really basic debug print. Trying to fix the proper debug_print. void dbg_prnt(char* msg){ while (!*msg){ POKE32((UART_0+UART_THR),*msg); msg++; } POKE32((UART_0+UART_THR),0x0d); POKE32((UART_0+UART_THR),0x0a); } This routine would be much more useful if you changed the while condition to RAM.c: // void *RISCOS_AddRAM(unsigned int flags, void *start, void *end, uintptr_t sigbits, void *ref); //does it return the handle needed for subsequent calls? Yes. The ref value will also be needed when you call OS_Start. Other: It’s possible the compiler is using r11 for its own purposes (I can’t see any obvious flag/pragma which is protecting it). So your assembler routines might be losing track of where the OS header is. (With Norcroft this is handled by declaring a special I’m sure I could find more things to comment on, but I should probably get back to work! |
Rick Murray (539) 13840 posts |
Just to add:
It is storing R1 to the address SP-4, writing back to SP. It is functionally the same as STMFD R13!, {R1} without being silly and using a multiple register instruction to write a single register. ;-) |
Clive Semmens (2335) 3276 posts |
Now there’s another tiny tangle of wasted instruction set space I don’t think anyone’s considered repurposing… 8~) |