Adding new firmware functions - General Discussion and Assistance - CHDK Forum

Adding new firmware functions

  • 19 Replies
  • 14093 Views
*

Offline srsa_4c

  • ******
  • 4451
Adding new firmware functions
« on: 08 / June / 2013, 22:38:13 »
Advertisements
I started a new topic for this to prevent cluttering the other threads.
I have recently requested some functions to be added to the dryos sigfinder. Since I'd like to continue supporting cameras with vxworks, I started to look into finding those functions in older cameras. I have used a poorly modified version of finsig_dryos and a modified version of the disassembler found in CHDK-PT. The results seem promising, though I'll still have to find some of the functions manually in older firmwares.
Results of the automated search: https://subversion.assembla.com/svn/chdk-s1.misc/data/fw_functions/

The reason behind this script is that I'd like to avoid to manually check every firmware disassembly.

Once all of them are found, I'd like to start to make use of some of them.

*

Offline srsa_4c

  • ******
  • 4451
Re: Adding new firmware functions
« Reply #1 on: 29 / June / 2013, 18:30:11 »
The VxWorks equivalent of this is now included in finsigvx2. The hits are not verified yet.

*

Offline srsa_4c

  • ******
  • 4451
Re: Adding new firmware functions
« Reply #2 on: 13 / July / 2013, 14:40:48 »
"Reversed" basic documentation for the semaphore functions. The VxWorks and DryOS versions can have slightly different return values, but that should not make any practical difference when using below definitions.
Only checked on VxWorks and DryOS r23, but I think they are valid up to r52.

int CreateBinarySemaphore(char *name, int init)
    name: semaphore name, can be NULL
    init: initial value, 1 (means 'not taken') or 0 ('taken')

    return value:
        0: not created (NULL handle)
        bit0 is set: error
        otherwise: semaphore handle

int CreateCountingSemaphore(char *name, int init)
    name: semaphore name, can be NULL
    init: initial value

    return value:
        0: not created (NULL handle)
        bit0 is set: error
        otherwise: semaphore handle

int DeleteSemaphore(int hSem)
    hSem: semaphore handle

    return value:
        0: no error
        bit0 is set: error (generic)

int TakeSemaphore(int hSem, unsigned int wait)
    hSem: semaphore handle
    wait:
        0: wait indefinitely
        not 0: wait not more than specified msecs

    return value:
        0: no error
        bit0 is set: error (generic)
        bit3 is set: timeout

int TryTakeSemaphore(int hSem)
    Takes semaphore if available, returns immediately.
    hSem: semaphore handle

    return value:
        0: no error
        bit0 is set: error (generic)

int GiveSemaphore(int hSem)
    hSem: semaphore handle

    return value:
        0: no error
        bit0 is set: error (generic)

int GetSemaphoreValue(int hSem, int *pVal)
    hSem: semaphore handle
    pVal: points to variable for the retrieved value (not checked for NULL!)

    return value:
        0: no error
        bit0 is set: error (generic)

« Last Edit: 02 / February / 2015, 18:07:26 by srsa_4c »

*

Offline srsa_4c

  • ******
  • 4451
Re: Adding new firmware functions
« Reply #3 on: 28 / January / 2014, 17:15:32 »
Timer functions, GetSystemTime() based (msec resolution), callbacks can't be NULL.

hTimer SetTimerAfter(int delay, (*good_cb)(int, int), (*bad_cb)(int, int), int whatever);

return: bit0 = 1 when error, handle otherwise
callback arguments: a = current time value, b = 'whatever'
bad_cb() gets called when 'delay' is zero
good_cb() gets called after 'delay' msecs

hTimer SetTimerWhen(int time, (*good_cb)(int, int), (*bad_cb)(int, int), int whatever);

return: bit0 = 1 when error, handle otherwise
callback arguments: a = current time value, b = 'whatever'
bad_cb() gets called when the desired time has already passed
good_cb() gets called when GetSystemTime() reaches 'time'

int CancelTimer(hTimer);



HP timer functions, they use a 20 bit hw counter, retrieved by GetCurrentMachineTime() aka *(int*)0xc0242014
The callbacks can't be NULL.

hHPTimer SetHPTimerAfterNow(int delay, (*good_cb)(int, int), (*bad_cb)(int, int), int whatever);
return: bit0 = 1 when error, handle otherwise

hHPTimer SetHPTimerAfterTimeout(int time_base, int delay, (*good_cb)(int, int), (*bad_cb)(int, int), int whatever)
return: bit0 = 1 when error, handle otherwise
 bad_cb(int a, int b);
 gets called when the desired time has already passed, a=time_base+delay, b='whatever'

int CancelHPTimer(hHPTimer);


The two callbacks probably get the same kind of params in not noted cases, since they are usually the same in firmware code.

Since the callbacks probably run in interrupt context, they should be as lightweight as possible. They can probably be thumb on DryOS, but most probably need to be ARM on VxWorks.

Here's a demonstration:
Code: [Select]
Index: core/main.c
===================================================================
--- core/main.c (revision 3343)
+++ core/main.c (working copy)
@@ -189,6 +189,8 @@
     }
 
     shooting_init();
+    extern void init_timer_demo();
+    init_timer_demo();
 
     while (1)
     {
@@ -249,10 +251,11 @@
 
         i = 0;
 
-#ifdef DEBUG_PRINT_TO_LCD
-        sprintf(osd_buf, "%d", cnt ); // modify cnt to what you want to display
+//#ifdef DEBUG_PRINT_TO_LCD
+        extern int hmmm, hmmmm;
+        sprintf(osd_buf, "%x, %x", hmmm, hmmmm ); // modify cnt to what you want to display
         draw_txt_string(1, i++, osd_buf, conf.osd_color);
-#endif
+//#endif
 
         if (camera_info.perf.md_af_tuning)
         {
Index: platform/a3200/sub/100d/stubs_entry_2.S
===================================================================
--- platform/a3200/sub/100d/stubs_entry_2.S (revision 3343)
+++ platform/a3200/sub/100d/stubs_entry_2.S (working copy)
@@ -12,3 +12,10 @@
 NHSTUB(TurnOnMic,                   0xFF8608E8)
 NHSTUB(TurnOffMic,                  0xFF860914)
 NHSTUB(TurnOffE1,                   0xff83bc20)
+
+NHSTUB(SetTimerAfter,          0xff83aa4c)
+NHSTUB(SetTimerWhen,           0xff83aacc)
+NHSTUB(CancelTimer,            0xff83ab30)
+NHSTUB(SetHPTimerAfterNow,     0xff888770)
+NHSTUB(SetHPTimerAfterTimeout, 0xff8887f0)
+NHSTUB(CancelHPTimer,          0xff888878)
Index: platform/generic/lib.c
===================================================================
--- platform/generic/lib.c (revision 3343)
+++ platform/generic/lib.c (working copy)
@@ -1 +1,2 @@
 #include "platform.h"
+
Index: platform/generic/wrappers.c
===================================================================
--- platform/generic/wrappers.c (revision 3343)
+++ platform/generic/wrappers.c (working copy)
@@ -1677,3 +1677,37 @@
     return (conf.remote_enable == 0 && get_usb_bit());
 }
 
+// timer demo
+
+extern int _SetTimerAfter(int delay, int(*good_cb)(int, int), int(*bad_cb)(int, int), int whatever);
+extern int _SetTimerWhen(int time, int(*good_cb)(int, int), int(*bad_cb)(int, int), int whatever);
+extern int _CancelTimer(int);
+
+static int blinkcnt = 0;
+static int blinkdly = 4096;
+static int demostate = 1;
+int hmmm = 0;
+int hmmmm = 0;
+
+int mytimerfunc(int a, int b) {
+    hmmmm = a;
+    hmmm = b;
+    blinkcnt--;
+    if (blinkcnt>0) {
+        _SetTimerAfter(blinkdly,mytimerfunc,mytimerfunc,(int)&hmmm);
+    }
+    else {
+        void init_timer_demo();
+        init_timer_demo();
+    }
+    blinkdly>>=1;
+    debug_led(demostate);
+    demostate = !demostate;
+    return 0;
+}
+void init_timer_demo() {
+    blinkcnt = 8;
+    blinkdly = 1024;
+    _SetTimerWhen(get_tick_count()+10000,mytimerfunc,mytimerfunc,(int)&hmmm);
+}
+
« Last Edit: 28 / January / 2014, 17:27:36 by srsa_4c »

Re: Adding new firmware functions
« Reply #4 on: 23 / March / 2014, 17:47:27 »
HP timer functions, they use a 20 bit hw counter, retrieved by GetCurrentMachineTime() aka *(int*)0xc0242014
So far this is only defined for a couple of cameras.

Quote
They can probably be thumb on DryOS, but most probably need to be ARM on VxWorks.
Trying to understand how to make a common callback handler for all camera OS's. 

Easy enough to put calls to _SetHPTimerAfterNow() in wrappers.c (i.e. ARM) but if the callback is common code, does its source for VxWorks need to be in a different file than its source for ARM? Use a common file but #include it at a different point in the build based on OS so it gets built as ARM or Thumb as required?

On a related note, does all code in the callback need to be Thumb (DryOS) or Arm (VxWorks) ?  Can ARM code (in wrappers.c for example) safely call Thumb code (up in chdk/core) ?
Ported :   A1200    SD940   G10    Powershot N    G16

*

Offline philmoz

  • *****
  • 3450
    • Photos
Re: Adding new firmware functions
« Reply #5 on: 23 / March / 2014, 18:03:32 »
They can probably be thumb on DryOS, but most probably need to be ARM on VxWorks.
Trying to understand how to make a common callback handler for all camera OS's. 

I would have thought thumb code should work in both cases, although I haven't looked at the VxWorks firmware functions.

I would expect the firmware code is loading the callback address into a register and doing a 'BL Rn' instruction - so the CPU should take care of mode switching based on the low bit of the address.

We already do this with the qsort firmware function callback.

Phil.
CHDK ports:
  sx30is (1.00c, 1.00h, 1.00l, 1.00n & 1.00p)
  g12 (1.00c, 1.00e, 1.00f & 1.00g)
  sx130is (1.01d & 1.01f)
  ixus310hs (1.00a & 1.01a)
  sx40hs (1.00d, 1.00g & 1.00i)
  g1x (1.00e, 1.00f & 1.00g)
  g5x (1.00c, 1.01a, 1.01b)
  g7x2 (1.01a, 1.01b, 1.10b)

Re: Adding new firmware functions
« Reply #6 on: 23 / March / 2014, 18:10:36 »
I would have thought thumb code should work in both cases, although I haven't looked at the VxWorks firmware functions.  I would expect the firmware code is loading the callback address into a register and doing a 'BL Rn' instruction - so the CPU should take care of mode switching based on the low bit of the address.
Thanks - that makes sense to me too.

So all I need is a small wrapper for _SetHPTimerAfterNow() and _CancelHPTimer() in wrappers.c and all the rest of the code can go into usb_remote.c.   Nice.

At some point soon,  it would be nice to get those two function added to stubs_entry.S (they are already in the funcs_by_name.csv & funcs_by_address.csv)
Ported :   A1200    SD940   G10    Powershot N    G16

*

Offline srsa_4c

  • ******
  • 4451
Re: Adding new firmware functions
« Reply #7 on: 23 / March / 2014, 18:59:46 »
I would have thought thumb code should work in both cases, although I haven't looked at the VxWorks firmware functions.

I would expect the firmware code is loading the callback address into a register and doing a 'BL Rn' instruction - so the CPU should take care of mode switching based on the low bit of the address.
Unfortunately, the code is like this:
NSTUB(SetHPTimerAfterNow, 0xffc056d8):
ffc056d8: push  {r4, r5, r6, r7, lr}
ffc056dc: ldr   r12, =0x1db0
ffc056e0: ldr   lr, [r12]
ffc056e4: cmp   lr, #0
ffc056e8: mov   r6, r0
ffc056ec: mov   r5, r3
ffc056f0: mov   r0, #23
ffc056f4: mov   r4, r1
ffc056f8: mov   r7, r2
ffc056fc: popne {r4, r5, r6, r7, pc}
ffc05700: bl    GetCurrentMachineTime
ffc05704: mov   r1, r4
ffc05708: add   r4, r0, r6
ffc0570c: bic   r4, r4, #0xff000000
ffc05710: bic   r4, r4, #0xf00000
ffc05714: cmp   r6, #0
ffc05718: mov   r2, r5
ffc0571c: mov   r0, r4
ffc05720: bne   ffc05738
ffc05724: mov   r1, r5
ffc05728: mov   lr, pc
ffc0572c: mov   pc, r7
As far as I know, there is no thumb/ARM mode switch on MOV.

HP timer functions, they use a 20 bit hw counter, retrieved by GetCurrentMachineTime() aka *(int*)0xc0242014
So far this is only defined for a couple of cameras.
If you mean GetCurrentMachineTime(), it's really only
int GetCurrentMachineTime() {
  return *(int*)0xc0242014;
}

*

Offline philmoz

  • *****
  • 3450
    • Photos
Re: Adding new firmware functions
« Reply #8 on: 23 / March / 2014, 19:22:40 »
I would have thought thumb code should work in both cases, although I haven't looked at the VxWorks firmware functions.

I would expect the firmware code is loading the callback address into a register and doing a 'BL Rn' instruction - so the CPU should take care of mode switching based on the low bit of the address.
Unfortunately, the code is like this:
NSTUB(SetHPTimerAfterNow, 0xffc056d8):
ffc056d8: push  {r4, r5, r6, r7, lr}
ffc056dc: ldr   r12, =0x1db0
ffc056e0: ldr   lr, [r12]
ffc056e4: cmp   lr, #0
ffc056e8: mov   r6, r0
ffc056ec: mov   r5, r3
ffc056f0: mov   r0, #23
ffc056f4: mov   r4, r1
ffc056f8: mov   r7, r2
ffc056fc: popne {r4, r5, r6, r7, pc}
ffc05700: bl    GetCurrentMachineTime
ffc05704: mov   r1, r4
ffc05708: add   r4, r0, r6
ffc0570c: bic   r4, r4, #0xff000000
ffc05710: bic   r4, r4, #0xf00000
ffc05714: cmp   r6, #0
ffc05718: mov   r2, r5
ffc0571c: mov   r0, r4
ffc05720: bne   ffc05738
ffc05724: mov   r1, r5
ffc05728: mov   lr, pc
ffc0572c: mov   pc, r7
As far as I know, there is no thumb/ARM mode switch on MOV.


It's never easy is it :(

I can suggest two approaches:
- put all the callback code in wrappers.c so it is always compiled as ARM
- put an ARM wrapper for the callback code in wrappers.c with the main thumb code in the usb_remote file

If the callback function is simple then it can probably live in wrappers.c, otherwise the second option is probably better.

Phil.
CHDK ports:
  sx30is (1.00c, 1.00h, 1.00l, 1.00n & 1.00p)
  g12 (1.00c, 1.00e, 1.00f & 1.00g)
  sx130is (1.01d & 1.01f)
  ixus310hs (1.00a & 1.01a)
  sx40hs (1.00d, 1.00g & 1.00i)
  g1x (1.00e, 1.00f & 1.00g)
  g5x (1.00c, 1.01a, 1.01b)
  g7x2 (1.01a, 1.01b, 1.10b)

Re: Adding new firmware functions
« Reply #9 on: 23 / March / 2014, 19:35:07 »
I can suggest two approaches:
- put all the callback code in wrappers.c so it is always compiled as ARM
- put an ARM wrapper for the callback code in wrappers.c with the main thumb code in the usb_remote file

If the callback function is simple then it can probably live in wrappers.c, otherwise the second option is probably better.
So here's a patch file that I've been playing with.  It adds an enable_highspeed_usb() function to Lua that switches the USB remote pulse counting & width measurement to work from an HP timer.   If you don't make the function call from a script,  all the USB remote code works as before.  At some point we might want to limit how short a timer interval the user can try but for now it "caveat emptor".


I don't have a VxWorks camera to test it with but it works a charm on my DryOS cameras.

There is a little test script (pwm_test.lua) in the CHDK/SCRIPTS directory.     I've experimented with rate as fast as 100 uSec but that tends to be so fast it catches switch bounce :)

Will it work this way under VxWorks ?
« Last Edit: 23 / March / 2014, 19:37:29 by waterwingz »
Ported :   A1200    SD940   G10    Powershot N    G16

 

Related Topics


SimplePortal © 2008-2014, SimplePortal