IXUS 130 (SD1400 IS) Porting Thread - page 3 - DryOS Development - CHDK Forum

IXUS 130 (SD1400 IS) Porting Thread

  • 288 Replies
  • 77828 Views
*

Offline emlyn

  • **
  • 88
Re: IXUS 130 (SD1400 IS) Porting Thread
« Reply #20 on: 14 / September / 2010, 18:29:38 »
Advertisements
Just a quick update:
I've got the boot process running up until boot.c, but somewhere in there it crashes. By flashing LEDs I've found where it crashes but I'm not yet sure why. So far I've been using the Ixus 95 as a reference, but I think I'll have a look at some other models to see if they do anything differently. If anyone has any experience porting CHDK, and is willing to take a look, let me know and I'll send the code.

Another thing I don't quite understand: I have some busy loops for the LED flashing, and the one at the very beginning of the boot function runs about 16 times slower than the others.

*

Online reyalp

  • ******
  • 12111
Re: IXUS 130 (SD1400 IS) Porting Thread
« Reply #21 on: 14 / September / 2010, 19:09:18 »
Another thing I don't quite understand: I have some busy loops for the LED flashing, and the one at the very beginning of the boot function runs about 16 times slower than the others.
Some of ASM code in boot.c enables the CPU caches :)

If you post a snippet of code where the crash happens someone might have an idea.

The Ixus95 port is quite immature, so I'd definitely suggest referring to other cams as well.
Don't forget what the H stands for.

*

Offline emlyn

  • **
  • 88
Re: IXUS 130 (SD1400 IS) Porting Thread
« Reply #22 on: 15 / September / 2010, 05:15:42 »
Some of ASM code in boot.c enables the CPU caches :)
Ah OK that makes sense, I sort of overlooked it because it has a comment saying:
// this is a carryover from old dryos ports, may not be useful
Also, I think the loops in the loader also ran at the faster speed, but maybe the caches were enabled there and somehow get disabled again before boot.c.

Quote
If you post a snippet of code where the crash happens someone might have an idea.

The Ixus95 port is quite immature, so I'd definitely suggest referring to other cams as well.

Here is where it crashes, with some context ("..." represents redacted code, to save space):

Code: [Select]
void boot() {
    long *canon_data_src = (void*)0xFFBF837C;  //From end of first function
    long *canon_data_dst = (void*)0x1900;     //From end of first function
    long canon_data_len = 0xEBD0 - 0x1900; // data_end - data_start
    long *canon_bss_start = (void*)0xEBD0; // just after data
    long canon_bss_len = 0x14FE20 - 0xEBD0; //In loop at end of first function

    long i;

    // enable caches and write buffer... this is a carryover from old dryos ports, may not be useful
    asm volatile (
"MRC     p15, 0, R0,c1,c0\n"
"ORR     R0, R0, #0x1000\n"
"ORR     R0, R0, #4\n"
"ORR     R0, R0, #1\n"
"MCR     p15, 0, R0,c1,c0\n"
    :::"r0");

    for(i=0;i<canon_data_len/4;i++)
        canon_data_dst[i]=canon_data_src[i];

    for(i=0;i<canon_bss_len/4;i++)
        canon_bss_start[i]=0;

// see [url=http://chdk.setepontos.com/index.php/topic,2972.msg30712.html#msg30712]SD990[/url]

    *(int*)0x1934=(int)taskCreateHook;
    *(int*)0x1938=(int)taskCreateHook2; //VERIFY_SD780

    // IXUS130: see code from FF85F3F0
    *(int*)(0x2484)= (*(int*)0xC0220128)&1 ? 0x400000 : 0x200000;

    // jump to init-sequence that follows the data-copy-routine
    asm volatile ("B      sub_FF810354_my\n");
}

void __attribute__((naked,noinline)) sub_FF810354_my() {
        asm volatile ("..." // copied from fw dump
"                BL      sub_FF811198_my\n"
        );
}

void __attribute__((naked,noinline)) sub_FF811198_my() {
asm volatile ("..."
"                 LDR     R0, =new_sa\n" //Replaces original start location 0x14FE20
"                 LDR     R0, [R0]\n"
"                 ..." // Storing lots of things on the stack, including:
"                 LDR     R1, =sub_FF815E58_my\n" // also tried "LDR     R1, =0xFF815E58"
// It gets here
"                 MOV     R0, SP\n"
"                 MOV     R2, #0\n"
"                 BL      sub_FF813404\n" // was FF812D68
// It doesn't get here
"                 ADD     SP, SP, #0x74\n"
"                 LDR     PC, [SP],#4\n"
);
}

void __attribute__((naked,noinline)) sub_FF815E58_my() {
asm volatile ( // It doesn't get here
"                 ..."
"                 B       taskcreate_Startup_my\n" // FF81FAF0
);
}

It is the call to sub_FF813404 that fails. It seems to take a function pointer as an argument, I tried passing in the original function from the firmware instead of the new one from boot.c, but it doesn't make any difference - the call never returns, and the function pointer passed in is never called.
I thought about copying sub_FF813404 into boot.c as well, so that I can find out whereabouts it is failing, but if someone has an idea that will save me the work, all the better :-)

*

Online reyalp

  • ******
  • 12111
Re: IXUS 130 (SD1400 IS) Porting Thread
« Reply #23 on: 15 / September / 2010, 12:31:36 »
Ah OK that makes sense, I sort of overlooked it because it has a comment saying:
// this is a carryover from old dryos ports, may not be useful
Yes, that's my bad comment and it should be corrected to something like
// re-enable caches disabled in loader
I didn't fully understand this when I did the SD990 port where that comment originated...  :-[
I'd actually suggest using the original camera startup code, as it does a bit more than just turning on the caches (although things seem to work fine without that, probably because it's already set up before reboot.) See recent change to d10.
Quote
Also, I think the loops in the loader also ran at the faster speed, but maybe the caches were enabled there and somehow get disabled again before boot.c.
Yup, it's disabled in loader/<camera>/resetcode/main.c

This bit of ASM code needs to be correct for your camera as well, BTW.
Quote
Code: [Select]
    *(int*)0x1934=(int)taskCreateHook;
    *(int*)0x1938=(int)taskCreateHook2; //VERIFY_SD780
Are you doing anything in these hooks ? If so, try commenting those out.
Quote
"                 BL      sub_FF813404\n" // was FF812D68
// It doesn't get here
"                 ADD     SP, SP, #0x74\n"
"                 LDR     PC, [SP],#4\n"

It is the call to sub_FF813404 that fails. It seems to take a function pointer as an argument, I tried passing in the original function from the firmware instead of the new one from boot.c, but it doesn't make any difference - the call never returns, and the function pointer passed in is never called.
I don't think this function would ever be expected to return, look at what would happen if it did... Unfortunately, this doesn't help you narrow down the problem much. Have you checked the ROMLOG ? See http://chdk.wikia.com/wiki/Canon_Basic#RomLog for a script to dump it. If the camera is hitting an exception or assert, this may give you a clue.

I also noticed
Code: [Select]
"                 BL      sub_FF813404\n" // was FF812D68
If you are going through and "correcting" code from another camera, chances are you've missed an address or code difference somewhere. For the ASM, I'd really suggest starting from scratch.

Don't forget what the H stands for.


*

Offline emlyn

  • **
  • 88
Re: IXUS 130 (SD1400 IS) Porting Thread
« Reply #24 on: 15 / September / 2010, 17:11:57 »
This bit of ASM code needs to be correct for your camera as well, BTW.
Quote
Code: [Select]
   *(int*)0x1934=(int)taskCreateHook;
    *(int*)0x1938=(int)taskCreateHook2; //VERIFY_SD780
I was just looking into that, how can I find out what it should be? Can I comment it out to begin with?

Quote
Are you doing anything in these hooks ? If so, try commenting those out.
I've commented out most of their contents so they are basically doing nothing at the moment.

Quote
Quote
"                 BL      sub_FF813404\n" // was FF812D68
// It doesn't get here
"                 ADD     SP, SP, #0x74\n"
"                 LDR     PC, [SP],#4\n"

It is the call to sub_FF813404 that fails. It seems to take a function pointer as an argument, I tried passing in the original function from the firmware instead of the new one from boot.c, but it doesn't make any difference - the call never returns, and the function pointer passed in is never called.
I don't think this function would ever be expected to return, look at what would happen if it did... Unfortunately, this doesn't help you narrow down the problem much.
I don't know ARM assembler very well (I hadn't done any before this), so I'm not sure I follow you. To me that just looks like deallocating the local variables and then returning (the function starts with "STR LR, [SP,#-4]!", "SUB SP, SP, #0x74"). If it was not meant to return, wouldn't it be followed by constants or the start of another function?
EDIT: I just realised that it would return right to the end of the previous function and run off the end. (Does this mean that those last two instructions are not needed, and the BL could just be a B?)

Quote
Have you checked the ROMLOG ? See http://chdk.wikia.com/wiki/Canon_Basic#RomLog for a script to dump it. If the camera is hitting an exception or assert, this may give you a clue.
I haven't tried this yet, but I will keep it in mind in case the other ideas don't work.

Quote
I also noticed
Code: [Select]
"                 BL      sub_FF813404\n" // was FF812D68
If you are going through and "correcting" code from another camera, chances are you've missed an address or code difference somewhere. For the ASM, I'd really suggest starting from scratch.

Yes, I've already found a couple of errors in there, but fixing them hasn't helped. I suspect there are more and that is the problem, so I think I'll do as you suggest.
If I just jump to 0xff810000, I think I should get into a boot loop, is that right? So if I blink an LED I should see it flashing. Then I can gradually add more code from the dump, until I have all I need.
« Last Edit: 15 / September / 2010, 17:21:43 by emlyn »

*

Offline emlyn

  • **
  • 88
Re: IXUS 130 (SD1400 IS) Porting Thread
« Reply #25 on: 15 / September / 2010, 18:36:49 »
I've found that jumping to 0xff810000 (just after re-enabling the caches) does create a boot loop, so that gives me something to start from.
Now I'm trying to start copying the code from the fw dump, but I'm having a bit of trouble since the syntax of my dump is not quite the same as the assembler expects.
The function ends with:
Code: [Select]
    "bcc    sub_FF81013C\n"
    "ldr    r1, =0x14fe20\n"
    "mov    r2, #0\n"// ; 0x0
    "cmp    r3, r1\n"
    "strcc  r2, [r3], #4\n"
    "bcc    sub_FF810154\n"
    "b      sub_FF810354\n"
I get undefined reference errors to sub_FF81013C and sub_FF810154, but not to sub_FF810354. Do I have to define them somewhere? If so, presumably the third is already defined there, but I can't find it anywhere.
I also tried using constants instead (e.g. bcc 0xFF810154), which compiled but generated the wrong addresses in the dump.

*

Online reyalp

  • ******
  • 12111
Re: IXUS 130 (SD1400 IS) Porting Thread
« Reply #26 on: 15 / September / 2010, 20:25:52 »
EDIT: I just realised that it would return right to the end of the previous function and run off the end. (Does this mean that those last two instructions are not needed, and the BL could just be a B?)
Probably. Since this function is "boot the OS" it doesn't really make sense that it would ever return, there is nothing to return to. My guess the instructions for a return are just generated by canons compiler because it's a function.

Quote
Now I'm trying to start copying the code from the fw dump, but I'm having a bit of trouble since the syntax of my dump is not quite the same as the assembler expects.
You have to fix it. If you can look at tools/asmify.sh if you are using IDA

Quote
I get undefined reference errors to sub_FF81013C and sub_FF810154, but not to sub_FF810354. Do I have to define them somewhere? If so, presumably the third is already defined there, but I can't find it anywhere.
These should be automatically created by the build process, look at stubs_auto.S and how the makefile generates it. This is done with sed, so it can get confused...

Quote
also tried using constants instead (e.g. bcc 0xFF810154), which compiled but generated the wrong addresses in the dump
Right, because B instructions take a signed 24 PC relative bit offset, and just overflow (in the assembler) if you use a larger number. What you want to do roll your own. For a function call it will look like
MOV LR, PC
LDR PC, =0x...

A straight B is just a LDR PC, =0x...
Don't forget what the H stands for.

*

Offline emlyn

  • **
  • 88
Re: IXUS 130 (SD1400 IS) Porting Thread
« Reply #27 on: 16 / September / 2010, 09:43:53 »
Quote
Now I'm trying to start copying the code from the fw dump, but I'm having a bit of trouble since the syntax of my dump is not quite the same as the assembler expects.
You have to fix it. If you can look at tools/asmify.sh if you are using IDA
I'm using a disassembly generated with the GNU tools. I think I understand most of the differences now. If I have to do much more I might make an asmify script for this.

Quote
These should be automatically created by the build process, look at stubs_auto.S and how the makefile generates it. This is done with sed, so it can get confused...
It turns out the makefile only sees the branch instructions if they start with an upper case B, I changed B to [Bb] in platform/makefile_sub.inc and it now works.

Quote
Right, because B instructions take a signed 24 PC relative bit offset, and just overflow (in the assembler) if you use a larger number. What you want to do roll your own. For a function call it will look like
MOV LR, PC
LDR PC, =0x...

A straight B is just a LDR PC, =0x...
I don't need this now I've got the sub_xxxx method working, but it's good to know. The more I learn about ARM the more I like it, it's so much nicer than x86...
But how come the MOV instruction gets the right PC value? I would naively expect it to get the address of itself or the LDR instruction, necessitating something like LDR LR, PC, #4.

I'm still having trouble with the camera crashing. If after enabling the caches I put "B sub_FF810000" then I get a boot loop, but if I copy the code from that address it crashes, even though as far as I can tell it is identical (but obviously I have missed something).
The forum won't let me post the function code here because it is too long, but I've put it on pastebin: original and mine.

One thing I found strange in the original are these lines:
Code: [Select]
ff810114: e3a01001 mov r1, #1 ; 0x1
ff810118: e59f205c ldr r2, [pc, #92] ; ff81017c: (c0243100)
ff81011c: e5812000 str r2, [r1]
If I'm not mistaken, that is writing 0xc0243100 to address 1, which looks the wrong way around to me, since the address is misaligned, but maybe I'm missing something. If this is the problem it would indicate a corrupted dump, maybe I'll try dumping with another method and comparing. Or I can branch to the original in the middle, to narrow down exactly where the problem is coming from.


*

Online reyalp

  • ******
  • 12111
Re: IXUS 130 (SD1400 IS) Porting Thread
« Reply #28 on: 16 / September / 2010, 13:21:06 »
I'm using a disassembly generated with the GNU tools. I think I understand most of the differences now. If I have to do much more I might make an asmify script for this.
There may be something like this floating around. I know several ports have been done with gnu tools.
Quote
I don't need this now I've got the sub_xxxx method working, but it's good to know. The more I learn about ARM the more I like it, it's so much nicer than x86...
Agreed, it's quite consistent.
Quote
But how come the MOV instruction gets the right PC value? I would naively expect it to get the address of itself or the LDR instruction, necessitating something like LDR LR, PC, #4.
Because it behaves differently when the source is PC, effectively automatically adding the 4 that you'd need.

The ARM documentation is pretty good. I suggest getting the ARM Architecture Reference Manual, you have to sign up at the ARM site to download it but it's free.
Links can be found at http://chdk.wikia.com/wiki/Developer_Technical_Documents

Quote
Code: [Select]
ff810114: e3a01001 mov r1, #1 ; 0x1
ff810118: e59f205c ldr r2, [pc, #92] ; ff81017c: (c0243100)
ff81011c: e5812000 str r2, [r1]
If I'm not mistaken, that is writing 0xc0243100 to address 1, which looks the wrong way around to me, since the address is misaligned, but maybe I'm missing something. If this is the problem it would indicate a corrupted dump, maybe I'll try dumping with another method and comparing. Or I can branch to the original in the middle, to narrow down exactly where the problem is coming from.

That is very strange, but other cameras with working ports do the same thing, so I'd say the dump is correct. Weird, never noticed that before. ISTR what actually happens on these machines when you store to an unaligned address is that it just gets truncated, so it's equivalent to storing to address 0.

But... I see your problem, or a problem at least
Code: [Select]
    "cmp        r1, r3\n"
    "ldrcc      r2, [r0], #4\n"
    "strcc      r2, [r1], #4\n"
    "bcc        sub_FF81013C\n"
This is B not a BL, so you need to use loc_... not sub. sub_ will send you off through stubs_entry.S and into ROM, where in fact you want to jump back a few instructions in a loop:
Code: [Select]
"loc_FF81013C:\n"
    "cmp        r1, r3\n"
    "ldrcc      r2, [r0], #4\n"
    "strcc      r2, [r1], #4\n"
    "bcc        loc_FF81013C\n"
sub_* should only be used when you are jumping into the actual ROM, usually for a BL but also in a few cases where you simply want to continue in ROM without returning to your CHDK code in RAM. loc_* (or really any label you make up) refers to a label within your code.
Don't forget what the H stands for.

*

Offline emlyn

  • **
  • 88
Re: IXUS 130 (SD1400 IS) Porting Thread
« Reply #29 on: 16 / September / 2010, 13:36:42 »
The ARM documentation is pretty good. I suggest getting the ARM Architecture Reference Manual, you have to sign up at the ARM site to download it but it's free.
Links can be found at http://chdk.wikia.com/wiki/Developer_Technical_Documents
Thanks, I'll look it up.

Quote
Quote
But... I see your problem, or a problem at least
Code: [Select]
    "cmp        r1, r3\n"
    "ldrcc      r2, [r0], #4\n"
    "strcc      r2, [r1], #4\n"
    "bcc        sub_FF81013C\n"
This is B not a BL, so you need to use loc_... not sub. sub_ will send you off through stubs_entry.S and into ROM, where in fact you want to jump back a few instructions in a loop:
Code: [Select]
"loc_FF81013C:\n"
    "cmp        r1, r3\n"
    "ldrcc      r2, [r0], #4\n"
    "strcc      r2, [r1], #4\n"
    "bcc        loc_FF81013C\n"
sub_* should only be used when you are jumping into the actual ROM, usually for a BL but also in a few cases where you simply want to continue in ROM without returning to your CHDK code in RAM. loc_* (or really any label you make up) refers to a label within your code.

Yes I just noticed that too and fixed it, but it still doesn't work.
By jumping to the original firmware form different points, I think I've found where it is failing, but I don't understand why:
Code: [Select]
    "ldr    r2, =0xc0242010\n"
    "ldr    r1, [r2]\n"
    "orr    r1, r1, #1\n"//    ; 0x1
    "str    r1, [r2]\n"

    "B          sub_ff810130\n" // works with this
    "ldr r0, =0xffbf837c\n"
    "B          sub_ff810134\n" // fails with this

    "ldr    r1, =0x1900\n"
    "ldr    r3, =0xebd0\n"
"loc_FF81013C:\n"
    "cmp    r1, r3\n"
    "ldrcc    r2, [r0], #4\n"
    "strcc    r2, [r1], #4\n"
    "bcc    loc_FF81013C\n"
The equivalent in the dump is:
Code: [Select]
ff810120:     e59f2058     ldr    r2, [pc, #88]    ; ff810180: (c0242010)
ff810124:     e5921000     ldr    r1, [r2]
ff810128:     e3811001     orr    r1, r1, #1    ; 0x1
ff81012c:     e5821000     str    r1, [r2]
ff810130:     e59f004c     ldr    r0, [pc, #76]    ; ff810184: (ffbf837c)
ff810134:     e59f104c     ldr    r1, [pc, #76]    ; ff810188: (00001900)
ff810138:     e59f304c     ldr    r3, [pc, #76]    ; ff81018c: (0000ebd0)
ff81013c:     e1510003     cmp    r1, r3
ff810140:     34902004     ldrcc    r2, [r0], #4
ff810144:     34812004     strcc    r2, [r1], #4
ff810148:     3afffffb     bcc    ff81013c <_binary__dump_bin_start+0x13c>
...
ff810184: ffbf837c undefined instruction 0xffbf837c

So if it executes the "ldr    r0, =0xffbf837c" from boot.c it fails, but if it executes it from the original fw it continues. How could it make any difference? Could it be a corrupted dump? Or something to do with endianness (I read that ARM can use either big or little endian)?

 

Related Topics