Rockbox Development > Starting Development and Compiling
Beginning steps in kernel disassembly and analysis
dconrad:
--- Quote ---use rockbox.bin.
--- End quote ---
Aha... That would definitely be a problem, even if it isn't the problem. I'm still not getting any signs of life, but it looks like usbboot is happy enough with it now:
--- Code: ---[root@localhost ingenic_tools]# ./usbboot --verbose --cpu x1000 --stage1 ../../build-erosqnative-boot/spl.erosq --wait 5 --stage2 ../../build-erosqnative/rockbox.bin
Opening USB device a108:1000
Issue SET_DATA_ADDRESS 0xf4001000
Transfer 10296 bytes from host to device
Issue PROGRAM_START1 0xf4001800
Wait 5 seconds
Issue SET_DATA_ADDRESS 0x80004000
Transfer 746968 bytes from host to device
Issue FLUSH_CACHES
Issue PROGRAM_START2 0x80004000
[root@localhost ingenic_tools]#
--- End code ---
I'll keep poking at it tomorrow, definitely don't feel like you have to rush to review my patchset by any means.
Edit: Unless you meant that the spl binary is also subject to this scramble header and needs to be .bin? I thought I had tried that and got an error message, but I'll try again in the morning.
dconrad:
Life!
I can get the screen to flash the backlight by calling spl_error() from just after init in spl-x1000.c:
--- Code: ---void spl_main(void)
{
/* Basic hardware init */
init();
spl_error();
/* If doing a USB boot, host PC will upload 2nd stage itself,
* we should not load anything from flash or change clocks. */
if((boot_sel & 3) == 2)
return;
/* Just pass control to the target... */
spl_target_boot();
}
--- End code ---
It's not much, but it's a starting point. It looks like in the usb boot case, this function returns, but what gets called after that? (aka... where can I put my flashy lights to follow?)
Edit: Looks like spl_error() doesn't flash the backlight if I call it from system_init() in system-x1000.c:
--- Code: ---void system_init(void)
{
spl_error();
// HACK FIXME: this is only for USB booting Rockbox, REMOVE ME
spl_handle_pre_boot(0);
/* Gate all clocks except CPU/bus/memory/RTC */
REG_CPM_CLKGR = ~jz_orm(CPM_CLKGR, CPU_BIT, DDR, AHB0, APB0, RTC);
/* Ungate timers and turn them all off by default */
jz_writef(CPM_CLKGR, TCU(0), OST(0));
jz_clrf(OST_ENABLE, OST1, OST2);
jz_write(OST_1MSK, 1);
jz_write(OST_1FLG, 0);
jz_clr(TCU_ENABLE, 0x80ff);
jz_set(TCU_MASK, 0xff10ff);
jz_clr(TCU_FLAG, 0xff10ff);
jz_set(TCU_STOP, 0x180ff);
--- End code ---
amachronic:
--- Quote from: dconrad on June 27, 2021, 12:09:40 AM ---Edit: Unless you meant that the spl binary is also subject to this scramble header and needs to be .bin? I thought I had tried that and got an error message, but I'll try again in the morning.
--- End quote ---
You do need to load spl.erosq with usbboot and not spl.bin. The .erosq file has a different header appended to it, generated by tools/mkspl-x1000.c, not the scramble header. The SPL header gets read by the CPU's boot ROM when booting from flash or SD. In the case of USB boot, I'm not 100% certain whether the header is necessary but it would only be useful for the CPU's "secure boot" mode, which isn't being used -- if it was, presumably you would've had a problem getting code to run at all. In any event, the usbboot tool is written to expect a file with the SPL header, so loading spl.bin using the --stage1 argument won't work.
--- Quote from: dconrad on June 27, 2021, 09:28:30 AM ---It's not much, but it's a starting point. It looks like in the usb boot case, this function returns, but what gets called after that? (aka... where can I put my flashy lights to follow?)
--- End quote ---
The entry point is ingenic_x1000/crt0.S, from there it calls main() in apps/main.c and the first thing called after that is system_init().
--- Quote from: dconrad on June 27, 2021, 09:28:30 AM ---Edit: Looks like spl_error() doesn't flash the backlight if I call it from system_init() in system-x1000.c:
--- End quote ---
You will have to take a close look at the memory initialization. It could be wrong for your player, since I only have 64MB X1000E SoCs to test with and not the 32MB X1000. The first thing I would check is to see if you have any memory corruption going on - this happened to me very early on because I didn't set up the DRAM self refresh properly, as a result any memory which wasn't accessed within a short span of time would corrupt because the memory controller wasn't sending the necessary refresh commands. So to check for any corruption, try putting this in the SPL:
--- Code: ---void spl_main(void)
{
/* Basic hardware init */
init();
memset((void*)0xa0000000, 0, 1024 * 1024);
return;
}
--- End code ---
That's zeroing out the first 1 MiB of memory using an uncached address to bypass the CPU cache. Run it like this and dump out that first 1M of memory:
--- Code: ---usbboot -v -c x1000 -1 <spl.erosq>
usbboot -v -c x1000 --addr 0xa0000000 --length 1048576 --upload memory0.bin
--- End code ---
Wait 1 minute or so, then dump the memory contents again:
--- Code: ---usbboot -v -c x1000 --addr 0xa0000000 --length 1048576 --upload memory1.bin
--- End code ---
hexdump them both and verify that both files are full of zeros as they should be. Repeat this a few times and wait for progressively longer intervals between dumps (arbitrarily, I would try up to 5 minutes just to be on the safe side). Keep the player plugged in, turned on, and don't re-run the SPL, only do the "upload" command. Of course, you should get a file full of zeros every time, but if you see more and more nonzero bytes appearing then DRAM is probably not refreshing correctly.
It could also be another DRAM related problem, eg. incorrect memory mappings or bad initialization. Or maybe even a non-DRAM problem, but I find it unlikely that DRAM would be okay and you can't get past the first few instructions. I just think DRAM corruption is the first and easiest thing to check for, so I'd do that first.
This is the source code for Ingenic's SPL: https://github.com/JaminCheung/x-loader. There's also some in the YuanhuanLiang repo. If it is really a memory related issue, you might start by comparing stuff from there... I wasn't able to find the x-loader source code myself so I simply reverse-engineered the M3K's SPL to write the memory initialization for Rockbox's SPL. Also useful, https://www.jedec.org/ lets you freely download the DDR2 spec, among other things, but you need to create an account first (requires a working email to activate the account; redistribution of their documents isn't allowed).
Here's some useful links for MIPS architecture stuff -- for example, the privileged resource architecture manual tells you how the virtual address space is laid out. Most of this is not directly useful for getting Rockbox running (ie, you probably won't need to actually code anything based on this info), but it's good background material.
* https://www.mips.com/downloads/introduction-to-the-mips32-architecture-v6-01/
* https://www.mips.com/downloads/the-mips32-instruction-set-v6-06/
* https://www.mips.com/downloads/the-mips32-and-micromips32-privileged-resource-architecture-v6-02/Just keep in mind those manuals have some things in there for multiple revisions of the MIPS architecture. The X1000 is a quasi-MIPS32 Release 2 CPU: it implements the integer r2 instructions according to its manual and from my limited testing, but it doesn't implement any useful stuff from the r2 PRA, and it's even missing some minor stuff from the base Release 1 PRA.
Anyway good luck! Let me know what you find out. At least you've got some progress :)
dconrad:
--- Quote ---
--- Quote from: dconrad on June 27, 2021, 09:28:30 AM ---Edit: Looks like spl_error() doesn't flash the backlight if I call it from system_init() in system-x1000.c:
--- End quote ---
You will have to take a close look at the memory initialization. It could be wrong for your player, since I only have 64MB X1000E SoCs to test with and not the 32MB X1000. The first thing I would check is to see if you have any memory corruption going on - this happened to me very early on because I didn't set up the DRAM self refresh properly, as a result any memory which wasn't accessed within a short span of time would corrupt because the memory controller wasn't sending the necessary refresh commands. So to check for any corruption, try putting this in the SPL:
--- Code: ---void spl_main(void)
{
/* Basic hardware init */
init();
memset((void*)0xa0000000, 0, 1024 * 1024);
return;
}
--- End code ---
That's zeroing out the first 1 MiB of memory using an uncached address to bypass the CPU cache. Run it like this and dump out that first 1M of memory:
--- Code: ---usbboot -v -c x1000 -1 <spl.erosq>
usbboot -v -c x1000 --addr 0xa0000000 --length 1048576 --upload memory0.bin
--- End code ---
Wait 1 minute or so, then dump the memory contents again:
--- Code: ---usbboot -v -c x1000 --addr 0xa0000000 --length 1048576 --upload memory1.bin
--- End code ---
hexdump them both and verify that both files are full of zeros as they should be. Repeat this a few times and wait for progressively longer intervals between dumps (arbitrarily, I would try up to 5 minutes just to be on the safe side). Keep the player plugged in, turned on, and don't re-run the SPL, only do the "upload" command. Of course, you should get a file full of zeros every time, but if you see more and more nonzero bytes appearing then DRAM is probably not refreshing correctly.
It could also be another DRAM related problem, eg. incorrect memory mappings or bad initialization. Or maybe even a non-DRAM problem, but I find it unlikely that DRAM would be okay and you can't get past the first few instructions. I just think DRAM corruption is the first and easiest thing to check for, so I'd do that first.
--- End quote ---
Well, I took several hex dumps over the course of about 15 minutes, and didn't see any non-zero values at all, so it looks like I'll have to start looking into the DRAM stuff.
--- Quote ---This is the source code for Ingenic's SPL: https://github.com/JaminCheung/x-loader. There's also some in the YuanhuanLiang repo. If it is really a memory related issue, you might start by comparing stuff from there... I wasn't able to find the x-loader source code myself so I simply reverse-engineered the M3K's SPL to write the memory initialization for Rockbox's SPL. Also useful, https://www.jedec.org/ lets you freely download the DDR2 spec, among other things, but you need to create an account first (requires a working email to activate the account; redistribution of their documents isn't allowed).
Here's some useful links for MIPS architecture stuff -- for example, the privileged resource architecture manual tells you how the virtual address space is laid out. Most of this is not directly useful for getting Rockbox running (ie, you probably won't need to actually code anything based on this info), but it's good background material.
* https://www.mips.com/downloads/introduction-to-the-mips32-architecture-v6-01/
* https://www.mips.com/downloads/the-mips32-instruction-set-v6-06/
* https://www.mips.com/downloads/the-mips32-and-micromips32-privileged-resource-architecture-v6-02/Just keep in mind those manuals have some things in there for multiple revisions of the MIPS architecture. The X1000 is a quasi-MIPS32 Release 2 CPU: it implements the integer r2 instructions according to its manual and from my limited testing, but it doesn't implement any useful stuff from the r2 PRA, and it's even missing some minor stuff from the base Release 1 PRA.
Anyway good luck! Let me know what you find out. At least you've got some progress :)
--- End quote ---
Thanks for the resources! I'll get started.
amachronic:
Hmm, if your DRAM contents are stable the issue might be elsewhere. I suspected DRAM because it's something very early on and not tested on your HW configuration. The only other DRAM-related thing which comes to mind is the addressing bits REG_DDRC_REMAPn, so you might try to confirm that the address mapping works by loop over all memory in the SPL like this:--
--- Code: ---void spl_main(void)
{
/* Basic hardware init */
init();
uint32_t* ptr = (uint32_t*)0xa0000000;
unsigned count = 32 * 1024 * 1024 / 4;
for(unsigned i = 0; i < count; ++i)
*ptr++ = i;
return;
}
--- End code ---
then grab the memory contents in 1M chunks...
--- Code: ---usbboot -v -c x1000 --addr 0xa0000000 --length 1048576 --upload mem00.bin
usbboot -v -c x1000 --addr 0xa0100000 --length 1048576 --upload mem01.bin
...
usbboot -v -c x1000 --addr 0xa1f00000 --length 1048576 --upload mem31.bin
cat mem*.bin > memory.bin
--- End code ---
then spin up a quick program to go over memory.bin and verify that every word in memory got written with the intended value.
To move the flashing backlight (almost) as early as possible you can call spl_error() at the top of your bootloader's main function. You can also try changing the entry point in the linker script ingenic_x1000/app.lds. That should ensure spl_error() is the absolute first thing that runs.
--- Code: ---#include "config.h"
#include "cpu.h"
OUTPUT_FORMAT("elf32-littlemips")
OUTPUT_ARCH(MIPS)
ENTRY(_start) /* <- change this to "main" in order to bypass crt0
(but be warned, this breaks C ABI because BSS segment won't be zeroed if you do this) */
STARTUP(target/mips/ingenic_x1000/crt0.o)
/* End of the audio buffer, where the codec buffer starts */
#define ENDAUDIOADDR (X1000_DRAM_END - PLUGIN_BUFFER_SIZE - CODEC_SIZE)
--- End code ---
Navigation
[0] Message Index
[#] Next page
[*] Previous page
Go to full version