Shop OBEX P1 Docs P2 Docs Learn Events
riscvp2 _clkset not working — Parallax Forums

riscvp2 _clkset not working

n_ermoshn_ermosh Posts: 294
edited 2020-05-02 23:43 in Propeller 2
Trying to get riscvp2 running from https://github.com/totalspectrum/riscvp2 and the loader from https://github.com/totalspectrum/loadp2. I'm able to compile and load programs, but it seems like _clkset() doesn't work. Below is my code and Makefile.

code:
#include <propeller.h>
#include <sys/p2_clock.h> // must be inluded in top level for defining _SETFREQ and _CLOCKFREQ based on defined clock frequency in makefile

#include <stdio.h>
#include <stdint.h>

void main() {

    _clkset(_SETFREQ, _CLOCKFREQ);

    printf("clock set 0x%x, should be 0x%x\n", *(int*)0x18, _SETFREQ);
    printf("clock frequency %u Hz, should be %d\n", _clkfreq, _CLOCKFREQ);

    while(1);
}

Makefile:
TOOLCHAIN = /opt/riscvp2
CC = $(TOOLCHAIN)/bin/riscv-none-embed-gcc
LOAD = $(TOOLCHAIN)/bin/loadp2

# hardware and project config
PORT = /dev/cu.usbserial-*
OBJDIR = build
LOAD_MODE = load

TARGET_FREQ = 200 # in MHz
XTALFREQ = 20000000 # in Hz
XOSC = 2

# CLKFREQ = 160000000
# CLKMODE	= 010009f8

CFLAGS = -Wl,-Tfastmath.ld
CLK_CFG = -DP2_TARGET_MHZ=$(TARGET_FREQ) -D_XTALFREQ=$(XTALFREQ) -D_XOSC=$(XOSC)
LOADFLAGS = -t -b 230400 #-f $(CLKFREQ) -m $(CLKMODE)

.PHONY: all setup load clean

all: setup $(OBJDIR)/main.elf $(LOAD_MODE)

setup:
	$(shell pkill loadp2)
	mkdir -p $(OBJDIR)

$(OBJDIR)/main.elf: $(OBJDIR)/main.o
		$(CC) -T riscvp2.ld -o $@ $(CFLAGS)  $^

$(OBJDIR)/main.o: main.c
		$(CC) -T riscvp2.ld -c $(INCLUDES) -o $@ $(CFLAGS) $(CLK_CFG) $<

load: $(OBJDIR)/main.elf
		$(LOAD) $(LOADFLAGS) -p $(PORT) $<

clean:
	rm -rf ./$(OBJDIR)/*


The result printed is:
clock set 0x10007f8, should be 0x10009f8
clock frequency 160000000 Hz, should be 200000000

I also tried patching in the clock frequency and mode, and the I get the following error from the loader:
/opt/riscvp2/bin/loadp2 -t -b 230400 -f 160000000 -m 010009f8 -p /dev/cu.usbserial-* build/main.elf
ERROR: timeout waiting for initial checksum: got -1

am I doing something wrong or is this a bug? Also should mention I tried including "-PATCH" option to the loader and no difference in result.

And tangentially related, is there a way to change the serial baudrate during runtime or does it have to be patched in via the loader?

Comments

  • ersmithersmith Posts: 6,053
    edited 2020-05-03 11:45
    That was definitely a bug. The test for the _clkset syscall was happening in the wrong order with the FPU system calls and so _clkset was never actually being called. That's fixed in github now. I've also added the p2_clock.h include files from fastspin (so you can just #include <sys/p2es_clock.h> instead of having to define the constants in your Makefile).

    When _clkset() is called the serial baud rate is updated based on whatever value is in *(unsigned *)0x1c. So you could patch that manually before calling _clkset() in order to change the baud.

    Thanks for the bug report,
    Eric
  • Thanks Eric, will pull the latest and try it out.

    On an unrelated note, is there a way to start native PASM cogs with risvp2? I have a PASM driver I want to load. In propgcc, there was a special way to compile these with the cog mode memory model, does riscvp2 have something similar?
  • n_ermosh wrote: »
    Thanks Eric, will pull the latest and try it out.

    On an unrelated note, is there a way to start native PASM cogs with risvp2? I have a PASM driver I want to load. In propgcc, there was a special way to compile these with the cog mode memory model, does riscvp2 have something similar?

    Yes, there is. I used the micropython source to figure it out. https://github.com/totalspectrum/micropython/tree/totalspectrum/ports/riscv-p2

    The process goes like this:
    1. Write spin object.
    2. Run spin2cpp. It will generate .c and .h files from the spin source. Spin2cpp records the actual command used at the top of the .c and .h files. PASM code is converted to a byte array.
    3. Incorporate the spin2cpp output .c and .h files into the gcc project.
  • @SaucySoliton that's clever. I ended up mirroring the way all the spin code in the riscvp2 tool is included:

    A simple PASM program:
    DAT
                org 0
                mov pin, ptra
    
    led_loop    drvnot pin
                waitx wait
                jmp #led_loop
    
    wait            long 100000000
    pin             long 0
    

    build it with fastspin to make a binary (led.bin), then compile a wrapper assembly program with the riscvp2 gcc:
        .text
        .globl _cog_led_start
    _cog_led_start:
        .incbin "build/led.bin"
    

    and link it with the main program
    #include <propeller.h>
    
    #include <stdio.h>
    #include <stdint.h>
    
    #define PIN 56
    
    extern uint32_t _cog_led_start[];
    
    void main() {
    
        _cognew(_cog_led_start, PIN);
    
        //printf("starting...\n");
    
        while(1);
    }
    

    This seems to mirror how propgcc did it on P1.

    What I am now having trouble with is starting a cog that's just another C function, i.e:
    #include <propeller.h>
    
    #include <stdio.h>
    #include <stdint.h>
    
    #define PIN 56
    #define PIN2 57
    
    extern uint32_t _cog_led_start[];
    
    void led_start() {
        _dirh(PIN2);
        _outh(PIN2);
    
        while(1);
    }
    
    void main() {
    
        _cognew(_cog_led_start, PIN);
        _cognew(led_start, 0);
    
        while(1);
    }
    

    But pin 57 does not go high. Does riscvp2 support starting other cogs that aren't native code (similar to starting other cmm cogs in propgcc)?
  • Unfortunately only COG 0 can run C code (riscv code) in riscvp2. Making the JIT compiler re-entrant so that it can support multiple COGs is something that's been on my to-do list for a while, but I haven't had time to get to it.

    BTW there was a conflict between _clkset and the FPU code, which I've just pushed a fix for, so you may want to grab a newer copy.
  • ersmith wrote: »
    Unfortunately only COG 0 can run C code (riscv code) in riscvp2. Making the JIT compiler re-entrant so that it can support multiple COGs is something that's been on my to-do list for a while, but I haven't had time to get to it.

    Okay, so sounds like the only options for multiple cogs is to compile binaries with fastspin? and I'm assuming that it will need to fit into the 496 longs of cog memory?
    ersmith wrote: »
    BTW there was a conflict between _clkset and the FPU code, which I've just pushed a fix for, so you may want to grab a newer copy.

    Yeah was just testing the clkset fix and noticed it wasn't working, and then saw a new commit. Works now, thanks!
  • n_ermosh wrote: »
    ersmith wrote: »
    Unfortunately only COG 0 can run C code (riscv code) in riscvp2. Making the JIT compiler re-entrant so that it can support multiple COGs is something that's been on my to-do list for a while, but I haven't had time to get to it.

    Okay, so sounds like the only options for multiple cogs is to compile binaries with fastspin? and I'm assuming that it will need to fit into the 496 longs of cog memory?

    You do have to compile with fastspin (or PNut, or spin2cpp), but the code doesn't have to fit in cog memory. It's quite OK to do hubexec or to load code into LUT. The tricky part is finding the addresses of the code in hub memory. You'll either have to make everything position independent, or else use spin2cpp to convert some PASM to hex bytes; in that case spin2cpp also produces a relocation table for the PASM code and a constructor to perform the relocation.
Sign In or Register to comment.