@ersmith Have two strange issues with the Wiznet code.
First one is that in this function (in fptd.c) with C++ style reference:
void scan_files(const char* filename, char *dbuf, uint16_t& size)
this doesn't work:
size +=s;
but this does:
size = size + s;
Second issue is something strange with printf() after I call scan_files().
The code is printing the value of size, but it doesn't print correctly.
Seems to be printing the value of size before scan_files() was called.
Added a printf() inside scan_files() and it shows the correct value.
Also, the actual value is correct, it's just not printing correctly...
Here's example output:
@Rayman : thanks for the bug report, there was indeed a problem with compiling the assignment operators like +=, -=, *=, etc. when the LHS was a reference. That should be fixed in the github source now, so the solutions are either to update or to re-write the assignment operators to be plain operators.
As for the -O2 problem, I cannot reproduce it (I don't have Wiznet hardware so your sample program won't run for me), but in general I would suggest not using -O2 for big projects and complicated C code. -O2 is somewhat experimental (more likely to be buggy) and also produces bigger code, so for now I think your best bet is to stick with -O1.
Unforunately fstat() is not implemented. The work-arounds are either (1) to use stat() on the file name used to open the file, or (2) if it's only the size of the file that's needed, to use fseek()/ftell() to find the size instead of fstat().
@Wuerfel_21 Indeed -O2,~cse does fix the printf() issue.
Maybe I'll stick with that for now try to remember to drop to -O1 if anything else goes wrong...
@pik33 I encounter this issue too. Eric suggested it can be avoided by breaking things up into smaller chunks of code (subroutines) and reducing complexity. This has helped me a lot. YMMV
Hi,
is there a way to restart a program, that has been loaded with "Compile & Run on P2", without loading it again?
Thanks! Christof
Edit: This is a modified shell program. Tried to use the "exec" _execve(arg1, 0, 0);
Is there a special way needed to compile the binary for this? Or is the size limited for this?
Here is the main program for my MicroDOS. The program allows selecting and running other programs using PSRAM as temporary storage so it can run near all sizes of program (tested on ***yumes, works)
The idea is simple: (1) display a screen (2) list all bin files found in 'microDOS' directory on the SD (3) allow to select one with a keyboard
After the file is selected, it is loaded from SD into PSRAM.
Then all cogs are stopped and the assembly program is started inside a cog. The assembly program overvrites the hub with the binary, then stops PSRAM driver (the last working cog), coginit #0,#0 and stops itself.
' MicroDOS - a binary loader for a PSRAM P2 system
' v. 0.02- 20220614
' Piotr Kardasz, pik33@o2.pl
' MIT license
' For better effect compile with -DFF_USE_LFN
'-----------------------------------------------------------------------------------------------
const _clkfreq = 336956522 ' don't change, video drivers will set it to this
const pin=8 ' VGA pin
const hpin=0 ' HDMI pin
const up_key=$51 ' define your keys here
const down_key=$50
const w_key=$77
const s_key=$73
const enter_key=$0D
const v_back_color=147 ' Display colors for VGA and HDMI. Drivers use Atari type palette, 16 colors on high nibble, 16 luminances on low nibble, 32 is red, 112 is blue, 192 is green
const v_write_color=154
const h_back_color=147-16
const h_write_color=154-16
const v_vspace=40
const h_vspace=20
'-----------------------------------------------------------------------------------------------
#include "dir.bi"
dim v as class using "vg001.spin2" ' VGA driver
dim h as class using "hg008.spin2" ' HDMI driver
dim psram as class using "psram.spin2" ' PSRAM driver
'' All drivers are hacked for this. VGA and HDMI has to have separated buffers, PSRAM mailbuffers are moved to S7FF00 to make loading size as big as possible
'-----------------------------------------------------------------------------------------------
' Replace this with your keyboard driver. It has to provide readkey() which returns the pressed key code or zero if no key pressed
' To do: add a standard USB keyboard driver here.
dim kbd as class using "keyboard.spin2"
'-----------------------------------------------------------------------------------------------
dim videocog as integer
dim hdmicog as integer
dim base as ulong
dim mbox as ulong
dim files$(27)
dim shortfiles$(27)
dim filebuf(16383) as ubyte
let title$="P2 MicroDOS v. 0.03 - 20220614"
' Start cogs
let kbdcog=kbd.start()
psram.startx(0, 0, 12, 7)
mbox=psram.getMailbox(0)
videocog=v.start(pin,mbox)
v.cls(v_write_color,v_back_color)
hdmicog=h.start(hpin,mbox)
h.cls(h_write_color,h_back_color)
' Initialize the display
waitms(100)
v.setfontfamily(4)
v.outtextxycz(960-16*len(title$),v_vspace,title$,v_write_color,v_back_color,4,2)
h.setfontfamily(4)
h.outtextxycz(512-8*len(title$),h_vspace,title$,h_write_color,h_back_color,2,1)
mount "/sd", _vfs_open_sdcard()
chdir "/sd/microDOS"
let currentdir$="/sd/microDOS/"
let pos=3*v_vspace : let hpos=3*h_vspace
let filenum=0
' Find and list filenames (*.binary)
let filename$ = dir$("*", fbNormal)
while filename$ <> "" andalso filename$ <> nil
let ext$=right$(filename$,7)
if ext$=".binary" then
files$(filenum)=currentdir$+filename$
filename$=left$(filename$,len(filename$)-7)
shortfiles$(filenum)=replacechar$(filename$,"_"," "): filenum+=1
endif
filename$ = dir$()
end while
let title$="W,S or up,down arrow to select, Enter to run"
v.outtextxycz(960-16*len(title$),1080-2*v_vspace,title$,v_write_color,v_back_color,4,2)
h.outtextxycz(512-8*len(title$),576-2*h_vspace,title$,h_write_color,h_back_color,2,1)
h.outtextxycz(512-4*len(shortfiles$(0)),hpos,shortfiles$(0),h_back_color,h_write_color,1,1) : hpos+=h_vspace
v.outtextxycz(960-8*len(shortfiles$(0)),pos,shortfiles$(0),v_back_color,v_write_color,2,2) : pos+=v_vspace
for i=1 to filenum-1: h.outtextxycz(512-4*len(shortfiles$(i)),hpos,shortfiles$(i),h_write_color,h_back_color,1,1) : hpos+=h_vspace : next i
for i=1 to filenum-1: v.outtextxycz(960-8*len(shortfiles$(i)),pos,shortfiles$(i),v_write_color,v_back_color,2,2) : pos+=v_vspace : next i
' Wait for a keyboard input, highlight the selected name
let filepos=0
do: loop until kbd.readkey()=0
do
let key=kbd.readkey()
if key=down_key orelse key=s_key then
key=0
v.outtextxycz(960-8*len(shortfiles$(filepos)),v_vspace*(3+filepos),shortfiles$(filepos),v_write_color,v_back_color,2,2)
h.outtextxycz(512-4*len(shortfiles$(filepos)), h_vspace*(3+filepos),shortfiles$(filepos),h_write_color,h_back_color,1,1)
filepos+=1
if filepos>=filenum-1 then filepos=filenum-1
v.outtextxycz(960-8*len(shortfiles$(filepos)),v_vspace*(3+filepos),shortfiles$(filepos),v_back_color,v_write_color,2,2)
h.outtextxycz(512-4*len(shortfiles$(filepos)), h_vspace*(3+filepos),shortfiles$(filepos),h_back_color,h_write_color,1,1)
endif
if key=up_key orelse key=w_key then
key=0
v.outtextxycz(960-8*len(shortfiles$(filepos)),v_vspace*(3+filepos),shortfiles$(filepos),v_write_color,v_back_color,2,2)
h.outtextxycz(512-4*len(shortfiles$(filepos)), h_vspace*(3+filepos),shortfiles$(filepos),h_write_color,h_back_color,1,1)
filepos-=1
if filepos<0 then filepos=0
v.outtextxycz(960-8*len(shortfiles$(filepos)),v_vspace*(3+filepos),shortfiles$(filepos),v_back_color,v_write_color,2,2)
h.outtextxycz(512-4*len(shortfiles$(filepos)), h_vspace*(3+filepos),shortfiles$(filepos),h_back_color,h_write_color,1,1)
endif
' if enter, load the file
if key=enter_key then
let title$="Loading: " + files$(filepos)
v.box(0,1080-64,1919,1080-33,v_back_color)
v.outtextxycz(960-16*len(title$),1080-2*v_vspace,title$,v_write_color,v_back_color,4,2)
h.box(0,576-32,1023,576-17,h_back_color)
h.outtextxycz(512-8*len(title$),576-2*h_vspace,title$,h_write_color,h_back_color,2,1)
key=0
' now upload it to PSRAM
open files$(filepos) for input as #9
let pos=1: let r=0 : let psramptr=0
do
get #9,pos,filebuf(0),16384,r : pos+=r
psram.write(addr(filebuf(0)),psramptr,16384)
psramptr+=r ' move the buffer to the RAM and update RAM position. Todo: this can be done all at once
loop until r<>16384 orelse psramptr>=$7C000 ' do until eof or memory full
' stop all driver cogs except PSRAM
cpustop(kbdcog)
cpustop(videocog)
cpustop(hdmicog)
'start loading cog
let loadingcog=cpu(@loadcog,@filebuf)
' stop itself
cpustop(cpuid())
endif
loop
'--------------------------- THE END OF THE MAIN PROGRAM ------------------------------------------------------
'----- addr: the helper function, return ulong instead of pointer
function addr(byref v as const any) as ulong
return(cast(ulong,@v))
end function
'----- the loader cog
asm shared
org
loadcog cogid t1 ' get a cogid
mul t1, #12 ' compute the offset to PSRAM mailbox
add mailbox, t1 ' add offset to find this COG's mailbox
mov psramaddr,#0
p101 mov buf1,psramaddr ' psramaddr=hubaddr
mov buf2,##16384 ' loading size
mov cmd,psramaddr ' set the address for reading
setnib cmd, #%1011, #7 ' attach the command - read burst
setq #2 ' write 3 longs to the mailbox
wrlong cmd, mailbox ' read the PSRAM
p102 rdlong cmd, mailbox ' poll mailbox for result
tjs cmd, #p102 ' retry until valid
add psramaddr,##16384
cmp psramaddr,##$7C000 wcz
if_lt jmp #p101 ' loop until full hub loaded
cogstop #7 ' stop psram driver
cogid t1 ' get id
coginit #0,#0 ' start the new program
cogstop t1 ' stop the loader
t1 long 0
mailbox long $7FF00
psramaddr long 0
cmd long 0
buf1 long 0
buf2 long 1024
end asm
'----- The end ---------------------------------------------------------------------------------------------------
@"Christof Eb." : In general no, there is no way to restart a program that has been loaded without loading it again. If the program is carefully written to avoid any reliance on the initial values of any variables, then it could restart itself with coginit. Or, if it knows its own path, it could exec itself (although in some sense this is "loading it again").
At present exec() requires that both the original and new program fit into memory at the same time (the original program loads the new one, then copies it down to execute at 0). So for a program to exec itself it must be less than 256K long.
Another option for running programs is to compile it to run at a different address (using something like -E -H 0x10000) and have the original shell remain resident and running while the new program runs in a different COG at a different address.
Finally, if all of this is in service of your new Swieros based code, wouldn't you actually want the bytecode emulator to stay resident and to run programs that have been compiled into bytecode themselves? So you wouldn't be running multiple Prop binaries, just the emulator.
Finally, if all of this is in service of your new Swieros based code, wouldn't you actually want the bytecode emulator to stay resident and to run programs that have been compiled into bytecode themselves? So you wouldn't be running multiple Prop binaries, just the emulator.
Yes this is the idea.
Unfortunately this compiler mallocs several times but does not free and therefore the ram gets lost. So I wanted to have a workaround.
I think I will need a table for each program to keeping track of the mallocs and then free everything after finish.
Thank you, for the answer!
@"Christof Eb." said:
Unfortunately this compiler mallocs several times but does not free and therefore the ram gets lost. So I wanted to have a workaround.
You can try using the garbage-collector. Change malloc to _gc_alloc_managed. The "actual" solution would be write some sort of zone allocator to auto-free the memory when it's done, but that's more difficult IG.
@"Christof Eb." said:
Unfortunately this compiler mallocs several times but does not free and therefore the ram gets lost. So I wanted to have a workaround.
You can try using the garbage-collector. Change malloc to _gc_alloc_managed. The "actual" solution would be write some sort of zone allocator to auto-free the memory when it's done, but that's more difficult IG.
_gc_alloc_managed() did indeed solve the problem. Many thanks!
I am a little bit frightened, if the P2 really knows, what is not needed any more....
@pik33 said:
Here is the main program for my MicroDOS. The program allows selecting and running other programs using PSRAM as temporary storage so it can run near all sizes of program (tested on ***yumes, works)
The idea is simple: (1) display a screen (2) list all bin files found in 'microDOS' directory on the SD (3) allow to select one with a keyboard
After the file is selected, it is loaded from SD into PSRAM.
Then all cogs are stopped and the assembly program is started inside a cog. The assembly program overvrites the hub with the binary, then stops PSRAM driver (the last working cog), coginit #0,#0 and stops itself.
' MicroDOS - a binary loader for a PSRAM P2 system
' v. 0.02- 20220614
' Piotr Kardasz, pik33@o2.pl
' MIT license
' For better effect compile with -DFF_USE_LFN
'-----------------------------------------------------------------------------------------------
const _clkfreq = 336956522 ' don't change, video drivers will set it to this
const pin=8 ' VGA pin
const hpin=0 ' HDMI pin
const up_key=$51 ' define your keys here
const down_key=$50
const w_key=$77
const s_key=$73
const enter_key=$0D
const v_back_color=147 ' Display colors for VGA and HDMI. Drivers use Atari type palette, 16 colors on high nibble, 16 luminances on low nibble, 32 is red, 112 is blue, 192 is green
const v_write_color=154
const h_back_color=147-16
const h_write_color=154-16
const v_vspace=40
const h_vspace=20
'-----------------------------------------------------------------------------------------------
#include "dir.bi"
dim v as class using "vg001.spin2" ' VGA driver
dim h as class using "hg008.spin2" ' HDMI driver
dim psram as class using "psram.spin2" ' PSRAM driver
'' All drivers are hacked for this. VGA and HDMI has to have separated buffers, PSRAM mailbuffers are moved to S7FF00 to make loading size as big as possible
'-----------------------------------------------------------------------------------------------
' Replace this with your keyboard driver. It has to provide readkey() which returns the pressed key code or zero if no key pressed
' To do: add a standard USB keyboard driver here.
dim kbd as class using "keyboard.spin2"
'-----------------------------------------------------------------------------------------------
dim videocog as integer
dim hdmicog as integer
dim base as ulong
dim mbox as ulong
dim files$(27)
dim shortfiles$(27)
dim filebuf(16383) as ubyte
let title$="P2 MicroDOS v. 0.03 - 20220614"
' Start cogs
let kbdcog=kbd.start()
psram.startx(0, 0, 12, 7)
mbox=psram.getMailbox(0)
videocog=v.start(pin,mbox)
v.cls(v_write_color,v_back_color)
hdmicog=h.start(hpin,mbox)
h.cls(h_write_color,h_back_color)
' Initialize the display
waitms(100)
v.setfontfamily(4)
v.outtextxycz(960-16*len(title$),v_vspace,title$,v_write_color,v_back_color,4,2)
h.setfontfamily(4)
h.outtextxycz(512-8*len(title$),h_vspace,title$,h_write_color,h_back_color,2,1)
mount "/sd", _vfs_open_sdcard()
chdir "/sd/microDOS"
let currentdir$="/sd/microDOS/"
let pos=3*v_vspace : let hpos=3*h_vspace
let filenum=0
' Find and list filenames (*.binary)
let filename$ = dir$("*", fbNormal)
while filename$ <> "" andalso filename$ <> nil
let ext$=right$(filename$,7)
if ext$=".binary" then
files$(filenum)=currentdir$+filename$
filename$=left$(filename$,len(filename$)-7)
shortfiles$(filenum)=replacechar$(filename$,"_"," "): filenum+=1
endif
filename$ = dir$()
end while
let title$="W,S or up,down arrow to select, Enter to run"
v.outtextxycz(960-16*len(title$),1080-2*v_vspace,title$,v_write_color,v_back_color,4,2)
h.outtextxycz(512-8*len(title$),576-2*h_vspace,title$,h_write_color,h_back_color,2,1)
h.outtextxycz(512-4*len(shortfiles$(0)),hpos,shortfiles$(0),h_back_color,h_write_color,1,1) : hpos+=h_vspace
v.outtextxycz(960-8*len(shortfiles$(0)),pos,shortfiles$(0),v_back_color,v_write_color,2,2) : pos+=v_vspace
for i=1 to filenum-1: h.outtextxycz(512-4*len(shortfiles$(i)),hpos,shortfiles$(i),h_write_color,h_back_color,1,1) : hpos+=h_vspace : next i
for i=1 to filenum-1: v.outtextxycz(960-8*len(shortfiles$(i)),pos,shortfiles$(i),v_write_color,v_back_color,2,2) : pos+=v_vspace : next i
' Wait for a keyboard input, highlight the selected name
let filepos=0
do: loop until kbd.readkey()=0
do
let key=kbd.readkey()
if key=down_key orelse key=s_key then
key=0
v.outtextxycz(960-8*len(shortfiles$(filepos)),v_vspace*(3+filepos),shortfiles$(filepos),v_write_color,v_back_color,2,2)
h.outtextxycz(512-4*len(shortfiles$(filepos)), h_vspace*(3+filepos),shortfiles$(filepos),h_write_color,h_back_color,1,1)
filepos+=1
if filepos>=filenum-1 then filepos=filenum-1
v.outtextxycz(960-8*len(shortfiles$(filepos)),v_vspace*(3+filepos),shortfiles$(filepos),v_back_color,v_write_color,2,2)
h.outtextxycz(512-4*len(shortfiles$(filepos)), h_vspace*(3+filepos),shortfiles$(filepos),h_back_color,h_write_color,1,1)
endif
if key=up_key orelse key=w_key then
key=0
v.outtextxycz(960-8*len(shortfiles$(filepos)),v_vspace*(3+filepos),shortfiles$(filepos),v_write_color,v_back_color,2,2)
h.outtextxycz(512-4*len(shortfiles$(filepos)), h_vspace*(3+filepos),shortfiles$(filepos),h_write_color,h_back_color,1,1)
filepos-=1
if filepos<0 then filepos=0
v.outtextxycz(960-8*len(shortfiles$(filepos)),v_vspace*(3+filepos),shortfiles$(filepos),v_back_color,v_write_color,2,2)
h.outtextxycz(512-4*len(shortfiles$(filepos)), h_vspace*(3+filepos),shortfiles$(filepos),h_back_color,h_write_color,1,1)
endif
' if enter, load the file
if key=enter_key then
let title$="Loading: " + files$(filepos)
v.box(0,1080-64,1919,1080-33,v_back_color)
v.outtextxycz(960-16*len(title$),1080-2*v_vspace,title$,v_write_color,v_back_color,4,2)
h.box(0,576-32,1023,576-17,h_back_color)
h.outtextxycz(512-8*len(title$),576-2*h_vspace,title$,h_write_color,h_back_color,2,1)
key=0
' now upload it to PSRAM
open files$(filepos) for input as #9
let pos=1: let r=0 : let psramptr=0
do
get #9,pos,filebuf(0),16384,r : pos+=r
psram.write(addr(filebuf(0)),psramptr,16384)
psramptr+=r ' move the buffer to the RAM and update RAM position. Todo: this can be done all at once
loop until r<>16384 orelse psramptr>=$7C000 ' do until eof or memory full
' stop all driver cogs except PSRAM
cpustop(kbdcog)
cpustop(videocog)
cpustop(hdmicog)
'start loading cog
let loadingcog=cpu(@loadcog,@filebuf)
' stop itself
cpustop(cpuid())
endif
loop
'--------------------------- THE END OF THE MAIN PROGRAM ------------------------------------------------------
'----- addr: the helper function, return ulong instead of pointer
function addr(byref v as const any) as ulong
return(cast(ulong,@v))
end function
'----- the loader cog
asm shared
org
loadcog cogid t1 ' get a cogid
mul t1, #12 ' compute the offset to PSRAM mailbox
add mailbox, t1 ' add offset to find this COG's mailbox
mov psramaddr,#0
p101 mov buf1,psramaddr ' psramaddr=hubaddr
mov buf2,##16384 ' loading size
mov cmd,psramaddr ' set the address for reading
setnib cmd, #%1011, #7 ' attach the command - read burst
setq #2 ' write 3 longs to the mailbox
wrlong cmd, mailbox ' read the PSRAM
p102 rdlong cmd, mailbox ' poll mailbox for result
tjs cmd, #p102 ' retry until valid
add psramaddr,##16384
cmp psramaddr,##$7C000 wcz
if_lt jmp #p101 ' loop until full hub loaded
cogstop #7 ' stop psram driver
cogid t1 ' get id
coginit #0,#0 ' start the new program
cogstop t1 ' stop the loader
t1 long 0
mailbox long $7FF00
psramaddr long 0
cmd long 0
buf1 long 0
buf2 long 1024
end asm
'----- The end ---------------------------------------------------------------------------------------------------
Thank you!
At the moment I use a kiss board and I do not plan to have psram added.
Christof Eb,
You might find using __builtin_alloca() to be an advantage. It's the only allocator I use now. It automatically frees upon function return. And if you want the allocation to stick around then place it in main().
@ersmith Happy Thanksgiving! I should be up watching the dog show with family, but instead working on Wiznet
Anyway, this code was working fine with my custom uSD pinout and at 250 MHz.
Changed pins for P2 Eval board and it wouldn't work.
Works when I drop clock rate to 160 MHz (in Platform.h).
How is this even possible? Has me stumped...
it's the scan_files() method where it can't read Eval SD at high clock rate.
But, if I call that method right after mounting, then it works at 300 MHz
Added this to start of code:
Think I've isolated the issue to the DNS code. If I comment that section out, it works...
Maybe I should have troubleshooted some more before posting about this...
Found the problem... Seems one should call DNS_init() before using DNS. Guess that makes sense...
Was using a buffer pointer that wasn't initialized...
Hi,
...still fighting with memory allocation...
I am now working with a separate memory allocation table for each process of aPropOs , using malloc() and at the finish of the process free(). It seems to work most times, but from time to time, I get "corrupted heap". The functions may be called from different cogs.
Is there a limit for or what is the possible maximum number of calls of malloc()? I think, I might need 100 in total.
Is there something more to know about heap: What can cause "corrupted heap"?
Thank you!
Christof
@"Christof Eb." said:
Is there something more to know about heap: What can cause "corrupted heap"?
Corrupting the heap, somewhat obviously. In particular, it prints that message when it happens across an allocation block that is of zero size (as presumably occurs when you overwrite the allocation header with zeroes).
@"Christof Eb." :
"Corrupted heap" is normally caused by writing past the end of an allocated area, e.g. allocating 100 bytes and then writing 120 to it.
There's no intrinsic limit on the number of mallocs, except that the total size of the allocation is limited by the heap size. What value are you using for _HEAPSIZE?
Are you making sure to check the value returned by malloc for errors?
Thanks for the answers! At the moment the problem is gone. Unfortunately I am not sure, why. I am not aware of overwriting the end or begin.
I had used
int *i=malloc(x); .... free(i);
Now I use void *i , but I can't reproduce the problem with int *i .
Good to know, that there is no limit for the number of memory slices.
At the moment I can use 300kBytes for heap, as much as possible.
Perhaps the following code snippet is useful for somebody to explore the biggest slice available:
`mFree()
{
int dsize= HEAPSIZE, size=0;
void *mem;
Sorry for the stupid question, but is there a documentation for "command line idiots" of how to build the compiler on a Windows PC? I have TDM-GCC-32 installed which is part of my Code::Blocks IDE I use everyday. I thought this should be compatible to mingw but there seems to be something missing.
E:\Projekte\Parallax-Obex\spin2cpp-master>mingw32-make all
/usr/bin/sh: fgrep: command not found
gcc -O1 -Wall -fwrapv -I. -I./backends -I./frontends -I./build -DFLEXSPIN_BUILD
-o build/testlex.exe testlex.c build/lexer.o build/uni2sjis.o build/symbol.o bui
ld/ast.o build/expr.o build/dofmt.o build/flexbuf.o build/lltoa_prec.o build/str
upr.o build/strrev.o build/strdupcat.o build/to_utf8.o build/from_utf8.o build/p
reprocess.o -lm
build/lexer.o:lexer.c:(.text+0x21f): multiple definition of `FindSymbol'
C:\DOKUME~1\Besitzer\LOKALE~1\Temp\ccvhlR6w.o:testlex.c:(.text+0x413): first def
ined here
build/symbol.o:symbol.c:(.text+0x134): multiple definition of `FindSymbol'
C:\DOKUME~1\Besitzer\LOKALE~1\Temp\ccvhlR6w.o:testlex.c:(.text+0x413): first def
ined here
build/ast.o:ast.c:(.text+0x778): multiple definition of `FindSymbol'
C:\DOKUME~1\Besitzer\LOKALE~1\Temp\ccvhlR6w.o:testlex.c:(.text+0x413): first def
ined here
build/expr.o:expr.c:(.text+0x101): multiple definition of `FindSymbol'
C:\DOKUME~1\Besitzer\LOKALE~1\Temp\ccvhlR6w.o:testlex.c:(.text+0x413): first def
ined here
c:/programme/tdm-gcc-32/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.
exe: C:\DOKUME~1\Besitzer\LOKALE~1\Temp\ccvhlR6w.o: bad reloc address 0x2f4 in s
ection `.data'
collect2.exe: error: ld returned 1 exit status
Makefile:160: recipe for target 'build/testlex.exe' failed
mingw32-make: *** [build/testlex.exe] Error 1
@ManAtWork said:
Sorry for the stupid question, but is there a documentation for "command line idiots" of how to build the compiler on a Windows PC? I have TDM-GCC-32 installed which is part of my Code::Blocks IDE I use everyday. I thought this should be compatible to mingw but there seems to be something missing.
E:\Projekte\Parallax-Obex\spin2cpp-master>mingw32-make all
/usr/bin/sh: fgrep: command not found
gcc -O1 -Wall -fwrapv -I. -I./backends -I./frontends -I./build -DFLEXSPIN_BUILD
-o build/testlex.exe testlex.c build/lexer.o build/uni2sjis.o build/symbol.o bui
ld/ast.o build/expr.o build/dofmt.o build/flexbuf.o build/lltoa_prec.o build/str
upr.o build/strrev.o build/strdupcat.o build/to_utf8.o build/from_utf8.o build/p
reprocess.o -lm
build/lexer.o:lexer.c:(.text+0x21f): multiple definition of `FindSymbol'
C:\DOKUME~1\Besitzer\LOKALE~1\Temp\ccvhlR6w.o:testlex.c:(.text+0x413): first def
ined here
build/symbol.o:symbol.c:(.text+0x134): multiple definition of `FindSymbol'
C:\DOKUME~1\Besitzer\LOKALE~1\Temp\ccvhlR6w.o:testlex.c:(.text+0x413): first def
ined here
build/ast.o:ast.c:(.text+0x778): multiple definition of `FindSymbol'
C:\DOKUME~1\Besitzer\LOKALE~1\Temp\ccvhlR6w.o:testlex.c:(.text+0x413): first def
ined here
build/expr.o:expr.c:(.text+0x101): multiple definition of `FindSymbol'
C:\DOKUME~1\Besitzer\LOKALE~1\Temp\ccvhlR6w.o:testlex.c:(.text+0x413): first def
ined here
c:/programme/tdm-gcc-32/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.
exe: C:\DOKUME~1\Besitzer\LOKALE~1\Temp\ccvhlR6w.o: bad reloc address 0x2f4 in s
ection `.data'
collect2.exe: error: ld returned 1 exit status
Makefile:160: recipe for target 'build/testlex.exe' failed
mingw32-make: *** [build/testlex.exe] Error 1
Install a GCC that's not ancient.
I think the meaning of inline changed at some point and old GCC inexplicably generates an export symbol for every time the inline function is defined.
@ManAtWork I'm surprised your version of gcc had trouble with the inline, but that was a slightly complicated case, so I've changed it to a #define in the most recent source.
Comments
@ersmith Have two strange issues with the Wiznet code.
First one is that in this function (in fptd.c) with C++ style reference:
void scan_files(const char* filename, char *dbuf, uint16_t& size)
this doesn't work:
size +=s;
but this does:
size = size + s;
Second issue is something strange with printf() after I call scan_files().
The code is printing the value of size, but it doesn't print correctly.
Seems to be printing the value of size before scan_files() was called.
Added a printf() inside scan_files() and it shows the correct value.
Also, the actual value is correct, it's just not printing correctly...
Here's example output:
s=21, Size= 1666
s=19, Size= 1685
s=18, Size= 1703
s=21, Size= 1724
returned size: 6
The second issue is fixed by changing optimization level from 2 to 1.
Not the first issue though...
@Rayman : thanks for the bug report, there was indeed a problem with compiling the assignment operators like +=, -=, *=, etc. when the LHS was a reference. That should be fixed in the github source now, so the solutions are either to update or to re-write the assignment operators to be plain operators.
As for the -O2 problem, I cannot reproduce it (I don't have Wiznet hardware so your sample program won't run for me), but in general I would suggest not using -O2 for big projects and complicated C code. -O2 is somewhat experimental (more likely to be buggy) and also produces bigger code, so for now I think your best bet is to stick with -O1.
Perhaps note that you can try to narrow down the problematic part of -O2 by disabling its constituent flags individually. I.e. try
-O2,~cse
(this is the culprit most of the time)-O2,~inline-single
-O2,~loop-reduce
-O2,~remove-bss
Hi,
question about fstat(). What must I do to use this function in FlexProp?
Thank you!
Edit: I use the shell.c example of FlexProp with its filesystem as a basis.
Unforunately fstat() is not implemented. The work-arounds are either (1) to use stat() on the file name used to open the file, or (2) if it's only the size of the file that's needed, to use fseek()/ftell() to find the size instead of fstat().
@Wuerfel_21 Indeed -O2,~cse does fix the printf() issue.
Maybe I'll stick with that for now try to remember to drop to -O1 if anything else goes wrong...
When the code is somewhat bigger, the -o2 ends with this:
error: Internal error exceeded local register limit, possibly due to -O2 optimization needing additional registers or code being too complicated
Some time ago I gave up and I don't even try to use -o2.
@pik33 I encounter this issue too. Eric suggested it can be avoided by breaking things up into smaller chunks of code (subroutines) and reducing complexity. This has helped me a lot. YMMV
Hi,
is there a way to restart a program, that has been loaded with "Compile & Run on P2", without loading it again?
Thanks! Christof
Edit: This is a modified shell program. Tried to use the "exec" _execve(arg1, 0, 0);
Is there a special way needed to compile the binary for this? Or is the size limited for this?
Is there a command to completely reboot the P2? Found this, and will try it:
https://p2docs.github.io/hubctrl.html#software-reset
Here is the main program for my MicroDOS. The program allows selecting and running other programs using PSRAM as temporary storage so it can run near all sizes of program (tested on ***yumes, works)
The idea is simple: (1) display a screen (2) list all bin files found in 'microDOS' directory on the SD (3) allow to select one with a keyboard
After the file is selected, it is loaded from SD into PSRAM.
Then all cogs are stopped and the assembly program is started inside a cog. The assembly program overvrites the hub with the binary, then stops PSRAM driver (the last working cog), coginit #0,#0 and stops itself.
@"Christof Eb." : In general no, there is no way to restart a program that has been loaded without loading it again. If the program is carefully written to avoid any reliance on the initial values of any variables, then it could restart itself with coginit. Or, if it knows its own path, it could exec itself (although in some sense this is "loading it again").
At present exec() requires that both the original and new program fit into memory at the same time (the original program loads the new one, then copies it down to execute at 0). So for a program to exec itself it must be less than 256K long.
Another option for running programs is to compile it to run at a different address (using something like -E -H 0x10000) and have the original shell remain resident and running while the new program runs in a different COG at a different address.
Finally, if all of this is in service of your new Swieros based code, wouldn't you actually want the bytecode emulator to stay resident and to run programs that have been compiled into bytecode themselves? So you wouldn't be running multiple Prop binaries, just the emulator.
Yes this is the idea.
Unfortunately this compiler mallocs several times but does not free and therefore the ram gets lost. So I wanted to have a workaround.
I think I will need a table for each program to keeping track of the mallocs and then free everything after finish.
Thank you, for the answer!
You can try using the garbage-collector. Change malloc to
_gc_alloc_managed
. The "actual" solution would be write some sort of zone allocator to auto-free the memory when it's done, but that's more difficult IG._gc_alloc_managed() did indeed solve the problem. Many thanks!
I am a little bit frightened, if the P2 really knows, what is not needed any more....
Thank you!
At the moment I use a kiss board and I do not plan to have psram added.
Christof Eb,
You might find using
__builtin_alloca()
to be an advantage. It's the only allocator I use now. It automatically frees upon function return. And if you want the allocation to stick around then place it inmain()
.@ersmith Happy Thanksgiving! I should be up watching the dog show with family, but instead working on Wiznet
Anyway, this code was working fine with my custom uSD pinout and at 250 MHz.
Changed pins for P2 Eval board and it wouldn't work.
Works when I drop clock rate to 160 MHz (in Platform.h).
How is this even possible? Has me stumped...
it's the scan_files() method where it can't read Eval SD at high clock rate.
But, if I call that method right after mounting, then it works at 300 MHz
Added this to start of code:
Actually, just doing "opendir("/SD");" at start of code makes it work...
Think I've isolated the issue to the DNS code. If I comment that section out, it works...
Maybe I should have troubleshooted some more before posting about this...
Ok, nevermind, nothing to see here...
Found the problem... Seems one should call DNS_init() before using DNS. Guess that makes sense...
Was using a buffer pointer that wasn't initialized...
@Rayman : glad you were able to find it!
Hi,
...still fighting with memory allocation...
I am now working with a separate memory allocation table for each process of aPropOs , using malloc() and at the finish of the process free(). It seems to work most times, but from time to time, I get "corrupted heap". The functions may be called from different cogs.
Is there a limit for or what is the possible maximum number of calls of malloc()? I think, I might need 100 in total.
Is there something more to know about heap: What can cause "corrupted heap"?
Thank you!
Christof
I'm not sure but you might be required to use the garbage collection functions.
Corrupting the heap, somewhat obviously. In particular, it prints that message when it happens across an allocation block that is of zero size (as presumably occurs when you overwrite the allocation header with zeroes).
@"Christof Eb." :
"Corrupted heap" is normally caused by writing past the end of an allocated area, e.g. allocating 100 bytes and then writing 120 to it.
There's no intrinsic limit on the number of mallocs, except that the total size of the allocation is limited by the heap size. What value are you using for _HEAPSIZE?
Are you making sure to check the value returned by malloc for errors?
Thanks for the answers! At the moment the problem is gone. Unfortunately I am not sure, why. I am not aware of overwriting the end or begin.
I had used
int *i=malloc(x); .... free(i);
Now I use void *i , but I can't reproduce the problem with int *i .
Good to know, that there is no limit for the number of memory slices.
At the moment I can use 300kBytes for heap, as much as possible.
Perhaps the following code snippet is useful for somebody to explore the biggest slice available:
`mFree()
{
int dsize= HEAPSIZE, size=0;
void *mem;
while(dsize>512){
dsize=dsize/2;
size+=dsize;
mem= malloc(size);
if(!mem) size-=dsize;
free(mem);
}
printf("Free Memory: %d kByte\n", size/1024);
}
`
Sorry for the stupid question, but is there a documentation for "command line idiots" of how to build the compiler on a Windows PC? I have TDM-GCC-32 installed which is part of my Code::Blocks IDE I use everyday. I thought this should be compatible to mingw but there seems to be something missing.
Install a GCC that's not ancient.
I think the meaning of
inline
changed at some point and old GCC inexplicably generates an export symbol for every time the inline function is defined.@ManAtWork you may also try to
mingw32-make all OPT="-Og -g -std=gnu11"
(aftermingw32-make clean
of course)That parameter should probably be enshrined in the makefile itself.
@ManAtWork I'm surprised your version of gcc had trouble with the inline, but that was a slightly complicated case, so I've changed it to a #define in the most recent source.