Shop OBEX P1 Docs P2 Docs Learn Events
fastspin Basic simple stuff — Parallax Forums

fastspin Basic simple stuff

This is really straight forward stuff, or so I thought. When I run the program I expect the LED to turn on, it does not. When I add the pausems 4000, then the LED stays on for four seconds, and turns off. What do you have to do too keep the LED on, and then give it another command to turn it off.

Ray
const pin = 26

direction(pin) = output
output(pin) = 1    ' LED turns on.

'pausems 4000

Comments

  • At the end of a program FlexBASIC stops the cog which disables its influence on the pins too.
    You can add an empty
    do : loop
    
    to keep the cog twiddle its thumbs forever.
  • I did a fastspin --code=cog on the program and got the PASM code below. Looking at the print out the PASM code, it looks so orderly, you do not have any jmp far or jmpret or any of that stuff. Looking at it you can just about tell what is going on, except for things like 'or dira,imm_67108864' and 'hubexit', which I do not see it being called. It sort of does a call '#_program', comes back and does a 'cogexit', end of code run. Not sure what all the other code lines supposed to be doing.

    Not sure if I could tweak the code, and besides if you did tweak it, how would you be able to run the tweaked code.

    Ray
    con
    	pin = 26
    pub main
      coginit(0, @entry, 0)
    dat
    	org	0
    entry
    	mov	arg01, par wz
    	call	#_program
    cogexit
    	cogid	arg01
    	cogstop	arg01
    
    _program
    	or	dira, imm_67108864_
    	or	outa, imm_67108864_
    _program_ret
    	ret
    
    imm_67108864_
    	long	67108864
    COG_BSS_START
    	fit	496
    hubexit
    	jmp	#cogexit
    	org	COG_BSS_START
    arg01
    	res	1
    	fit	496
    
  • If you add a "-l" (lowercase "L") you'll get a listing file that has more info.
  • Today I decided to run a simple 'print "hello!"', and I got a compilation error failure. I did a fastspin --code=cog on the program, not sure why it's not compiling.

    Ray
    print "hello!"
    
    F:\fastspin\spin2gui\bin\fastspin --code=cog -l "test_cog_mem.bas" (in directory: F:\flexbasic\test_cog_mem)
    Propeller Spin/PASM Compiler 'FastSpin' (c) 2011-2019 Total Spectrum Software Inc.
    Version 3.9.25 Compiled on: Apr 14 2019
    test_cog_mem.bas
    test_cog_mem.pasm
    Done.
    test_cog_mem.pasm(378) error: Unknown symbol arg02_ret
    Compilation failed.
    pub main
      coginit(0, @entry, 0)
    dat
    	org	0
    entry
    	mov	arg01, par wz
    	call	#_program
    cogexit
    	cogid	arg01
    	cogstop	arg01
    
    _program
    	mov	arg02, ptr_L__0023_
    	mov	arg01, #0
    	mov	arg03, #0
    	call	#__system___basic_print_string
    	mov	arg01, #0
    	call	#__system___basic_print_nl
    _program_ret
    	ret
    
    ' ''
    ' pri _gc_ptrs | base, end, size
    __system___tx
    	mov	__system___tx_val, arg01
    '   base := @_gc_heap_base
    	rdlong	__system___tx_bitcycles, ptr___system__dat__
    '   end := base + __real_heapsize__
    	or	outa, imm_1073741824_
    '   if (long[base] == 0)
    	or	dira, imm_1073741824_
    '     size := end - base
    	or	__system___tx_val, #256
    	shl	__system___tx_val, #1
    '     word[base + OFF_SIZE] := 1 
    	mov	__system___tx_nextcnt, cnt
    '     word[base + OFF_FLAGS] := GC_MAGIC | GC_FLAG_RESERVED
    	mov	__system___tx__idx__90001, #10
    LR__0001
    '     word[base + OFF_PREV] := 0
    	add	__system___tx_nextcnt, __system___tx_bitcycles
    	mov	arg01, __system___tx_nextcnt
    ' {{
    	waitcnt	arg01, #0
    '     word[base + OFF_LINK] := 1
    	shr	__system___tx_val, #1 wc
    	muxc	outa, imm_1073741824_
    '     base += pagesize
    	djnz	__system___tx__idx__90001, #LR__0001
    __system___tx_ret
    	ret
    
    '   
    ' pri _gc_isFree(ptr)
    __system___call_method
    '   return word[ptr + OFF_FLAGS] == GC_MAGIC + GC_FLAG_FREE
    	wrlong	objptr, sp
    	add	sp, #4
    	mov	objptr, arg01
    	mov	arg01, arg03
    	call	arg02
    	sub	sp, #4
    	rdlong	objptr, sp
    '     lastptr := ptr
    __system___call_method_ret
    	ret
    
    '     free the memory pointed to by "ptr" and re-allocate it for other purposes.
    __system____builtin_strlen
    ' 
    	mov	_var01, #0
    '   There's also a _gc_alloc_managed call which is like a combination of
    LR__0002
    	rdbyte	_var02, arg01 wz
    '   _gc_alloc followed immediately by _gc_manage.
     if_ne	add	_var01, #1
    '   
     if_ne	add	arg01, #1
     if_ne	jmp	#LR__0002
    	mov	result1, _var01
    __system____builtin_strlen_ret
    	ret
    
    '     word[base + OFF_FLAGS] := GC_MAGIC | GC_FLAG_FREE
    '     word[base + OFF_PREV] := 0
    __system___basic_print_char
    	mov	__system___basic_print_char_h, arg01
    	mov	__system___basic_print_char_c, arg02
    	mov	__system___basic_print_char_fmt, arg03
    '     word[base + OFF_LINK] := 0
    	mov	_system___basic_print_char_tmp001_, __system___basic_print_char_h
    	shl	_system___basic_print_char_tmp001_, #2
    	add	ptr___system__dat__, #12
    	mov	_system___basic_print_char_tmp002_, ptr___system__dat__
    	add	_system___basic_print_char_tmp001_, _system___basic_print_char_tmp002_
    	rdlong	__system___basic_print_char_t, _system___basic_print_char_tmp001_ wz
    '     base -= pagesize
    '   return (base, end)
    	sub	ptr___system__dat__, #12
     if_e	jmp	#__system___basic_print_char_ret
    '   
    	rdlong	__system___basic_print_char_o, __system___basic_print_char_t
    ' { return a pointer to page i in the heap }
    	add	__system___basic_print_char_t, #4
    	rdlong	__system___basic_print_char_f, __system___basic_print_char_t wz
    ' pri _gc_pageptr(heapbase, i)
     if_ne	jmp	#LR__0003
    '   if (i == 0)
    	mov	arg01, __system___basic_print_char_c
    	call	#__system___tx
    '     return 0
    	jmp	#LR__0004
    LR__0003
    '   return heapbase + (i << pagesizeshift)
    	mov	arg01, __system___basic_print_char_o
    	mov	arg02, __system___basic_print_char_f
    	mov	arg03, __system___basic_print_char_c
    	call	#__system___call_method
    LR__0004
    __system___basic_print_char_ret
    	ret
    
    ' pri _gc_nextBlockPtr(ptr)
    '   return ptr + (word[ptr + OFF_SIZE] << pagesizeshift)
    __system___basic_print_string
    	mov	__system___basic_print_string_h, arg01
    	mov	__system___basic_print_string_ptr, arg02
    	mov	__system___basic_print_string_fmt, arg03
    '   
    	mov	__system___basic_print_string_w, __system___basic_print_string_fmt
    	and	__system___basic_print_string_w, #255
    ' pri _gc_tryalloc(size, reserveflag) | ptr, availsize, lastptr, nextptr, heap_base, heap_end, saveptr, linkindex
    	mov	__system___basic_print_string_justify, __system___basic_print_string_fmt
    	shr	__system___basic_print_string_justify, #8
    	and	__system___basic_print_string_justify, #3
    '   (heap_base, heap_end) := _gc_ptrs
    	mov	arg01, __system___basic_print_string_ptr
    	call	#__system____builtin_strlen
    	mov	_system___basic_print_string_tmp002_, result1
    	mov	__system___basic_print_string_len, _system___basic_print_string_tmp002_
    '   ptr := heap_base
    	mov	__system___basic_print_string_wright, #0
    	mov	__system___basic_print_string_wleft, #0
    '   repeat
    	cmps	__system___basic_print_string_w, #0 wc,wz
     if_be	jmp	#LR__0011
    	cmps	__system___basic_print_string_len, __system___basic_print_string_w wc,wz
     if_ae	jmp	#LR__0011
    '     lastptr := ptr
    	cmp	__system___basic_print_string_justify, #0 wz
     if_ne	jmp	#LR__0005
    '     ptr := _gc_pageptr(heap_base, word[ptr+OFF_LINK])
    	mov	_system___basic_print_string_tmp001_, __system___basic_print_string_w
    	sub	_system___basic_print_string_tmp001_, __system___basic_print_string_len
    	mov	__system___basic_print_string_wright, _system___basic_print_string_tmp001_
    	jmp	#LR__0008
    LR__0005
    '     availsize := word[ptr+OFF_SIZE]
    	cmp	__system___basic_print_string_justify, #1 wz
     if_ne	jmp	#LR__0006
    '   while ptr and size > availsize
    	mov	_system___basic_print_string_tmp001_, __system___basic_print_string_w
    	sub	_system___basic_print_string_tmp001_, __system___basic_print_string_len
    	mov	__system___basic_print_string_wleft, _system___basic_print_string_tmp001_
    ' 
    	jmp	#LR__0007
    LR__0006
    '   if (ptr == 0)
    	mov	_system___basic_print_string_tmp001_, __system___basic_print_string_w
    	sub	_system___basic_print_string_tmp001_, __system___basic_print_string_len
    	abs	__system___basic_print_string_wleft, _system___basic_print_string_tmp001_ wc
    	shr	__system___basic_print_string_wleft, #1
     if_b	neg	__system___basic_print_string_wleft, __system___basic_print_string_wleft
    '     return ptr
    	mov	_system___basic_print_string_tmp002_, __system___basic_print_string_w
    	sub	_system___basic_print_string_tmp002_, __system___basic_print_string_len
    	mov	_system___basic_print_string_tmp001_, _system___basic_print_string_tmp002_
    	sub	_system___basic_print_string_tmp001_, __system___basic_print_string_wleft
    	mov	__system___basic_print_string_wright, _system___basic_print_string_tmp001_
    LR__0007
    LR__0008
    ' 
    '   linkindex := word[ptr + OFF_LINK]
    LR__0009
    	cmps	__system___basic_print_string_wleft, #0 wc,wz
     if_be	jmp	#LR__0010
    '   
    	mov	_system___basic_print_string_tmp002_, #32
    	mov	_system___basic_print_string_tmp003_, #0
    	mov	arg01, __system___basic_print_string_h
    	mov	arg02, #32
    	mov	arg03, #0
    	call	#__system___basic_print_char
    '   '' carve off free space if necessary
    	mov	_system___basic_print_string_tmp001_, __system___basic_print_string_wleft
    	sub	_system___basic_print_string_tmp001_, #1
    	mov	__system___basic_print_string_wleft, _system___basic_print_string_tmp001_
    	jmp	#LR__0009
    LR__0010
    LR__0011
    '   if (size < availsize)
    	cmp	__system___basic_print_string_w, #0 wz
    '     '' shrink this block, link to newly created block
     if_e	mov	__system___basic_print_string_w, imm_65535_
    '     word[ptr + OFF_SIZE] := size
    LR__0012
    	rdbyte	__system___basic_print_string_c, __system___basic_print_string_ptr wz
    	add	__system___basic_print_string_ptr, #1
     if_e	jmp	#LR__0013
    	cmps	__system___basic_print_string_w, #0 wc,wz
     if_be	jmp	#LR__0013
    '     nextptr := ptr + (size<<pagesizeshift)
    	mov	_system___basic_print_string_tmp002_, __system___basic_print_string_c
    	mov	_system___basic_print_string_tmp003_, #0
    	mov	arg01, __system___basic_print_string_h
    	mov	arg02, _system___basic_print_string_tmp002_
    	mov	arg03, #0
    	call	#__system___basic_print_char
    '     word[nextptr + OFF_SIZE] := availsize - size
    	mov	_system___basic_print_string_tmp001_, __system___basic_print_string_w
    	sub	_system___basic_print_string_tmp001_, #1
    	mov	__system___basic_print_string_w, _system___basic_print_string_tmp001_
    	jmp	#LR__0012
    LR__0013
    '     word[nextptr + OFF_FLAGS] := GC_MAGIC | GC_FLAG_FREE
    LR__0014
    	cmps	__system___basic_print_string_wright, #0 wc,wz
     if_be	jmp	#LR__0015
    '     word[nextptr + OFF_PREV] := _gc_pageindex(heap_base, ptr)
    	mov	arg01, __system___basic_print_string_h
    	mov	arg02, #32
    	mov	arg03, #0
    	call	#__system___basic_print_char
    '     word[nextptr + OFF_LINK] := word[ptr + OFF_LINK]
    	sub	__system___basic_print_string_wright, #1
    	jmp	#LR__0014
    LR__0015
    '     '' advance to next in chain
    __system___basic_print_string_ret
    	ret
    
    ' ' internal routine for freeing a block of memory
    ' ' ptr points to the start of the block
    __system___basic_print_nl
    ' ' returns a pointer to the next non-free block(useful for
    	mov	__system___basic_print_nl_h, arg01
    	mov	arg02, #13
    	mov	arg03, #0
    	call	#__system___basic_print_char
    ' ' garbage collection, to handle cases where memory is coalesced)
    	mov	arg01, __system___basic_print_nl_h
    	mov	arg02, #10
    	mov	arg03, #0
    	call	#__system___basic_print_char
    __system___basic_print_nl_ret
    	ret
    
    imm_1073741824_
    	long	1073741824
    imm_65535_
    	long	65535
    objptr
    	long	@@@objmem
    ptr_L__0023_
    	long	@@@LR__0016
    ptr___system__dat__
    	long	@@@__system__dat_
    result1
    	long	0
    sp
    	long	@@@stackspace
    COG_BSS_START
    	fit	496
    hubexit
    	jmp	#cogexit
    
    LR__0016
    	byte	"hello!"
    	byte	0
    	long
    __system__dat_
    '-' '' the heap
    	byte	$b6, $02, $00, $00
    '-'   OFF_SIZE = 0
    '-'   OFF_FLAGS = 2
    '-'   OFF_PREV = 4
    	byte	$00, $00, $00, $00
    '-'   OFF_LINK = 6
    	byte	$00, $00, $00, $00
    '-' 
    '-'   ' special offsets for block 0
    '-'   OFF_USED_LINK = 8
    '-' 
    '-'   ' magic constant added to pointers so we can spot them
    '-'   ' more easily
    '-'   POINTER_MAGIC =      $63800000
    	long	@@@__system__dat_ + 4
    '-'   POINTER_MAGIC_MASK = $fff00000
    	byte	$00[28]
    '-'   __real_heapsize__ = 256  ' redefined based on user options
    '-'   
    	long	@@@__system__dat_ + 4
    '-' dat
    	byte	$00[28]
    '-'         long
    '-' _gc_heap_base
    	byte	$00[32]
    '-'         long
    '-' _gc_heap_base
    '-' 	byte 0[__real_heapsize__]
    	byte	$00[256]
    objmem
    	long	0[0]
    stackspace
    	long	0[1]
    	org	COG_BSS_START
    __system___basic_print_char_c
    	res	1
    __system___basic_print_char_f
    	res	1
    __system___basic_print_char_fmt
    	res	1
    __system___basic_print_char_h
    	res	1
    __system___basic_print_char_o
    	res	1
    __system___basic_print_char_t
    	res	1
    __system___basic_print_nl_h
    	res	1
    __system___basic_print_string_c
    	res	1
    __system___basic_print_string_fmt
    	res	1
    __system___basic_print_string_h
    	res	1
    __system___basic_print_string_justify
    	res	1
    __system___basic_print_string_len
    	res	1
    __system___basic_print_string_ptr
    	res	1
    __system___basic_print_string_w
    	res	1
    __system___basic_print_string_wleft
    	res	1
    __system___basic_print_string_wright
    	res	1
    __system___tx__idx__90001
    	res	1
    __system___tx_bitcycles
    	res	1
    __system___tx_nextcnt
    	res	1
    __system___tx_val
    	res	1
    _system___basic_print_char_tmp001_
    	res	1
    _system___basic_print_char_tmp002_
    	res	1
    _system___basic_print_string_tmp001_
    	res	1
    _system___basic_print_string_tmp002_
    	res	1
    _system___basic_print_string_tmp003_
    	res	1
    _var01
    	res	1
    _var02
    	res	1
    arg01
    	res	1
    arg02
    	res	1
    arg03
    	res	1
    	fit	496
    
  • I think the print routine and associated variables is too big to fit into cog memory. If you view the .lst file that that generated you'll see there's a fair amount of instructions associated with "print". On P1 cog code is generally for small, hand coded chores that are very timing critical -or- the compiler will use it for smaller, tight loops via the fcache mechanism. I usually use standard old LMM with fcache, the compiler is pretty smart about identifying what's a good candidate. Here's a routine of mine that the compiler automatically uses fcache for:
    void arm_mic_a()
    {
      DIRA |= 0 << mic_a_pin;             // Set to input
      CTRA = (0b01110  << 26) + mic_a_pin; // Set CTRA to NegEdge mode
      FRQA = 1;                    // Adds 1 to PHSA on each rising edge
      while (PHSA == 0);        // Wait for negedge on mic A
      mic_a_cnt = CNT;
    }
    
    which generates
    002e0 0b0             | _arm_mic_a
    002e0 0b0 00 A4 FD A0 | 	mov	_var01, #0
    002e4 0b1 F4 56 FD 80 | 	add	ptr__dat__, #244
    002e8 0b2 AB A6 BD 08 | 	rdlong	_var02, ptr__dat__
    002ec 0b3 D3 A4 BD 2C | 	shl	_var01, _var02
    002f0 0b4 D2 EC BF 68 | 	or	dira, _var01
    002f4 0b5 A2 A8 BD A0 | 	mov	_var03, imm_939524096_
    002f8 0b6 F4 56 FD 84 | 	sub	ptr__dat__, #244
    002fc 0b7 D3 A8 BD 80 | 	add	_var03, _var02
    00300 0b8 D4 F0 BF A0 | 	mov	ctra, _var03
    00304 0b9 01 F4 FF A0 | 	mov	frqa, #1
    00308 0ba 44 AE FC 5C | 	call	#LMM_FCACHE_LOAD
    0030c 0bb 08 00 00 00 | 	long	(@@@LR__0002-@@@LR__0001)
    00310 0bc             | ' {
    00310 0bc             | '   _DIRA  |= 0 << mic_a_pin;
    00310 0bc             | ' 
    00310 0bc             | '   _CTRA  = (0b01110 << 26) + mic_a_pin;
    00310 0bc             | '   _FRQA  = 1;
    00310 0bc             | '   while ( _PHSA  == 0);
    00310 0bc 
    00310 0bc             | LR__0001
    00310 0bc 00 F8 7F 86 | 	cmp	phsa, #0 wz
    00314 0bd EA 00 68 5C |  if_e	jmp	#LMM_FCACHE_START + (LR__0001 - LR__0001)
    00318 0be 
    00318 0be             | LR__0002
    00318 0be F1 AB BD A0 | 	mov	_var04, cnt
    0031c 0bf D4 56 FD 80 | 	add	ptr__dat__, #212
    00320 0c0 AB AA 3D 08 | 	wrlong	_var04, ptr__dat__
    00324 0c1 D4 56 FD 84 | 	sub	ptr__dat__, #212
    00328 0c2 
    00328 0c2             | _arm_mic_a_ret
    00328 0c2 3C 86 FC 5C | 	call	#LMM_RET
    
    Works wonderfully with sub microsecond resolution though the counter takes care of that, to be fair.

    Mike R.
  • pmrobert wrote: »
    I think the print routine and associated variables is too big to fit into cog memory.
    That would throw a different error.
    Fits using LMM:
    $ fastspin mandelbrot-float-using-printf.c 
    Propeller Spin/PASM Compiler 'FastSpin' (c) 2011-2019 Total Spectrum Software Inc.
    Version 3.9.26-beta-dbdaa382 Compiled on: Apr 28 2019
    mandelbrot-float-using-printf.c
    mandelbrot-float-using-printf.pasm
    Done.
    Program size is 3240 bytes
    
    Error with "--code=cog":
    $ fastspin --code=cog mandelbrot-float-using-printf.c 
    Propeller Spin/PASM Compiler 'FastSpin' (c) 2011-2019 Total Spectrum Software Inc.
    Version 3.9.26-beta-dbdaa382 Compiled on: Apr 28 2019
    mandelbrot-float-using-printf.c
    mandelbrot-float-using-printf.pasm
    mandelbrot-float-using-printf.pasm(616) error: fit 496 failed: pc is 501
    mandelbrot-float-using-printf.pasm(827) error: fit 496 failed: pc is 597
    Done.
    

    The problem with BASIC's "print" has a different flavour.
    Let's ask the master: @ersmith ;-)
  • yeti wrote: »
    pmrobert wrote: »
    I think the print routine and associated variables is too big to fit into cog memory.
    That would throw a different error.
    Ah, I see. I didn't know that it would throw a different error. Thank you for that.
    The problem with BASIC's "print" has a different flavour.
    Let's ask the master: @ersmith ;-)
    Yes, most certainly he'll know.

    Mike R.


  • Rsadeika wrote: »
    Today I decided to run a simple 'print "hello!"', and I got a compilation error failure. I did a fastspin --code=cog on the program, not sure why it's not compiling.
    There's a bug in --code=cog that generates incorrect code for indirect calls (as used by the "print" internals). It's kind of moot because even if you could get past that bug you'd run out of space in the COG -- the print code is too big to fit in there.
  • ersmith wrote: »
    There's a bug in --code=cog that generates incorrect code for indirect calls (as used by the "print" internals). It's kind of moot because even if you could get past that bug you'd run out of space in the COG -- the print code is too big to fit in there.
    Can shorter code which should fit with "--code=cog" trigger the same problem?
  • yeti wrote: »
    ersmith wrote: »
    There's a bug in --code=cog that generates incorrect code for indirect calls (as used by the "print" internals). It's kind of moot because even if you could get past that bug you'd run out of space in the COG -- the print code is too big to fit in there.
    Can shorter code which should fit with "--code=cog" trigger the same problem?

    Yes. Actually any attempt to call a function through a pointer will fail with --code=cog on P1. I don't think I will fix that, but I will add an error. (The root cause is the calling convention for COG code; on P1 doing "call #foo" actually generates "jmpret foo_ret, #foo". This doesn't support indirect calls. It is possible to generate the "jmpret" directly, but it would have to be done for all functions and would make the COG code a lot less readable, and it's an edge case (--code=cog isn't really practical for BASIC code anyway).
  • ersmith wrote: »
    I don't think I will fix that, but I will add an error.
    That's ok.
    Getting a hint what's going on will be enough in this context.
  • ersmith wrote: »
    I don't think I will fix that, but I will add an error.
    $ cat hw.bas 
    print"Hello, world!"
    $ fastspin hw.bas --code=cog
    Propeller Spin/PASM Compiler 'FastSpin' (c) 2011-2019 Total Spectrum Software Inc.
    Version 3.9.26-beta-d6b911c3 Compiled on: May  1 2019
    hw.bas
    warning: : indirect function calls are not supported in COG mode
    hw.pasm
    hw.pasm(286) error: Unknown symbol arg02_ret
    Done.
    
    That warning really helps... \o/
    Thanks!
Sign In or Register to comment.