Shop Learn P1 Docs P2 Docs
LLVM Backend for Propeller 2 - Page 6 — Parallax Forums

LLVM Backend for Propeller 2



  • glad you got it working. clearly there's work to be done on getting new folks set up, but things like compiling llvm and libp2 should be something the typical developer won't have to do. We'll get there...

    Let me know how things go and if anything else doesn't work as expected.

  • iseriesiseries Posts: 1,283

    I think I have a lot of things on my plate done.

    1) does it work on windows. Check
    2) can I compile my programs. Check
    3) does it work with Visual Studio Code. Check

    I made massive changes to propeller2.c and propeller2.h. I also change how crt0.c works. Don't know if you will like it though.

    Anyway now programs just look normal:

     * Lets do some C++ thinks
     * default baud rate is 230400
    #include <propeller2.h>
    #include <stdio.h>
    #include "Blinker.h"
    Blinker led1(56, 1000);
    Blinker led2(57, 1000/2);
    Blinker led3(58, 1000/3);
    Blinker led4(59, 1000/4);
    int main() {
        while(1) {

    Blinker object:

    #include "Blinker.h"
    #include <propeller2.h>
    #include <stdlib.h>
    #include <stdio.h>
    Blinker::Blinker(char pin, int delay) {
        this->pin = pin;
        this->delay = delay;
    void Blinker::start() {
        const int stack_size = 32;
        unsigned int *stack = (unsigned int *)malloc(stack_size);
        int cogid = cogstart(blink, this, stack, stack_size);
        printf("cog ID is %d\n", cogid);
    void Blinker::blink(void *par) {
        Blinker *led = (Blinker*)par;
        while(1) {

    I see you imported a lot of the P1 stuff and made some changes. I think you should be thing along the lines of Arduino. I know it will have to be dummied down a bit to fit but this could bring a whole lot of C++ people to the P2.

    If haven't said it yet, Great Job. Don't know how you pulled it off, but this thing is amazing.


  • Love it!

    Can you share your changes to the p2 library? I'll see what makes sense to incorporate it, but I'm thrilled to have someone else making improvements to it.

    I'm a bit split on making this "arduino-like". I think it is powerful for people people getting started with microcontrollers and with propeller, but for professional development, something arduino-like might be too restrictive. But my hope is to provide the core C++ tools, and have those who have more patience than me develop the libraries :). With that, there can be a separate arduino-like library to wrap all the hardware into nice objects, but give full flexibility to those who need it.

    (Full disclosure, I've never actually used Arduino, my only experience with AVR and Atmel has been using their original hardware libraries. Other than that it's been all propeller).

  • @n_ermosh said:
    Love it!

    Can you share your changes to the p2 library? I'll see what makes sense to incorporate it, but I'm thrilled to have someone else making improvements to it.

    I'm a bit split on making this "arduino-like". I think it is powerful for people people getting started with microcontrollers and with propeller, but for professional development, something arduino-like might be too restrictive. But my hope is to provide the core C++ tools, and have those who have more patience than me develop the libraries :). With that, there can be a separate arduino-like library to wrap all the hardware into nice objects, but give full flexibility to those who need it.

    (Full disclosure, I've never actually used Arduino, my only experience with AVR and Atmel has been using their original hardware libraries. Other than that it's been all propeller).

    I'm with you on this. Compilers should not ship with high-level, powerful libraries like what Arduino provides. Even if those high-level libraries are provided in addition to low-level libraries, it's cumbersome to update a compiler. Anything high-level is likely to change as the opinions of developers change and folks want something even higher level or with a slightly different parameter set. So, the compiler's standard library should provide the minimum necessary to get the job done at a very low level, and then user libraries can/should add to that.

  • iseriesiseries Posts: 1,283

    The point I was trying to make is to provide an Arduino environment so this product could be use with the Arduino build system. This would allow people that program on Arduino could pick P2 as one of the platforms and compile Arduino code which is C++.

    Now you can use Adafuits, Sparkfun, projects on your P2 platform and not just provide hi level libraries.

    This will bring developers to the P2 without them having to learn an entire new environment.

    If you have built Arduino programs you will understand what I mean.


  • iseriesiseries Posts: 1,283

    I have some assembly code that's not working.

         abc: 08 a4 67 f0            shl r2, #8 
    00000ac0 <L1>:
         ac0: 01 a4 b7 f0            rcl r2, #1 wc
         ac4: 1f aa 63 cd       if_c     waitx r5   
         ac8: 1f a8 63 3d       if_nc    waitx r4   
         acc: 59 a2 63 fd            drvh r1    
         ad0: 1f a8 63 cd       if_c     waitx r4   
         ad4: 1f aa 63 3d       if_nc    waitx r5   
         ad8: 58 a2 63 fd            drvl r1    
         adc: f8 a1 6f fb            djnz r0, #-8

    The before code:

    asm volatile("   shl %0, #8\n"
            "L1:   rcl %0, #1 wc\n"
            "if_c   waitx %1\n"
            "if_nc  waitx %2\n"
            "   drvh %3\n"
            "if_c   waitx %2\n"
            "if_nc  waitx %1\n"
            "   drvl %3\n"
            "   djnz %4, #L1\n"
            :"r"(H), "r"(L), "r"(pin), "r"(bits));

    The djnz jump is always -8 and should be -32.


  • n_ermoshn_ermosh Posts: 288
    edited 2022-01-29 17:52

    I see what you mean about Arduino. Yes, making an arduino-compatible environment for propeller would be great, but that’s not something I plan to take on any time soon. Maybe there’s someone out there who will?

    The djnz is correct to be -8. See page 20 of the silicon docs. In hub mode, the immediate gets shifted by two bits before changing PC, so that the operand is always whole the number of whole instructions to jump.

    One warning about inline assembly I should put out there. When passing in constraints, “r” works fine for register constrains. “i” for immediates will only work if the immediate is less than 9 bits. I don’t yet have the code that will modify inline asm statements to automatically insert an augs/augd. Just something to be aware of. Maybe I’ll look into that today.

  • @iseries said:
    The point I was trying to make is to provide an Arduino environment so this product could be use with the Arduino build system. This would allow people that program on Arduino could pick P2 as one of the platforms and compile Arduino code which is C++.

    Now you can use Adafuits, Sparkfun, projects on your P2 platform and not just provide hi level libraries.

    This will bring developers to the P2 without them having to learn an entire new environment.

    If you have built Arduino programs you will understand what I mean.


    Last I saw (which was a few years ago) Arduino was built on top of GCC. Even if/when Nikita's work gets merged upstream into LLVM, that will not make it available in the Arduino IDE. I think the Arduino IDE might be open source, so I guess you could hack it apart and stick LLVM in there. But at that point... it's probably easier to just take something like and uplift it to work with P2/LLVM. Then combine that with the build system/IDE of your choice, which could well be PropWare/CLion or PropWare/VSCode.

  • iseriesiseries Posts: 1,283

    Yes, I just read the manual on djnz and see that it's instructions and not addresses.

    I am converting my custom libraries that I have for different hardware interfacing, and I am running into some issues. I don't want to build a make file for every project that uses an object library. I need it to automatically link in when the library is referenced. How can I use a custom library with my programs?

    This is the program:

    #include "Custom/ws2812.h"
    #include <stdio.h>
    #include <propeller2.h>
    #define WSLED 40
    #define LED_COUNT 12
    unsigned long ledColors[LED_COUNT];
    int i;
    unsigned long c[3];
    int main()
      int x;
      c[0] = COLOR(32,0,0);
      c[1] = COLOR(0,32,0);
      c[2] = COLOR(0,0,32);
      x = 0;
      for (int i=0;i<12;i++)
        for (int j=0;j<LED_COUNT;j++)
          if (x > 2)
            x = x - 3;
          ledColors[j] = c[x++];
        ws2812_set(WSLED, ledColors, LED_COUNT);
      for (int i=0;i<LED_COUNT;i++)
        ledColors[i] = 0;
      ws2812_set(WSLED, ledColors, LED_COUNT);

    Here is a video of the results


  • Awesome!!

    Regarding having it automatically link based in what's included, I'm not familiar with any mechanism that will do that. Maybe clang has some pragma directive to add a linker flag, but it's not something I'm familiar with. You could convert your hardware stuff into header-only libraries, now that you have full C++ functionality. But, that obviously bloats your translation units and for very large projects will slow down compile time.

    I would also recommend looking into cmake. I was annoyingly against it cause it felt like too much overhead, but once I set up one project with cmake, I'm never turning back. It's so powerful to manage all these kinds of things.

  • iseriesiseries Posts: 1,283

    The problem is that I'm using Visual Studio Code as my IDE and having to build a bunch of Cmake or Make files is not elegant.

    I see when I link my projects that libp2.a and libc.a get loaded auto magically. How you do that?


  • I also use VSCode, it has great extensions for make or cmake, but if it doesn't have the elegance you need then fair enough.

    libp2 and libc are added as link flags by the P2 target driver in clang. Changing that requires recompiling clang, so not a solution I think that would work for you.

  • iseriesiseries Posts: 1,283

    Got the custom library thing working. Created an archive and added it to linking script. Just compile and run now.

    ELF bloat? I was updating my P2 loader program so I could load elf files and in the process noticed that the files were rather large. Loading also took a bit over Wifi.

    Looking into it, it seems that the linker wants to load the debug code even though there is none.

    p2.ld file has this at the end:

        .debug : {
            . = 0x7c800;
            . = 0x7fc00;

    I removed it and now the files seem normal and load a lot faster.


  • yeah if the debug code is present, it will try to load basically the full 512 kb of memory, which is obviously slow. this is where loadp2's staged loading could be helpful. But it's odd that it's trying to load that section if you don't have any of the debug code linked.

  • iseriesiseries Posts: 1,283

    Converting some library functions and I'm having a problem assigning a function to a pointer..

    BME280_INTF_RET_TYPE bme280Read(uint8_t, uint8_t *, uint16_t, void *);
    BME280_INTF_RET_TYPE bme280Write(uint8_t, uint8_t *, uint16_t, void *);
    void bme280Wait(uint32_t, void *);
    int main(int argc, char** argv)
        //i2c_open(&Bme, BMESCL, BMESDA, 1);
        Bme = I2C_Init(BMESCL, BMESDA, I2C_STD);
        struct bme280_dev dev;
        int8_t rslt = BME280_OK;
        uint8_t dev_addr = BME280_I2C_ADDR_SEC;
        dev.intf_ptr = &dev_addr;
        dev.intf = BME280_I2C_INTF; = bme280Read;  //<--- this is the problem..
        dev.write = bme280Write;
        dev.delay_us = bme280Wait;
        rslt = bme280_init(&dev);
        switch (rslt)
            case 0: printf("Ok\n");
            case -1: printf("Null Pointer\n");
            case -2: printf("Device Not Found\n");
            case -3: printf("Invalid Length\n");
            case -4: printf("Comunictions Failed\n");
            case -5: printf("Sleep Mode Failed\n");
            case -6: printf("Environment Copy Failed\n");
        while (1)

    The compiler is trying to assign the return type of the function and not assign it to the variable.


  • That seems like a front-end issue. Odd, I'll look into it. can you please write and provide the smallest example that reproduces this issue, that doesn't rely on your hardware libraries. I've used function pointers pretty extensively with no problems.

  • iseriesiseries Posts: 1,283

    I didn't write the driver. It comes from Bosch that way. It kind of hides the hardware functions.

    Anyway here is a link to the driver from bosch.BME280 driver

    The driver compiles no problem.

    This code works with FlexSpin.


  • iseriesiseries Posts: 1,283

    Never mind, I got it to work I think. I had to provide cast.

        dev.intf_ptr = &dev_addr;
        dev.intf = BME280_I2C_INTF; = (bme280_read_fptr_t)bme280Read;
        dev.write = (bme280_write_fptr_t)bme280Write;
        dev.delay_us = (bme280_delay_us_fptr_t)bme280Wait;


  • iseriesiseries Posts: 1,283

    Working on converting some library device functions which is working fine. Trying to add some libc functions though is leading into random memory issues that I cannot pin down. Compiled code looks good but the code crashes. Changing one line of code causes something different to crash. Will continue to look at it.

    There are some instructions that are missing:


    This are used for smartpins.


  • I can add those in today (not all instructions are supported as there are a lot of them so I only added them as they were needed). Let me know if you get completely stuck with the memory issues--I can try to allocate some time to get the debugger tool in a cleaner state so that you can use it to step through code one line at a time and see what's crashing

  • iseriesiseries Posts: 1,283

    This program crashes for me everytime.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <propeller2.h>
    unsigned char b[128];
    unsigned char Buffer[128];
    unsigned char data[] = "Now is the time for all good men.";
    int main(int argc, char** argv)
        //b = malloc(128);
        printf("Coping into buffer\n");
        memcpy(Buffer, data, 24);
        printf("Coping Buffer to memory\n");
        memcpy(b, Buffer, 24);
        printf("Memory: %24.24s\n", b);
        while (1)


  • issue was that memcpy, memmove, and memset are expected to be in the runtime library and therefor live in LUT RAM, but weren't marked as going in the LUT section so the linker put them in the wrong place. fixed now, and those instructions were added.

  • iseriesiseries Posts: 1,283
    edited 2022-02-08 13:17

    Don't quite understand what LUT has to do with moving data around in HUB ram but it seems to have fixed that issue.

    Still have some printf weirdness still going on.

    I added an SD card driver to the libc functions so I can read sd cards now. Here is the test program that I used:

    #include <sys/types.h>
    #include <sys/time.h>
    #include <errno.h>
    #include <stdio.h>
    #include <fcntl.h>
    #include <string.h>
    #include <propeller2.h>
    #include <sdcard.h>
    void dodir(void);
    void doread(void);
    void dowrite(void);
    char Buffer[512];
    FILE *fp;
    int i;
    unsigned p;
    int main(int argc, char** argv)
        struct tm ti;
        struct timeval tv;
        time_t t;
        ti.tm_year = 2021 - 1900;
        ti.tm_mon = 2;
        ti.tm_mday = 7;
        ti.tm_hour = 6;
        ti.tm_min = 0;
        ti.tm_sec = 0;
        t = mktime(&ti);
        tv.tv_sec = t;
        settimeofday(&tv, 0);
        i = sd_mount(PIN_SS, PIN_CLK, PIN_MOSI, PIN_MISO);
        if (i != 0)
            printf("Mount Failed\n");
            while (1)
        while (1)
    void dodir()
        DIR *dir;
        struct dirent *ent;
        dir = sd_opendir("/");
        if (dir == NULL)
            printf("Directory Failed(%d)!\n", errno);
            while (1)
        while (!sd_readdir(dir, ent))
            if (ent->d_type & 0x10)
                printf("d %s\n", ent->d_name);
                printf("  %s\n", ent->d_name);
    void doread()
        printf("Opening file OneCall\n");
        fp = fopen("SD:/OneCall.txt", "r");
        if (fp == NULL)
            printf(" File Not Found!\n");
            while (1)
        i = fread(Buffer, 1, 256, fp);
        printf("Read %d bytes\n", i);
        Buffer[i] = 0;
        printf("Buffer: %s\n", Buffer);
    void dowrite()
        printf("Writing log file\n");
        fp = fopen("SD:/logfile.txt", "a");
        if (fp == NULL)
            printf("File Creation Error!\n");
            while (1)
        printf("File Pointer %lx\n", (unsigned long)fp->drvarg[0]);
        printf("Buffer Base: %lx\n", (unsigned long)fp->_base);
        printf("Buffer Size %d\n", (int)fp->_bsiz);
        printf("File Flags: %x\n", fp->_flag);
        printf("File Lock: %d\n", fp->_lock);
        printf("Buffer Pointer: %lx\n", (unsigned long)fp->_ptr);
        printf("Buffer Count: %d\n", fp->_cnt);
        printf("Driver Open: %lx\n", (unsigned long)fp->_drv->fopen);
        printf("Driver Read: %lx\n", (unsigned long)fp->_drv->read);
        printf("Driver Write: %lx\n", (unsigned long)fp->_drv->write);
        printf("Driver Close: %lx\n", (unsigned long)fp->_drv->fclose);
        printf("About to write...\n");
        i =  fwrite("Test Data only\n", 1, 15, fp);
        printf("Wrote %d\n", i);
        printf("Error: %d\n", errno);

    This test program outputs the following:

    Executing task: Build P2LLVM Program <
    Starting build...
    d:/opt/p2llvm/bin/clang.exe -Oz -ffunction-sections -fdata-sections -fno-jump-tables --target=p2 -Dprintf=__simple_printf -o D:\Documents\P2LLVM\build\TestSD.o -c D:\Documents\P2LLVM\TestSD.c
    Build finished successfully.
    Terminal will be reused by tasks, press any key to close it.
      Executing task: Link P2LLVM Program <
    Starting build...
    d:/opt/p2llvm/bin/clang.exe --target=p2 -Wl,--gc-sections -Wl,--print-gc-sections -Ld:\documents\p2llvm\Custom\build -lcustom -Os -o D:\Documents\P2LLVM\build\TestSD.elf D:\Documents\P2LLVM\build\TestSD.o
    removing unused section D:\Documents\P2LLVM\build\TestSD.o:(.text)
    removing unused section D:\Documents\P2LLVM\build\TestSD.o:(.bss.p)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(fopen.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(fopen_intern.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(fopen_intern.o):(.data)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(fflush.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(fwrite.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(fread.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(simple_printf.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(fputc.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(default_io.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(init_io.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(ctype.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(SimpleSerial.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(atoi.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(terminal.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(SDDriver.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(SDDriver.o):(.text.sd_creat)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(SDDriver.o):(.text.sd_stat)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(SDDriver.o):(.text.sd_ioctl)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(SDDriver.o):(.text.sd_mkdir)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(SDDriver.o):(.text.sd_rmdir)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(SDDriver.o):(.text.sd_rename)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(errno.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(errno.o):(.text._geterror)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(errno.o):(.text._geterrnoptr)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(calloc.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(malloc.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(sbrk.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(sbrk.o):(.heap)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(ff.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(ff.o):(.text.f_stat)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(ff.o):(.text.f_getfree)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(ff.o):(.text.f_truncate)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(ff.o):(.text.f_mkdir)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(ff.o):(.text.f_rename)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(ff.o):(.text.f_mkfs)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(ff.o):(.rodata.str2.2)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(ff.o):(.rodata.cst16)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(ffunicode.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(diskio.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(sd_mmc.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(thread.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(memcpy.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(memset.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(strlen.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(strncmp.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(strncpy.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(time.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(localtim.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(localtim.o):(.text.gmtime)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(getenv.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(gettimeofday.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(crt0.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(crt0.o):(.text.__cxa_pure_virtual)
    removing unused section d:\opt\p2llvm\bin\..\libc.a(init_cstd.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text._cnt)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text._waitcnt)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text._waitx)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text._getsec)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text._getms)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text._clkset)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text._hubset)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text._coginit)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text.cogstart)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text._lockret)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text._locktry)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text._pinw)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text._pinnot)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text._pinr)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text._testp)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text._rdpin)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text._rqpin)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text._wrpin)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text._wxpin)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text._wypin)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text._pinstart)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(propeller2.o):(.text._rev)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(ashldi3.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(ashrdi3.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(divdi3.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(divsi3.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(lshrdi3.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(moddi3.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(modsi3.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(muldi3.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(negdi2.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(udivdi3.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(udivmoddi4.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(umoddi3.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(comparedf2.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(comparesf2.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(fixunsdfdi.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(floatundidf.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(subdf3.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(muldf3.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(adddf3.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(fp_mode.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(mulsf3.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(addsf3.o):(.text)
    removing unused section d:\opt\p2llvm\bin\..\libp2.a(subsf3.o):(.text)
    Build finished successfully.
    Terminal will be reused by tasks, press any key to close it.
      Executing task: d:/opt/p2llvm/p2loader.exe com10 'd:\Documents\P2LLVM\build\TestSD.elf' <
    Loading 104300 bytes.
    Entering terminal mode.  Press Ctrl-] to exit. 
    System Volume Information  System Volume Information
    OneCall.txt  OneCall.txt
    logfile.txt  logfile.txt
    BigFileName.bin  BigFileName.bin
    eName.binRead 256 bytes
    Buffer: {"lat":44.84,"lon":-87.37,"timezone":"America/Chicago","timezone_offset":-18000,"current":{"dt":1592063363,"sunrise":1592042574,"sunset":1592098
    Writing log file
    File Pointer 1a0f4
    Buffer Base: 1a0ac
    Buffer Size 64
    File Flags: 4802
    File Lock: 3
    Buffer Pointer: 1a0ac
    Buffer Count: 0
    Driver Open: 2a2c
    Driver Read: 2bb4
    Driver Write: 2c18
    Driver Close: 2b30
    Wrote 15
    Error: 0

    You can see where it printed the file directory off the SD card it doesn't print what print statements show....

    The program does work and does read a file off the SD card and write to the end of another with the correct data without crashing....

    I also converted the TFMINI driver over and had to use serial to get the data from this device. I first converted my serial driver over and that worked.

    Then I tried to get it to work with simple serial driver and that did not work. I had to change it a little because the serial_getbyte checks were backwards and the uart section did not enable _IORW for the driver.


  • Regarding LUT: There's a set of functions that are part of the "builtin runtime library", as defined by LLVM here. Basically, this is all the math operations that aren't supported in hardware, and the 3 basic memory manipulation functions (memset, memmove, memcpy). I've defined the ABI such that these functions should be loaded into each cog's LUT RAM. If the function doesn't get marked as going in the .lut section, it won't get loaded and behavior will be undefined when calling it. But that's all fixed now

    I'm not really familiar with the SD card driver, been a long time since I did SD card stuff on P1, so not sure if I can offer any specific help, but something does seem off. Try disabling --gc-sections? maybe it's removing something it thinks is unnecessary. Can you attached the sd driver code? and provide details about how you set up the SD card for use with the p2 eval board, I'll try it out and see what's going on.

  • iseriesiseries Posts: 1,283

    I didn't use the SD functions that came with the P1 code. I am using the chan-fatfs code.

    This took some work as I had to write a driver function to work with the GCC code that was already there. Then rework the assembly code that did the low level card reading.

    I like this code because it supports long file names and does not rely on any spin code to work.

    This code seems to be working though except for the simple_printf functions that dump the directory entries. This I have not looked into since I was having issues with the memory code doing funky thinks on me. Now that this seems to be fixed I can start to look at it.

    I do need a stable printf function as this is the only means I have to debug code. The llvm-objdump helps too.

    I don't know what you have for hardware but I can put up the pieces for the SD card driver so far.

    Need to convert the simpletools functions so that people moving from the P1 can feel at home.


  • I wonder if the printf not dumping properly is due to like a leading \0 byte so it just quits printing early? The printf function itself should be okay, I'm betting it's the data going into it that's got some weirdness to it. But I could be wrong, could be some corner case.

    I just have a P2 eval board, and a P2 edge on the way. sounds like getting you the debugger would be pretty useful--that's pretty much how I find all these random bugs now... It's currently written in python and uses a large terminal window to draw everything. I might move to an actual UI, but terminal works pretty well honestly. Would python work for you if I clean up that application so that you and others can use it? I wrote it in like 2 nights so its pretty rough right now.

  • iseriesiseries Posts: 1,283

    I don't know that a debugger will help here. A lot of times I'm trying to track down a timing issue and using a debugger adds size to the program and messes with the timing of things.

    Anyway I found my printf issues with directory printing.

    I went through and reassembled the disassembled code for that function and tracked down all the memory references which turns out to be just 0x1000 more that the memory reference in the program from the ELF file.

    I noticed right away that there were some tests missing and some printf statements missing.

    After walking through the code I got it to match my output. Aha, says the blind man. You're passing a pointer to a function that expects a pointer to a directory object. Oops, I fell into that conversion trap instead of writing it from scratch. The old code allocated a structure that it filled in and I was not.

    Now the code prints just fine and I can move on to the next pit fall.


  • iseriesiseries Posts: 1,283

    Went through and converted most of Simpletools, simplei2c and fixed up the inline assembly issues that I had.

    Have a lot of issues with unsigned char and unsigned int not working the same. clang sign extends them so my 129 character turns into -1,

    Missing some more assembly functions:


  • That's great progress! Have you been able to fully test all the features of simpletools or just compile?

    Yeah C/C++ standard says chars being signed or unsigned is platform specific, and I guess clang's default is to treat them as signed (which I think semantically makes sense).

    I'll add those instructions in today.

  • iseriesiseries Posts: 1,283

    I tested most of the functions as I added them, that's why I need those extra assembly items added.

    Can't create a pull request to add all the item to your repository, conflicts. You should be able to see all the items though.


Sign In or Register to comment.