Allwinner H3
Tristan M. (2946) 1039 posts |
It’s about time I moved out of the hijacked thread and into one of my own. For quite a while I have been working on trying to get a port of RISC OS working on my Orange Pi PC. The real roadblock was my lack of knowledge, not the hardware. Perseverence pays off, I hope. The Allwinner H3 isn’t a bad SoC. Lots of useful features, and for the most part documented. The H3 and its relatives are used in a variety of devices. This first post is mostly a placeholder for now. It’ll get filled in when I have some time. |
Tristan M. (2946) 1039 posts |
Reserved for later. |
Tristan M. (2946) 1039 posts |
Current status: Functional in supervisor mode with no hardware support beyond the basics required to get it running.
Progress is being made. I have enough of a functional system to allow me to go back and work on the early boot with the knowledge that it will load a functioning system if correctly set up. |
Tristan M. (2946) 1039 posts |
I mostly fixed the pre OS_Start instability. For whatever reason now booting always gets stuck at InitDynamicAreas. Why could that be? |
Jeffrey Lee (213) 6048 posts |
Interrupts shouldn’t be enabled at that point (although I guess there’s always the chance of a non-maskable FIQ?), so it’s likely to either be an invalid RAM list that’s provided to OS_Start, or register/memory corruption from the handful of HAL calls that are made up to that point. |
Tristan M. (2946) 1039 posts |
Hmm… I dug through the timer and interrupt source. Couldn’t really find anything. Even went through and preserved scratch registers in timers.s just in case. What’s interesting are the random instruction or data aborts it can get during init. Also interesting is the text is garbled in *Help. It’s not random. Most of the characters are displaying a substitute ANSI character. I haven’t worked out what the bit corruption pattern is yet. It’s so weird. |
Tristan M. (2946) 1039 posts |
I’m certain I’ll regret this, but I put what I have in a GitHub Repository |
Leo Smiers (245) 56 posts |
First of all I like following your progress and struggles with the port to the AllWinner chip, likewise I also like following Michael Grunditz escapades. At line 18: AllWEinner should be AllWinner |
Michael Grunditz (467) 531 posts |
I follow this one and OrangePi closely, interesting since we are going to meet the same problems. I also get corrupted *Help. |
Jeffrey Lee (213) 6048 posts |
You regret that I’ll be able to help you by reviewing the code? :-) One problem is that you seem to have encountered a situation which Hdr2H can’t cope with – it looks like it doesn’t work properly with files that contain multiple structure definitions/storage maps. So instead of IO_BaseAddr being given an offset of zero, the C header has it at an offset of 84. It also looks like it struggles with the padding entries which use :INDEX:. A while ago I did suggest in an email to someone that a “H2Hdr” tool would be nice, since that would allow C code to use native C structs instead of messing around applying manual offsets to untyped pointers. Unfortunately I don’t think anything ever came of that. Perhaps, since parsing C can be as involved as parsing assembler, maybe it would make sense to introduce start from a third data definition language which is much easier to deal with. I think at one point I was also toying with the idea of using C & objasm macros to produce a data definition language that could be processed directly – but that may be a bit tricky since C wants parentheses around macro parameters while objasm doesn’t. Also I’m not seeing any makefile rules to cause Hdr2H to automatically run. Which makes things even more dangerous. Either way, your C workspace structs (and potentially other things like register layouts) are bogus, so until you get those fixed your C code isn’t going to work properly. Next problem: Your code for disabling the MMU looks a bit suspect – you’re flushing the TLB & branch predictors but not cleaning/invalidating (or even disabling) the cache. You also need an ISB after the MRC that disables the MMU, to make sure it actually turns off before the other instructions are executed. I was thinking of pointing you towards the code in the softload tool, but the code there isn’t exactly what I was expecting to see so maybe some of my assumptions are wrong. But making sure you disable & flush the caches before disabling the MMU would probably be a good place to start. |
Tristan M. (2946) 1039 posts |
It’s fine. I mean, yes there are things that Hdr2H can’t cope with. I know it complains about shifts eg ( 3 << 2 ) . There are currently no modules in C being built besides CLib, which isn’t even being used right now. So just ignore anything C in the source. The .h headers had to be fixed manually. The included ones are untouched Hdr2h ones. No good. Regarding turning off the MMU. That has been a troublesome one. Everything I have found on it has been different. You probably saw all the hacked about and commented code. I’m truly surprised you didn’t pick on all my StaticWS entries with 0 length and all the aliased definitions in headers. Although I have chopped things around a little, The iMx6, and OMAP3/4/5 Interrupts.s could be just about dropped in. Okay. it looks like I need to focus hard on the MMU and cache disabling again. If anyone is in the mood, could they please have a look at the BaseAddress macro in s.UART please? It’s referencing 4 sequential 4 byte entries in StaticWS, with a 0 byte entry above it so it can serve as being accessed by name or offset. The UART base addresses are &400 apart in memory. I don’t know why but I’m having a mental block with it. I think the GIC code should be working, but can’t really prove it as yet. The timer also should be initialised properly and ticking along. Because of the way it initialises I know that boot would get stuck if it didn’t. I learned this the hard way by dropping a write. PRINT TIME in BASIC consistently yields 0.
It should actually be Allwinner. I thought I had it right, but apparently not. Hopefully the video driver shouldn’t be hard. I believe I can use the iMx6 code. It just needs a little magic incantation beforehand to un-obfuscate the interface. |
Jeffrey Lee (213) 6048 posts |
That looks like it’s a typo. That register isn’t used by the HAL, so if it’s wrong it would have easily gone unnoticed.
Some of the UART entry points use multiple arguments, so by using a2 you’ll be corrupting those. Also the square brackets are missing from the LDR. This should work: ADRL ip, HALUART_Log LDR a1, [ip, a1, LSL #2] For the corrupt help text – I have a feeling that this can happen if specific modules are missing from the ROM. Probably TerritoryManager + UK (which should be safe to include at this point). |
Tristan M. (2946) 1039 posts |
Thanks as always. I’m working my way through, fixing a few things. I haven’t / don’t have much time currently. Later in the week hopefully some actual results will be seen. I’m not uploading any changes unless there’s an actual improvement. I found some a7 related cache etc code for clearing, turning off and invalidating. I have to go through and make my own to test. Thanks for straightening out the BaseAddr macro. I just had a really silly mental block. While I’m here, another thing. Not really relevant but the ADFS module has at least one SWP in it still. |
Chris Mahoney (1684) 2165 posts |
Looks like just one (in Adfs14). With that said, I thought I’d read somewhere that ADFS had been ported over to C (edit: here). |
Tristan M. (2946) 1039 posts |
While I have no use for any FS currently, I tried to build it anyway. That’s how I found out.
I added them without issue. Didn’t fix *Help though. It’s like it is loading a nonexistent codepage or something. I couldn’t care less about what *Help says, beyond it being a gauge of ability to execute code and data integrity. PRINT TIME in BASIC is still reading 0. While I do have some code missing in Timer.s, the init code should be setting a 3MHz clock with an interrupt firing @100Hz and enabling it. I did come up with an idea which I’ll have to try when I have a bit more time. Write some BASIC / asm test programs to spit out the contents of the logical mapped registers among other things. I realised because I’m using !Connector I could drag and drop basic listings into the terminal window :) It would be easy to have addresses spat out during HAL_Init, which I plan on doing. But I need to know what’s going on from a program’s POV too. That reminds me. I think it’s during OS_InitARM that the physical address of the SCU is printed to UART. I’m guessing that the kernel is determining this address somehow, somewhere in its debug code and printing it. e: I seem to have dropped a lot of square braces. That’ll do it. Time to go do another pass through the code. |
Tristan M. (2946) 1039 posts |
On second inspection, no I didn’t drop any braces. I’m still struggling a little with the hidden register and offset thing in workspaces with ObjAsm. I just put a bit of debug code in my copy in Timer_Init in Timers.s to print the timer value, wait a bit and do it again. It’s definitely decrementing. I still have to test if it’s actually auto-restarting like it should be. PRINT TIME in BASIC is still 0. All I can think is the timer decrements to 0 then stops after my test code runs. |
Michael Grunditz (467) 531 posts |
Your interrupts needs to be going. For me it was the fact that Interrupts driver subtracts 32 from every irq number. You can check that from basic. Add 32 from your Timer IRQ number and issue HAL_IRQSTatus from basic. (SYS"OS_Hardware",IRQnum,,,,,,,,,5)If it works it should give you > 0. You also need to be sure that the Timer actually generates a interrupt. |
Tristan M. (2946) 1039 posts |
Michael, I will give that a try when I’m back to working on it. I’m not really able to work on it for the next day or so. I did have a look at the unfinished timer code I pushed yesterday(?) and spotted an incorrect STR that would have caused major issues, but that code wasn’t tested as such. I pushed it so I could work on it from elsewhere. e: It’s actually a total mess. I’m going through fixing it. |
Tristan M. (2946) 1039 posts |
Done lots of tweaking. Filled out the UART code some more. Added more timer code. Did alterations to Top and Boot, and some more I can’t recall. Threw everything I could at resetting CPU state. Also brought the vector table back to the beginning of HAL again. I need to make it verbose or something. Is there something wrong with my AddRAM code? It’s the most frequent lockup point before MMU init.
etc. etc. I broke the last line down into three to show what’s going on there. It hits AddRAM. Makes it to a debug number I put in it’s kernel code. The SCU physical address is printed from ??? in the kernel code, and reboot. |
Tristan M. (2946) 1039 posts |
Two posts in a row, I know. I’ve been seeing issues with corruption, yes? I also haven’t been able to pin down what has been causing that and random lockups. That second execution of the timer init code has made me realise there’s an avenue I haven’t explored yet. What if all the cores are awake and U-boot just has all but one spinning. Or perhaps early code, maybe even InitARM wakes them up. Then what? It’d be chaos! I may well be wrong, but it would explain the nondeterministic nature of what I’m seeing. It would also explain why some locks are randomly occurring at points where they really shouldn’t be, like the second test read of the timer in Boot.s Perhaps it’s time to set up some core catching code. |
Tristan M. (2946) 1039 posts |
^H^H^H Forget about that. For some reason, what’s happening is that something is randomly triggering the undefined instruction vector. Something just inside RISCOS_Start, and something inside the MMU activation zone. Unfortunately I have no idea what, or why. |
Michael Grunditz (467) 531 posts |
The Timers isn’t used before MMU on. There are flags to to RISCOS_Stat.. look in my thread. |
Tristan M. (2946) 1039 posts |
I just want to check something. Things like the timers and UARTs are zero indexed with RO, right? |
Michael Grunditz (467) 531 posts |
I am not sure what you mean.. in my case the thr register is the same as base address . In the timer hal it is logical addresses. So the mmu must be on. But I suggest that you debug riscosstart FIRST. You will not get far without it. |
Tristan M. (2946) 1039 posts |
I mean that the first timer or UART number is 0, not 1. I assumed 0, however there is nothing which states this is actually the case. Besides filling in a little missing functionality in those two components, all I have been doing is working on the area around RISCOS_Start and HAL_Init. I have some ideas why the code sometimes gets stuck before reaching HAL_Init. I have reduced the frequency of it happening, but not completely stopped it. I’ve started working on some code that disables as much as possible early in boot. However it’s not clear how much use that will be. Some things occur after HAL_Init that really bother me. |