Hi,
I'm new here and just want to say hello!
I live in Germany and have quite some experience with the Atmel AVR hard- and software. The Parallax chip is very interesting, I'm beginning to build my IDE around PropBasic and Edit+. It works, but I would like to have the same behaviour than the BST IDE, the ouput pane should just show the compiler errors and jump to the offending line by double clicking it. What compile switch and/or output pattern do I need to achieve this?
Problem solved with a batch file:
@echo off
PropBasic-bst %1.pbas /q
more %1.err
and the regular expressions for the output
in edit+:
Hello,
after installing the new PropBasic-compiler, I suddenly had problems with compiling a PropBasic-program. The time for the compilation went from a few seconds to several minutes. I tested a couple other programs from the PBAS-DEMO and there was the same problem with the program DS18B20.pbas. Meanwhile, I was able to identify the problem. The new compiler has problems with multiplication. The compilation is slow but the result is correct and the program runs without error. It may be that it is my development environment: Asus 1005h netbook with Ubuntu 10.04 and BST 0.19.3/PropBasic 00.01.14-79.
Excerpt from DS18B20.pbas (problem in line 4) :
temp = value / 16 ' Get whole value
tempWhole = STR temp, 4, 7 ' Signed leading spaces, no zero terminator
temp = value AND 15 ' Get fractional value
temp = temp * 625 ' 10000 / 16
tempFrac = STR temp, 4, 4 ' Unsigned leading zeros, no zero terminator
In my own program, problems occur in line 3 and 5.
The problematic lines marked with comment tags and the compilation runs in normal speed.
The time delay occurs at the beginning of the compilation before BST displays a message.
PS.:
So now I have used an additional variable and assigns it a value of 100 and then I used the variable in the equations. Now the compilation works as fast as usual.
.....
laddr VAR LONG
lperc VAR LONG
tmp1 VAR LONG
tmp2 VAR LONG
tmp3 VAR LONG
tmp4 VAR LONG = 100
laddr = GETADDR ledpercent
Hi Bean,
I've tried to reproduce one of the first spin programs out of the "Programming & customizing the multicore propeller...".
It uses 4 cogs total, blinks leds in parallel with different timing.
I'm wondering if this is the right way to do it in PropBasic (best practice?)
Why are the pause statement necessary after the COGSTART statement? If I omit them only the last cog is started.
Also the COGSTOP statement is necessary, otherwise the cogs will loop forever?
Many thanks for your help, Fried
' ----------------------------------------------------------------------
' File...... Multi_Flash_Led.pbas
' Author.... fgvissel 21.08.2011
' ----------------------------------------------------------------------
' ----- Device Settings ------------------------------------------------
DEVICE P8X32A, XTAL1, PLL16X
XIN 5_000_000
' ----- Conditional Compilation Symbols --------------------------------
' ----- Constants ------------------------------------------------------
Rt CON 3 'For the I/O Pins
Gn CON 4
Ge CON 5
' ----- IO Pins --------------------------------------------------------
' ----- Shared (HUB) Variables (Byte, Word, Long) ----------------------
Hubled HUB LONG
HubDur HUB LONG
HubCnt HUB LONG
' ----- User Data (DATA, WDATA, LDATA, FILE) ---------------------------
' ----- TASK Definitions -----------------------------------------------
Flash_Task TASK
' ----- Local Variables (LONG only) ------------------------------------
' ----- SUB and FUNC Definitions ---------------------------------------
' ----------------------------------------------------------------------
PROGRAM Start
Start:
' setup code
Main:
WRLONG HubLed, Rt 'Blink Leds simultanously
WRLONG HubDur, 30
WRLONG HubCnt, 10
COGSTART Flash_Task
Pause 1 ' <------------- Won't work without this pause, WHY ??????????
wrlong hubled, Gn
wrlong hubdur, 15
wrlong hubcnt, 20
cogstart flash_task
pause 1 ' <------------- Won't work without this pause, WHY ??????????
wrlong hubled, Ge
wrlong hubdur, 7
wrlong hubcnt, 30
cogstart flash_task
END
' ----- SUB and FUNC Code ----------------------------------------------
' ----- TASK Code ------------------------------------------------------
TASK Flash_Task
Flash_LED SUB 3
LocLed VAR LONG
LocDur VAR LONG
LocCnt VAR LONG
RDLONG HubLed,LocLed
RDLONG HubDur,LocDur
RDLONG HubCnt,LocCnt
Flash_Led LocLed, LocDur, LocCnt
COGSTOP '<--------------- Without this, Cogs loop forever ???????????????????????
SUB Flash_LED ' Flash led on Pin for Duration(msec)
' a total of Count times
time VAR LONG
duration VAR LONG
wcnt VAR LONG
loopcnt VAR LONG
time = cnt 'Get time for sync
RDLONG 0,duration
duration = duration / 100 'duration = 1msec
duration = duration * __param2 'duration = __param2 msecs
loopcnt = __param3 * 2 'Blink __param3 times
wcnt = time + duration
OUTPUT __param1 'Set Pin to Output
DO
WAITCNT wcnt, duration
TOGGLE __param1
LOOP loopcnt
INPUT __param1 'Free Pin for other Tasks, Cogs
ENDSUB
ENDTASK
' ----------------------------------------------------------------------
The cogstart only initiates the start of a cog. It takes about 100us for the task's code to load into the cog and for the cog to actually start running. All this takes place while the original cog continues to run (in parallel). The PAUSE allows the new cog to start running.
Yes, you need something to either stop the task's cog (cogstop) or some kind of infinite loop for the cog to execute. There's no way to return from a cogstart and there's nothing automatically compiled that will stop the cog at the end of the task's code.
Thx very much, Mike.
So when I want to start Taks in different cogs in a deterministic way I need to sync them at the beginning of the task, with some kind of semaphore?
Init them, go into a waiting loop and then run if a pin or a Hub VAR assumes a certain state?
Does a task in a cog lives there permanently or ist it reloaded with every cogstart?
Regards, Fried
There are several ways to sync cogs. The video drivers work by taking the system clock value (CNT) and adding some amount of time to it that's large enough that all the cogs will finish their initialization within the time interval, then all of the cogs use WAITCNT to wait for that time to occur. When the WAITCNTs finish, all of the cogs continue executing at the same time and move forward in lockstep..
You can use semaphores (LOCKxxx) for synchronization if you want. For this kind of simple semaphore use, you can just use a hub byte as you mentioned.
The cogstart statement uses the COGINIT instruction to start the task and sets the bit that causes the Propeller to use the next available (stopped) cog for the task. The task will continue to run in that cog until it stops itself. If you do another cogstart, you'll start up another cog with the same code. Eventually, you'll run out of cogs. You can issue a COGINIT instruction that reuses a specific cog. I'm not sure how to do that in PropBasic without using assembly language though. That form of the COGINIT instruction is not commonly used. It's too easy to get the cog number wrong and try to reuse the wrong cog.
I'm a little confused about the operation of the clock. My application uses an external oscillator (VCXO), and I'm getting some confusing behavior. I was using a 40 MHz VCXO, and this worked fine:
DEVICE P8X32A, XINPUT
XIN 40_000_000
I decided the program could benefit from a bit more speed, but I couldn't find a cheap 80 MHz VCXO. I did find a 4.096 MHz VCXO so I decided to use it and let the PLL multiply it up to 65.536 MHz. So, I tried the same code with the appropriate frequency change, but no dice. Here's a little test program to illustrate:
'DEVICE P8X32A, XINPUT, PLL16X
'XIN 4_096_000
DEVICE P8X32A, XTAL1, PLL16X
XIN 4_096_000
LED PIN 9 OUTPUT
PROGRAM Start
Start:
TOGGLE LED
PAUSE 500
GOTO Start
As it is, the code works fine and the LED toggles at the correct 1 Hz rate. If I use the commented declaration, which is the one I'd expect to use, the PLL doesn't work and the code runs at 1/16 the expected speed. I can't find anything that suggests that the PLL only works with a crystal but not an oscillator, and in fact it does work with the VCXO, I just have to tell the compiler there's a crystal there (The Xo pin is open). Am I misunderstanding how this is supposed to work?
I can't find anything that suggests that the PLL only works with a crystal but not an oscillator, and in fact it does work with the VCXO, I just have to tell the compiler there's a crystal there (The Xo pin is open). Am I misunderstanding how this is supposed to work?
Looks like bst doesn't handle/compile XINPUT|PLL16X as expected ($67), it simply ignores the PLL part ($22). As a quick fix I'd suggest saving the resulting SPIN file and compile it with the proptool.
I looked at the assembler output thinking there might be an issue, but was having trouble making sense out of the _clkmode constant. I obviously need to spend more time in the Prop manual.
Hi Pascal,
I have used LDATA and it was OK. I have to admit with numbers only up to 6999. Perhaps the problem is in the code nearby?
Best regards and good luck((from Esslingen))
Christof
Version 00.01.13 Optimized: WRLONG, WRWORD, WRBYTE (don't reload short constants)
Added: "STACK value" to change stack size (defaults to 16) (4 to 255 allowed)
NOTE: STACK only affects LMM code
May I ask how STACK affects LMM code ? What is happening in "laymans terms" ?
Sorry, but I am struggling to get my head around the matter!
To also mention why I ask, should it be relevant... I have a 16Kb buffer which I populate with data, and verify it is correct, but then later in the program try to read it back and it's all gone to zeros. I have not accessed that HUB buffer since, but perhaps due to stack settings with the LMM it's getting overwritten? Just a guess as I scratch around for ideas!
Maxwin,
The STACK in LMM is the depth of the call stack.
When using LMM the compiler uses a call stack to store the return address for calls. This is faster than modifying the return program location (since the return program location is stored in the HUB in LMM).
The stack is in COG RAM, it should have no effect on HUB RAM at all.
about the code error, I will continue to try and solve it and post later. In the other thread you mentioned a call for other things to add to the next revision. maybe this is something to wait for... I will try to solve it a quickly as possible.
Big thank you as always - especially for keeping PropBasic alive when the incentive might wear thin at times.
The stack in PropBasic is not the same as the stack in spin. In spin the stack is used for a lot of data storage. In PropBasic the stack is used ONLY for return addresses.
Unless you are using recursion the default STACK will be fine. If you are using recursion (only possible in LMM) then the stack must be at least as large as the deepest level of recursion possible.
By recursion in this situation, you mean calling a SUB or FUNC from another SUB or FUNC, or at least multiple nested calls.. So if I call 4 subs deep from the main code, then I need a stack of 4...
And is that relevant at the moment they are called, or for the entire compiled code.
So if I have 2 sub routines, which each call another sub, which then call another sub.
... I think that means I have 2 sub routines each requiring stack of 3.. But they are called one after another, not at the same time. So would I need stack of 3 or 6 in this case ? (If I have the explanation right?!)
Right, you only need be concerned with the deepest possible nesting in the whole program.
You could have 1,000 different calls that nest 3 deep, and one that nests 5 deep and you would require a stack of only 5 for the whole program.
P.S. Recursion where when a SUB or FUNC calls itself. Without local variables this is rarely done in PropBasic.
just to tidy up the end of the topic... would the compiler throw an error if the STACK was set too low ? Or otherwise, how could the problem of too small a stack be recognised (I mean before total system failure!!) ?
ah, just tried to compile with stack set lower than 4, and compiler throws an error... Is that a hard coded minimum, or does that mean "my code" needs a stack bigger than 4? in that case, I answered myself!!
Bean, back to the previous problem if I may seek your advice...
... I have a 16Kb buffer which I populate with data, and verify it is correct, but then later in the program try to read it back and it's all gone to zeros...
I tried a much smaller buffer size (200 bytes) and it keeps the data. I tried randomly larger sizes, but above 200 bytes it seems to fail, so I was thinking it might be a hub space issue. But if I set the buffer size to a crazy high value, then the compiler fails and tells me to keep within 32k. So it would not seem logical that I have a problem with an oversized buffer as the compiler would catch that?...
..hmm,,.,. Is it possible that I recall some old recommendations about the importance of the order in which HUB (and perhaps even local) variables/constants are declared? Perhaps concerning size or variable type order? I'm using (LOADing) 2 or 3 libraries and a couple of tasks too, which have there own CON, VAR, HUB and PIN deifinitions. Could that be an issue- should those lib/task variables/etc.. be defined in the main cog to ensure they are compiled to the right place in the .spin file?
Something rings a small bell, but the dust is too thick on that part of my mind...
Info: BST reported data: Program=5763 Longs, Stack/Free=2425 Longs (I'm coding/compiling with ViewPort, but that doesn't report program size AFAIK)
I've got some boards on the way soon for a touchscreen and the memory access is going to be fairly fast - I wonder if propbasic could run on this in XMM mode?
Let's take this
DEVICE P8X32A, XTAL1, PLL16X
XIN 5_000_000
PROGRAM Start LMM
A VAR __param1
Start:
FOR A = 1 TO 3
NEXT
Goto Start
and it compiles to this
'{$BST PATH C:\Propeller\propbasic}
'' *** COMPILED WITH PropBasic VERSION 00.01.14 July 26, 2011 ***
CON 'DEVICE P8X32A, XTAL1, PLL16X
_ClkMode = XTAL1 + PLL16X
_XInFreq = 5000000 'XIN 5_000_000
PUB __Program 'PROGRAM Start LMM
__OFFSET := @__Init
CogInit(0, @_LMM_Entry, @__DATASTART)
DAT
org 0
__Init
__RAM
mov dira,__InitDirA
mov outa,__InitOutA
rdlong __PC,__PC
long @@@Start
' A VAR __param1 'A VAR __param1
Start 'Start:
mov A,#1 'FOR A = 1 TO 3
__FOR_A_1
adds A,#1 'NEXT
cmps A,#3 WZ, WC
IF_BE rdlong __PC,__PC
long @@@__FOR_A_1
__NEXT_A_1
rdlong __PC,__PC 'Goto Start
long @@@Start
DAT
'-------------------------------------------------------------------------------------------
'LMM Execution code
' -------------------------------------------------------------------------------------------
ORG 0
_LMM_Entry
mov __PC,__OFFSET
_LMM_LOOP
rdlong __INSTR1,__PC
add __PC,#4
__INSTR1
nop ' Placeholder for LMM instruction
rdlong __INSTR2,__PC
add __PC,#4
__INSTR2
nop ' Placeholder for LMM instruction
rdlong __INSTR3,__PC
add __PC,#4
__INSTR3
nop ' Placeholder for LMM instruction
rdlong __INSTR4,__PC
add __PC,#4
__INSTR4
nop ' Placeholder for LMM instruction
jmp #_LMM_LOOP
_LMM_JUMP
rdlong __PC,__PC
jmp #_LMM_LOOP
_LMM_CALL
movd $+2,__STACKPTR
add __STACKPTR,#1
mov 0-0,__PC
rdlong __PC,__PC
jmp #_LMM_LOOP
_LMM_RET
sub __STACKPTR,#1
movs $+2,__STACKPTR
mov __PC,#4
add __PC,0-0
jmp #_LMM_LOOP
_LMM_MOVS
rdlong __MOVS,__PC
movs __MOVS,__INDEX
add __PC,#4
__MOVS
nop ' Placeholder for LMM instruction
jmp #_LMM_LOOP
_LMM_MOVD
rdlong __MOVD,__PC
movd __MOVD,__INDEX
add __PC,#4
__MOVD
nop ' Placeholder for LMM instruction
jmp #_LMM_LOOP
' Variables for LMM execution code
__INDEX LONG 0 ' Used by MOVS and MOVD
__OFFSET LONG 0-0' Set by spin
__PC LONG 0 ' Program counter
__STACKPTR LONG __STACK ' Stack pointer
__STACK LONG 0[16] ' Return stack
'**********************************************************************
__InitDirA LONG %00000000_00000000_00000000_00000000
__InitOutA LONG %00000000_00000000_00000000_00000000
_FREQ LONG 80000000
__remainder
__temp1 RES 1
__temp2 RES 1
__temp3 RES 1
__temp4 RES 1
__temp5 RES 1
A
__param1 RES 1
__param2 RES 1
__param3 RES 1
__param4 RES 1
__paramcnt RES 1
FIT 492
CON
LSBFIRST = 0
MSBFIRST = 1
MSBPRE = 0
LSBPRE = 1
MSBPOST = 2
LSBPOST = 3
DAT
__DATASTART
I think the relevant code is in the LMM load loop
rdlong __INSTR1,__PC
add __PC,#4
for XMM the rdlong is replaced with ?6 lines of code. Two ram chips in parallel so data is two bytes at once.
fetch a word, toggle counter pin, shift left 16 bits, fetch word, logical or with first word, toggle counter pin
I think there might need to be a mask in there somewhere too.
I'm wondering about the time it takes to fetch an instruction vs the time it takes to process that instruction. Would replacing the rdlong with 6 pasm instructions be too much of a performance hit?
Dr_Acula,
I think it would be useful. Just thinking off-the-cuff you would remove the four RDLONG, ADD, NOP sequences with something like:
Assuming the data is on pins 0 thru 15
mov temp,ina
xor outa,counterpin
shl temp,#16
mov __INSTR,ina
and __INSTR,_65535
or __INSTR,temp
xor outa,counterpin
__INSTR nop
This would be 8 times slower than native code. Which is pretty good considering.
How do you change the address to implement GOTOs and such ?
Good to hear. Schematic attached. Ignore the TV/VGA/Keyboard part, and also ignore the 40 pin touchscreen socket.
So there is one 138 decoder chip, five 161 counter chips and two memory chips.
P0-P15 are a 16 bit data bus.
The 161 counters count when propeller pin P16 is toggled.
Load the 161 counters with a new start value by selecting /load low via P25,P26 and P27. The value for this is 001. So to load the counter, P25 high, P26 and P27 low, put the value on prop pins P0-P18, then P25,26,27 all high. Reloading the 161 will be when there is a goto, gosub or a write to a memory location. Most of the time though the program proceeds in a linear fashion so all you are doing is counting.
Memory chip /CS when P25 low, P26 high, P27 low.
Memory chip /RD is P19
Memory chip /WR is P20
If you were reading the chip (ie most of the time it is a read) then P19 stays low.
For your code, counterpin is P16. It counts on the positive edge, so would stay high most of the time, then to count, make it low then high.
Where you xor the pin, does that toggle it or just change its state?
Also, where you read in a number of rdlongs in sequence
I only use four RDLONGs to make it run LMM faster. If you only use 1 RDLONG in the loop you will always miss the hub window.
Since there is no hub window with XMM, you can just have 1 in your loop.
xor changes the state of the pin from "high to low" or from "low to high"
You shouldn't need to adjust __PC because the hardware keeps track of the address. We really don't need to know what it is...
Bean
P.S. I just realized that we need to toggle the counter pin TWICE for each instruction...
__NEXT
xor outa,counterpin ' low
mov temp,ina
xor outa,counterpin ' high (new data bits)
shl temp,#16
mov __INSTR,ina
xor outa,counterpin ' low
and __INSTR,_65535
or __INSTR,temp
xor outa,counterpin ' high (new data bits)
__INSTR
nop
This would run XMM code at 1.8M IPS with a 80Mhz clock...
I'm sure there is probably some tricks to reduce the instructions, but I can't think of any right now...
Oh, you could propbably setup a counter or the video hardware to toggle the counter pin. That would get you down to 7 instructions in the loop or 2.85M IPS.
Comments
Problem solved with a batch file:
@echo off
PropBasic-bst %1.pbas /q
more %1.err
and the regular expressions for the output
in edit+:
(ERROR,+([^,]+),+([0-9]+))
File: None (or Tagged Expression 2)
Line: Tagged Expression 3
Column: None
after installing the new PropBasic-compiler, I suddenly had problems with compiling a PropBasic-program. The time for the compilation went from a few seconds to several minutes. I tested a couple other programs from the PBAS-DEMO and there was the same problem with the program DS18B20.pbas. Meanwhile, I was able to identify the problem. The new compiler has problems with multiplication. The compilation is slow but the result is correct and the program runs without error. It may be that it is my development environment: Asus 1005h netbook with Ubuntu 10.04 and BST 0.19.3/PropBasic 00.01.14-79.
Excerpt from DS18B20.pbas (problem in line 4) : In my own program, problems occur in line 3 and 5. The problematic lines marked with comment tags and the compilation runs in normal speed.
The time delay occurs at the beginning of the compilation before BST displays a message.
PS.:
So now I have used an additional variable and assigns it a value of 100 and then I used the variable in the equations. Now the compilation works as fast as usual.
With kind regards
G
I am also getting a very slow compiler response with version 1.14 on Windows 7. Seems to happen when you multiply a variable with a value.
Regards
Andre
I've tried to reproduce one of the first spin programs out of the "Programming & customizing the multicore propeller...".
It uses 4 cogs total, blinks leds in parallel with different timing.
I'm wondering if this is the right way to do it in PropBasic (best practice?)
Why are the pause statement necessary after the COGSTART statement? If I omit them only the last cog is started.
Also the COGSTOP statement is necessary, otherwise the cogs will loop forever?
Many thanks for your help, Fried
Yes, you need something to either stop the task's cog (cogstop) or some kind of infinite loop for the cog to execute. There's no way to return from a cogstart and there's nothing automatically compiled that will stop the cog at the end of the task's code.
So when I want to start Taks in different cogs in a deterministic way I need to sync them at the beginning of the task, with some kind of semaphore?
Init them, go into a waiting loop and then run if a pin or a Hub VAR assumes a certain state?
Does a task in a cog lives there permanently or ist it reloaded with every cogstart?
Regards, Fried
You can use semaphores (LOCKxxx) for synchronization if you want. For this kind of simple semaphore use, you can just use a hub byte as you mentioned.
The cogstart statement uses the COGINIT instruction to start the task and sets the bit that causes the Propeller to use the next available (stopped) cog for the task. The task will continue to run in that cog until it stops itself. If you do another cogstart, you'll start up another cog with the same code. Eventually, you'll run out of cogs. You can issue a COGINIT instruction that reuses a specific cog. I'm not sure how to do that in PropBasic without using assembly language though. That form of the COGINIT instruction is not commonly used. It's too easy to get the cog number wrong and try to reuse the wrong cog.
I'm a little confused about the operation of the clock. My application uses an external oscillator (VCXO), and I'm getting some confusing behavior. I was using a 40 MHz VCXO, and this worked fine:
DEVICE P8X32A, XINPUT
XIN 40_000_000
I decided the program could benefit from a bit more speed, but I couldn't find a cheap 80 MHz VCXO. I did find a 4.096 MHz VCXO so I decided to use it and let the PLL multiply it up to 65.536 MHz. So, I tried the same code with the appropriate frequency change, but no dice. Here's a little test program to illustrate:
'DEVICE P8X32A, XINPUT, PLL16X
'XIN 4_096_000
DEVICE P8X32A, XTAL1, PLL16X
XIN 4_096_000
LED PIN 9 OUTPUT
PROGRAM Start
Start:
TOGGLE LED
PAUSE 500
GOTO Start
As it is, the code works fine and the LED toggles at the correct 1 Hz rate. If I use the commented declaration, which is the one I'd expect to use, the PLL doesn't work and the code runs at 1/16 the expected speed. I can't find anything that suggests that the PLL only works with a crystal but not an oscillator, and in fact it does work with the VCXO, I just have to tell the compiler there's a crystal there (The Xo pin is open). Am I misunderstanding how this is supposed to work?
I looked at the assembler output thinking there might be an issue, but was having trouble making sense out of the _clkmode constant. I obviously need to spend more time in the Prop manual.
i'm using PropBasic and its really great!
But i've a problem with Data (LDATA) (Thats stored in the hub, right? so i can use values > 511)
The following code dont works (latest version of PropBasic and bst): The asm output is: but without any data!
Any ideas?
Thanks,
Pascal
I have used LDATA and it was OK. I have to admit with numbers only up to 6999. Perhaps the problem is in the code nearby?
Best regards and good luck((from Esslingen))
Christof
i tried this:
and get (no error in my code, because this is the result of "Compile Basic to Spin")
so any number > 511 will NOT processed But LDATA should use longs and they are (much) greater than 511.
Can you post a part of your code with LDATA? Wich version of PropBasic and BST do you use?
Any other idea?
Many greetings (from Wolfsburg )
Pascal
Fried
May I ask how STACK affects LMM code ? What is happening in "laymans terms" ?
Sorry, but I am struggling to get my head around the matter!
To also mention why I ask, should it be relevant... I have a 16Kb buffer which I populate with data, and verify it is correct, but then later in the program try to read it back and it's all gone to zeros. I have not accessed that HUB buffer since, but perhaps due to stack settings with the LMM it's getting overwritten? Just a guess as I scratch around for ideas!
The STACK in LMM is the depth of the call stack.
When using LMM the compiler uses a call stack to store the return address for calls. This is faster than modifying the return program location (since the return program location is stored in the HUB in LMM).
The stack is in COG RAM, it should have no effect on HUB RAM at all.
Bean
about the code error, I will continue to try and solve it and post later. In the other thread you mentioned a call for other things to add to the next revision. maybe this is something to wait for... I will try to solve it a quickly as possible.
Big thank you as always - especially for keeping PropBasic alive when the incentive might wear thin at times.
Unless you are using recursion the default STACK will be fine. If you are using recursion (only possible in LMM) then the stack must be at least as large as the deepest level of recursion possible.
Bean
And is that relevant at the moment they are called, or for the entire compiled code.
So if I have 2 sub routines, which each call another sub, which then call another sub.
... I think that means I have 2 sub routines each requiring stack of 3.. But they are called one after another, not at the same time. So would I need stack of 3 or 6 in this case ? (If I have the explanation right?!)
You could have 1,000 different calls that nest 3 deep, and one that nests 5 deep and you would require a stack of only 5 for the whole program.
P.S. Recursion where when a SUB or FUNC calls itself. Without local variables this is rarely done in PropBasic.
Bean
just to tidy up the end of the topic... would the compiler throw an error if the STACK was set too low ? Or otherwise, how could the problem of too small a stack be recognised (I mean before total system failure!!) ?
There is no way for the compiler to "know" how big the stack needs to be.
The lower limit of 4 is hard coded into the compiler.
If the stack is set too low, yes bad things will start happening. Like constants changing their value...Really fun stuff to try to debug.
Bean
I tried a much smaller buffer size (200 bytes) and it keeps the data. I tried randomly larger sizes, but above 200 bytes it seems to fail, so I was thinking it might be a hub space issue. But if I set the buffer size to a crazy high value, then the compiler fails and tells me to keep within 32k. So it would not seem logical that I have a problem with an oversized buffer as the compiler would catch that?...
..hmm,,.,. Is it possible that I recall some old recommendations about the importance of the order in which HUB (and perhaps even local) variables/constants are declared? Perhaps concerning size or variable type order? I'm using (LOADing) 2 or 3 libraries and a couple of tasks too, which have there own CON, VAR, HUB and PIN deifinitions. Could that be an issue- should those lib/task variables/etc.. be defined in the main cog to ensure they are compiled to the right place in the .spin file?
Something rings a small bell, but the dust is too thick on that part of my mind...
Info: BST reported data: Program=5763 Longs, Stack/Free=2425 Longs (I'm coding/compiling with ViewPort, but that doesn't report program size AFAIK)
It would seem the issue was TIMING.
I had 3 cogs all "doing stuff" with HUB variables, so perhaps the hub queue was overloaded?
One of the cogs was not doing timing-critical stuff, so I added a short pause (200 ms) at the end of its task loop and the problem is solved.
So the moral of the story.... if your program is behaving in an unexplainable way.... could be the HUB getting deadlocked.
:thumb:
I've got some boards on the way soon for a touchscreen and the memory access is going to be fairly fast - I wonder if propbasic could run on this in XMM mode?
Let's take this
and it compiles to this
I think the relevant code is in the LMM load loop
for XMM the rdlong is replaced with ?6 lines of code. Two ram chips in parallel so data is two bytes at once.
fetch a word, toggle counter pin, shift left 16 bits, fetch word, logical or with first word, toggle counter pin
I think there might need to be a mask in there somewhere too.
I'm wondering about the time it takes to fetch an instruction vs the time it takes to process that instruction. Would replacing the rdlong with 6 pasm instructions be too much of a performance hit?
I think it would be useful. Just thinking off-the-cuff you would remove the four RDLONG, ADD, NOP sequences with something like:
Assuming the data is on pins 0 thru 15
This would be 8 times slower than native code. Which is pretty good considering.
How do you change the address to implement GOTOs and such ?
Bean
So there is one 138 decoder chip, five 161 counter chips and two memory chips.
P0-P15 are a 16 bit data bus.
The 161 counters count when propeller pin P16 is toggled.
Load the 161 counters with a new start value by selecting /load low via P25,P26 and P27. The value for this is 001. So to load the counter, P25 high, P26 and P27 low, put the value on prop pins P0-P18, then P25,26,27 all high. Reloading the 161 will be when there is a goto, gosub or a write to a memory location. Most of the time though the program proceeds in a linear fashion so all you are doing is counting.
Memory chip /CS when P25 low, P26 high, P27 low.
Memory chip /RD is P19
Memory chip /WR is P20
If you were reading the chip (ie most of the time it is a read) then P19 stays low.
For your code, counterpin is P16. It counts on the positive edge, so would stay high most of the time, then to count, make it low then high.
Where you xor the pin, does that toggle it or just change its state?
Also, where you read in a number of rdlongs in sequence
Do you always read in four longs in sequence?
If so, then if you replaced this with XMM, does this mean that you only need to do one and change the #4 to #16 (or are there situations where you jump to, say __INSTR3 from somewhere else?)
Since there is no hub window with XMM, you can just have 1 in your loop.
xor changes the state of the pin from "high to low" or from "low to high"
You shouldn't need to adjust __PC because the hardware keeps track of the address. We really don't need to know what it is...
Bean
P.S. I just realized that we need to toggle the counter pin TWICE for each instruction...
This would run XMM code at 1.8M IPS with a 80Mhz clock...
I'm sure there is probably some tricks to reduce the instructions, but I can't think of any right now...
Oh, you could propbably setup a counter or the video hardware to toggle the counter pin. That would get you down to 7 instructions in the loop or 2.85M IPS.
Bean