Skip to content

cload: Initial import. #3951

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open

Conversation

pavelmachek
Copy link
Contributor

This allows running binary code on Bangle.js2.

Copy link
Collaborator

@bobrippling bobrippling left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice - tagging @gfwilliams for interest

# --emit-relocs
LDFLAGS=-Ttext=0x0100 $(ARCH_FLAGS)

all: $(TARGET).bin
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably want .PHONY: all and the same for dump, etc below here


function load() {
bin = new Uint8Array(12*1024);
binData = Uint8Array(require("Storage").readArrayBuffer("cload.bin"));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this just be binData = bin (or make them the same) ?

ram = new Uint8Array(rams);

msg("Reloc");
io[3] = 0x51a87;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might it be worth noting down the source of these addresses?

Comment on lines +97 to +106
"str sp, [r0, #0] \n"
"str lr, [r0, #4] \n"
"str r4, [r0, #8] \n"
"str r5, [r0, #12] \n"
"str r6, [r0, #16] \n"
"str r7, [r0, #20] \n"
"str r8, [r0, #24] \n"
"str r9, [r0, #28] \n"
"str r10, [r0, #32] \n"
"str r11, [r0, #36] \n"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a stm equivalent for the target arch?

"ldr r11, [r1, #36] \n"

"bx lr \n"
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want clobbers on this (and the other asms) ?

);
}

volatile char welcome[] = "Hello\nwatch\n:-)";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you make these (and all functions except public ones) static you'll get better loads/stores and potentially less memory use with the GOT depending on how the linker fares


// Save 32 FPU registers (S0–S31) and FPSCR (Floating Point Status and Control Register)
void call_with_fpu_preserved(void (*func)(void)) {
__asm volatile (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the asms really volatile ? There's nothing non-deterministic going on

Comment on lines +213 to +214
for (int i=0; i<sizeof(alt_stack); i++)
alt_stack[i] = 0xbe;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would the memset above do the trick here?

int remainder;
} divmod_result;

// __aeabi_idivmod: FIXME this likely needs to return values in registers
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the gcc attribute is pcc_reg_return or something like that (from memory)

@gfwilliams
Copy link
Member

It's great that you got this working, but I feel like surely this should just be added as _example_compiled_c or something? It's not just an app that someone can install from the app loader and magically have C.

There's also all the code for relocation you're doing, but I think if you use -fpic to ask for position independent code, the code will 'just work' when running from RAM without having to have a relocation step? The compiler we use for Inline C uses a bunch of flags to create its code that might help: https://github.com/gfwilliams/EspruinoCompiler/blob/master/src/compile.js#L457-L469

It might also be worth mentioning https://www.espruino.com/InlineC in the README. That's built in and while it's just for code defined inline, it 'just works' in the IDE and app loader I believe, so you don't have to worry about hard-coding addresses or anything.

@pavelmachek
Copy link
Contributor Author

gfw: I experimented a bit some time ago, and could not find reliable way to get code that did not need relocations.

I know about InlineC, but it relies on server magic somewhere, and is not really meant for, say, 2000 lines of C being imported that way. I'll add pointer to documentation.

@gfwilliams
Copy link
Member

This is the code I've used quite recently to compile C code to something that can be embedded. It worked great for me, and the code mostly comes from EspriunoCompiler. Hopefully it will help? Hopefully with it, we can do the without hard-coded addresses in the JS.

This is for one function, but I believe you should be able to handle others in a similar way - we already do return E.nativeCall(new DataView(E.toArrayBuffer(bin)).getUint32(0,1),... which uses the pointer in the first word as the function pointer, so you just need to ensure the second function pointer goes in 2nd word and so on

Example c file:

int main(uint32_t a) {
}

void *entryPoint[]  __attribute__ ((section (".entrypoint"))) = {(void*)main};

linker.ld:

ENTRY(entryPoint)

MEMORY
{
  RAM (xrw)       : ORIGIN = 0, LENGTH = 100K
}

SECTIONS
{
  .entrypoint :
  {
    . = ALIGN(4);
    *(.entryPoint)
  }
  /* We put everything in .text section as we load everything into RAM as one binary string */

  .text :
  {
    . = ALIGN(4);
    *(.text)
    *(.text*)
    *(.rodata)
    *(.rodata*)
    . = ALIGN(4);
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */
    . = ALIGN(4);
    *(.bss)
    *(.bss*)
    *(COMMON)
    . = ALIGN(4);
  } >RAM

  /* Remove stuff we don't want */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
    *(.ARM.*)
    *(.comment)
  }
}

Commands to create base64 code that can be run as-is:

INCLUDES="-I... "
CFLAGS="-mlittle-endian -mthumb  -mthumb-interwork -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -std=gnu11 -nostdlib -fno-common -fno-exceptions -fdata-sections -ffunction-sections -flto -fno-fat-lto-objects -Wl,--allow-multiple-definition -fpic -fpie -fpermissive -Os -Tlinker.ld "
arm-none-eabi-gcc $INCLUDES $CFLAGS compiledcode.c -o compiledcode.elf || exit 1
# arm-none-eabi-objdump -x -S compiledcode.elf # debug print
arm-none-eabi-objcopy -O binary compiledcode.elf compiledcode.bin || exit 1
echo "(function(){var bin=E.toFlatString(atob(\"`base64 compiledcode.bin  | tr -d '\n\r'`\"));return E.nativeCall(new DataView(E.toArrayBuffer(bin)).getUint32(0,1),'int(int)', bin);})"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants