BenF V3 source code

also on a related note, can we get a consistent naming convention for the files posted on google code?
As somebody who does not read this forum every day sometimes it’s hard to figure out what each file represents only from the title. Maybe some folders / consistent tagging …

I find that 0x0800c121 is the entry point of the app using IAR4.0. You can find the following sentences in the map file of the app project:
Program entry at : 0800C121 Relocatable, from module : ?CMAIN .
__program_start 0800C121 Absolute parts (?ABS_ENTRY_MOD) __vector_table (stm32f10x_vector)
Yet the mapping file is different in IAR5.0 . You can not find that sentence. I just set the __APP_Start to __iar_program_start. It did’t work. And we can not set __APP_Start to 0x0800c004, because the reset function is not the main function.

0x800c004 is not the main function, but contains a pointer to the reset handler, which after initializing variables, jumps to main(). So just read the address out of 0x800c004 and jump to it. The same is done in the DFU boot loader, for chainloading the LIB.

Both APP and LIB should do their initializing of variables, and since they do not share data segments (RAM sections defined in linker script does not overlap) it should not cause any issues either.

0x800c004 is not the main function, but contains a pointer to the reset handler, which after initializing variables, jumps to main(). So just read the address out of 0x800c004 and jump to it. The same is done in the DFU boot loader, for chainloading the LIB.

Thanks for your reply. Yes, the 0x800c004 is the pointer of the reset vector,I tried that way and it did’t work. In Ben’s firmware using IAR4.0, __APP_Start is not the reset handler but the program entry __program_start. I think the among reset handler and __program_start,there are some IAR internal function.

Thanks, I see. So whatever the APP reset handler does before calling APP __program_start would make it fail. It would be interesting to know what is going on there. Maybe something important (but something that can only be done once) that we miss in the gcc build. Can you please attach an elf file produced by IAR, so that I can try disassemble it?

I studied the IAR stuff, and the __program_start is indeed the reset handler. You can see this in EWARM/stm32f10x_vector.c
And 0x0800C121 which is APP_START in Ben’s LIB matches the reset vector you can see in Ben’s APP binary (byte 5-8).

So there must be another reason it did not work. Does this patch work? It is against current gcc branch. The gcc branch should build fine on IAR as well, otherwise I would like to fix it!

I tested on IAR 4.0 with calling the reset vector rather than a hardcoded assembly branch instruction and it woks as expected.

One issue with the proposed patch however is the following:

-__APP_Start ;void __APP_Start(void)

  • B 0x0800C121

If you remove those lines, addresses for callback from APP back into LIB will be incorrect. You should be able to start APP, but as soon as you call back into LIB (such as GetFonts) it is likely to fail miserably unless you adjust the vectors in APP accordingly.

A related aspect to consider is the _APP_Start label in LIB. This is hardcoded in APP and serves as an offset from where branch addresses to LIB functions can be found. This label may very well be placed at a different offset on Gcc and perhaps also IAR 5.0. Once you start APP, interrupt vectors are reasssiged into the APP program segment (away from LIB). USB service interrupts however are channeled back into LIB and so this is likley to crash hard and fast unless addresses are properly mapped.

If you look at this logic and verify harcoded/absolute addresses against the map file, you may be able to pick up and see some progress again.

Rgds
BenF

Thanks for looking at it! I originally thought these two lines only defined an __APP_Start() function (jumping to 0x0800C121, and I could just remove it since we do not use it (with the patch applied). But I understand the removal of this code will shift the following code a few bytes backwards… I should replace it with a dummy branch or enough NOPs. It is ugly in any case.

I don’t see anywhere that the branch table (in ASM_Function.s) is anchored to any address. Is it related to __APP_Start in any way? Anyway, I guess a better solution would be to put the table into a separate section and specify a fixed location in the linker script, for instance immediately after the interrupt vector table.

Very interesting. How are these channeled back? I thought the APP brings its own, complete set of interrupt routines.
EDIT: Oh, I got it: the __CTR_HP and _USB_Istr service the USB interrupts.

This definitely needs a solid rework in the gcc port. Tempting to get rid of the split and just link everything the normal way… But compatibility with IAR is the better way for now, I think.

However, the most important problem in the gcc port right now must be something different than these issues, because it does not seem to even come that far in the LIB that it will jump to APP. The screen remains white with no logos or texts displayed.

It is exacly like this in IAR4 - the vector table in LIB is located in segment CODE, which is
of type CODE and aligned on 2-byte boundaries; the table begins with __APP_start, so
other symbols could be located by computing the offset.

Here’s the excerpt from LIB’s ASM_Functions.s:

RSEG CODE:CODE(2)
__APP_Start                ;void __APP_Start(void)
    B       0x0800C121
__USB_Istr                 ;
    B       USB_Istr
__CTR_HP                   ;
    B       CTR_HP
__MSD_WriteBlock           ;
    B       MSD_WriteBlock
__MSD_ReadBlock            ;
    B       MSD_ReadBlock
__Get_Font_8x14            ;
    B       Get_Font_8x14
__Get_Ref_Wave             ;
    B       Get_Ref_Wave
__SD_Set_Changed           ;void SD_Set_Changed(void);
    B       SD_Set_Changed

The only EXPORTED symbol is __APP_Start, which contains the IAR4 entry point for APP.

Now, the parallel definitions in APP’s ASM_Functions.s are these:

__CTR_HP                  ;void __CTR_HP(void)
    B       0x08004159
__USB_Istr                ;void __USB_Istr(void);
    B       0x08004155
;-------------------------------------------------------------------------------
__MSD_WriteBlock          ;u8 __MSD_WriteBlock(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
    B       0x0800415D
__MSD_ReadBlock           ;u8 __MSD_ReadBlock(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead)
    B       0x08004161
__Get_Font_8x14           ;u16 __Get_TAB_8x14(unsigned char Code, unsigned short Row)
    B       0x08004165
__Get_Ref_Wave            ;u8 __Get_Ref_Wave(unsigned short i)
    B       0x08004169
__SD_Set_Changed          ;void __SD_Set_Changed(void)
    B       0x0800416D

from which you can infer that __APP_Start resides in memory at location 0x08004151 when LIB is compiled under IAR4. Of course, it won’t get the same address with IAR5 - there’s a brand new linker, there.

And, for the very same reason (as you already pointed out), __APP_Start should be updated to contain a different address - the APP entry point under both gcc and IAR5 will be different from 0x0800C121.

Well, this needs a solid rework in IAR5 too :wink:

A good starting point for me could be the one you proposed - a separate section whose address is specified via linker config. These notes explain how to do that in IAR5:
http://supp.iar.com/Support/?note=36121
http://supp.iar.com/Support/?note=17934

Don’t know about gcc, but another problem in the migration to IAR5 could be given by different stack alignment: from the migration guide at http://supp.iar.com/FilesPublic/SUPPORT/004242/EWARM_MigrationGuide.ENU.pdf, I read

Antonio

I’ve had a go with IAR5 - if you uncomment WaitForKey, the LIB works ok up to that point - so definitely we just need to update the jump into APP. I’ve then updated the symbol table inside APP, and bingo, it works :sunglasses: The magic numbers follow.

In LIB, use:

__APP_Start                ;void __APP_Start(void)
    B       0x08010cd1

In APP, when LIB’s main has WaitForKey uncommented, use:

__CTR_HP                  ;void __CTR_HP(void)
    B       0x08007219
__USB_Istr                ;void __USB_Istr(void);
    B       0x08007215
;-------------------------------------------------------------------------------
__MSD_WriteBlock          ;u8 __MSD_WriteBlock(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
    B       0x0800721D
__MSD_ReadBlock           ;u8 __MSD_ReadBlock(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead)
    B       0x08007221
__Get_Font_8x14           ;u16 __Get_TAB_8x14(unsigned char Code, unsigned short Row)
    B       0x08007225
__Get_Ref_Wave            ;u8 __Get_Ref_Wave(unsigned short i)
    B       0x08007229
__SD_Set_Changed          ;void __SD_Set_Changed(void)
    B       0x0800722D

In APP, when LIB’s main has WaitForKey commented, use:

__CTR_HP                  ;void __CTR_HP(void)
    B       0x08007205
__USB_Istr                ;void __USB_Istr(void);
    B       0x08007201
;-------------------------------------------------------------------------------
__MSD_WriteBlock          ;u8 __MSD_WriteBlock(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
    B       0x08007209
__MSD_ReadBlock           ;u8 __MSD_ReadBlock(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead)
    B       0x0800721D
__Get_Font_8x14           ;u16 __Get_TAB_8x14(unsigned char Code, unsigned short Row)
    B       0x08007211
__Get_Ref_Wave            ;u8 __Get_Ref_Wave(unsigned short i)
    B       0x08007215
__SD_Set_Changed          ;void __SD_Set_Changed(void)
    B       0x08007219

Have fun!

Antonio

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)
    THUMB
__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:

Antonio

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.

Antonio

Thanks,Antonio.
You can send modified files to deyou.wang@seeedstudio.com. 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,
Pjve