BenF V3 source code

Hi Antonio,
Great. I just have tested it,and it worked. Thank you.I need to read Migrating from version 4.x to version 5.x to learn more.

Hello Jerry,
glad to hear it’s reproducible consistently :slight_smile:

As soon as I have some more night-time available, I’d like to rewrite the hairy stuff using explicit addressing in the linker - and maybe have a peek at backporting it also to IAR4.

It’s quite easy: modify LIB assembler function in

    SECTION `.exports_table`:CODE:NOROOT(2)
__APP_Start                ;void __APP_Start(void)
    B       0x08010cd1

and add the following lines to the .icf Ilink control file:

define symbol _exports_TABLE__   = 0x08007211;
place at address mem:_exports_TABLE__ { readonly section .exports_table };

The imports addresses in APP can then be adjusted to the correct offset from the table start at 0x08007211 (that’s the current address of __APP_Start for IAR5, but of course if you are explicit with Ilinker you can place it where you like).

Inside APP you should then do something along the same lines in order to make sure the linker always places main() at address 0x08010cd1 (again, you can then choose whatever and simply adjust the above declaration in LIB accordingly).

I still don’t know how the same could be achieved with IAR4, but it is surely possible.

Will you have time to start the SVN repository? It would be way easier to supply patches, then. And maybe BenF would be so kind as to go on contributing his code on a more regular basis :wink:


Hi Antonio,

Thanks. I have built SVN repository on google code. Sorry,I still don’t understand what you write. Could you explain how you get the address of _APP_Start and __CTR_HP?

Jerry, that’s really Great! What’s needed in order to submit code?

__APP_Start is exported from LIB, so if you instruct IAR5 to generate a .map file (think objdump -x in gcc jargon) you will find its address in it. The pointers table is then easy to build - just add 4 bytes of offset for each pointer:

address of __USB_Instr   ->  address of __APP_Start + 4
address of __CTR_HP      ->  address of __APP_Start + 8

Maybe that part could also be done explicitly, defining a symbol __App_Start_address in APP that knows the address of __APP_Start in LIB (which should really be set explicitly by configuring the linker, as I was saying above) and then using it to express the needed function addresses.


You can send modified files to And I will merge modifications to SVN. Later,I will set a public account,so that ereryone can submit their code.

Hi ,

I get it. :slight_smile: I had a misunderstanding of the reset handler before. The reset handler in vector table is just a pointer,not code. Wen switching from lib to app,DSO jumps to the value of the reset handler pointer. Using GCC, it’s the same way.

Does this patch look good?

EDIT: Note that my check for SP in RAM (not so important anyway) accepts RAM addresses up to 128k, but our Nanos have only 20k. The bitwise OR can therefore be narrowed down and done against 0xFFFF8000 instead, although that would also not be precise and accept values up to 32k. I would suggest to keep 128k for future compatibility…

Hi Antonio,

I already found other addresses according to the map file generated by the lib part.

In LIB, use (this stays the same):

__APP_Start                ;void __APP_Start(void)
    B       0x08010cd1

In APP, when LIB’s main has WaitForKey commented, use:
This table has been determined according to the lib map file where all values can be found under entry.

; Table of library functions start address
__CTR_HP                  ;void __CTR_HP(void)
    B       0x080066eb
__USB_Istr                ;void __USB_Istr(void);
    B       0x08007031
__MSD_WriteBlock          ;u8 __MSD_WriteBlock(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
    B       0x08005353 

__MSD_ReadBlock           ;u8 __MSD_ReadBlock(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead)
    B       0x080053bf
__Get_Font_8x14           ;u16 __Get_TAB_8x14(unsigned char Code, unsigned short Row)
    B       0x08004ec1
__Get_Ref_Wave            ;u8 __Get_Ref_Wave(unsigned short i)
    B       0x08004ed3
__SD_Set_Changed          ;void __SD_Set_Changed(void)
    B       0x08005f5d

I also checked your entries and these seem to work, however when loading already stored data the scope will reset or hang. When using the values found in the lib map file everything works fine.

I have a couple of questions:
Do you have the same experience?
How did you determine the table addresses, because when using the same compiler/linker and settings as determined in the project the map file must be the same?

I’m using IAR Embedded Workbench 5.5, maybe that’s the difference.

Kind regards,

Yes, it looks good to go. I’m not sure what will happen when you exit from main (no APP found), so you may want to add an empty infinite loop to keep the image on screen.

This should allow you to start APP, but you’re still left with the challenge of getting the offset address of your __BRANCH_TABLE (LIB) compiled into APP.

This line of programming is as ugly as it gets and probably not what IAR hoped for when they decided to offer the 32K trial version. Ultimately a single build image would be preferred, but it may be tricky if the goal is to maintain a single source.

As for the Gcc port, there is also the issue of assembly/C calling conventions to look into (if there are differences). The small assembly stubs may cause issues before you even get to calling APP unless you get this right. Perhaps a small isolated test application is simpler than debugging on the full LIB/APP.

Another idea might be to pass the BRANCH_TABLE/APP_START address in an unused interrupt vector (one of the reserved vectors or an unused peripheral vector are good candidates). This would allow you to determine the LIB callback addresses from APP at runtime rather than compile time. First you look up the BRANCH_TABLE address from the interrupt vector offset address and from this you can build function pointers to LIB routines.

Hello Pjve,
thanks a lot - you’ve made me find an error in my address table: the code

__MSD_ReadBlock ;u8 __MSD_ReadBlock(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead) B 0x0800721D
should actually read

__MSD_ReadBlock ;u8 __MSD_ReadBlock(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead) B 0x0800720D

My table of addresses comes from the map file as well. I’d say that the difference is in IAR - I have version 5.4, quite likely the two linkers produce diffent layouts.


Hello all,
I’ve done a few tests with explicit memory address linking in IAR5: for me it works as intended. You can see the changes in the svn repository (here), they are relatively minor. I’m positive the same could be done for IAR4 - don’t know the correct syntax, though, and have no IAR4 to test it.


I’ve added a patch for making the APP entry point address static too; now everyone using IAR5 should be able to compile and link without the need to hand-edit any pointer table. I have version 5.4 - if anyone with a different linker feels like to give it a go, you can check the code out of svn:

svn checkout DSO_BenF_v3_IAR5


Hi Antonio,

Just tried your new code on IAR 5.5 and it seems to work OK.

Kind Regards,

Hello Pjve64,
thanks a lot for your test!