--
You received this message because you are subscribed to the Google Groups "RC2014-Z80" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rc2014-z80+...@googlegroups.com.
To post to this group, send email to rc201...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/CAK%2B%3DWr9y76%3D7skujqveY8vQu_jhme1%3DiXtObZP6r6Q8ecZSXVA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/CAKD5ztY1WawCFhR5kpADPgvpgUmfRyBZDOyJDOUnAeKsHqH-rg%40mail.gmail.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/766BAD6A-7788-4C37-BA31-DF784BB6E399%40gmail.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/CAO93Pte_fLYPUi2U_nbRJfjzJn6Bzk7oL%3DeYwzj_TDPm1ZiQWg%40mail.gmail.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/766BAD6A-7788-4C37-BA31-DF784BB6E399%40gmail.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/F4CDDB0F-869D-4BC2-84ED-A4EF22066510%40gmail.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/EAEFDFB1-B426-42CC-857F-0CCB8726BDE0%40gmail.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/BD613C1B-CC19-4C7D-A1E1-7FDA3D4B8EE3%40gmail.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/CAKD5ztZDQ-M__uNJbhR5%2B9eezksXp8VXDwnn_fY2cf_zUxF07w%40mail.gmail.com.
Hold on...If all the code il located on a read only memory I cannot just read and write on the "program" array (Scott hope you remember your basic source code) as it would for sure be located in the wrong memory area.I've never had such issues in my life since I usually have all the _ram_ space at my service ;) so.. Without a linker script that places the data section at the correct place I need to work a little bit more to fix these problems
--
You received this message because you are subscribed to the Google Groups "RC2014-Z80" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rc2014-z80+...@googlegroups.com.
To post to this group, send email to rc201...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/5c5d9ac2-1a5b-45d7-9c75-6c7f67840d14%40googlegroups.com.
I'm sorry if someone asked on your forum for the rc2014 :) this is a rather new community that is growing around Spencer's RC2014 home-brew computer.
Given the growing interest for rc2014, I was already thinking to handle it properly and create a new z88dk "target" for it. As usual, I'll need to provide some initialisation code and I need to figure out where to place all the stuff in memory (stack location, ROM/RAM areas, etc). I'll read the documentation you mentioned to experiment a bit.
As I said, I'm quite new to this so I already have a lot of question regarding your toolkit. If you think it's appropriate I can post some on your forum. In the meanwhile, thank you again for your all the useful informations you told us :)
--
You received this message because you are subscribed to the Google Groups "RC2014-Z80" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rc2014-z80+...@googlegroups.com.
To post to this group, send email to rc201...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/24f393a7-c285-4df7-8329-c0bd9106ce9d%40googlegroups.com.
Nearly! It is very close to working, but not quite...
If I boot straight in to the Tiny Basic rom, I just get a line of random characters on the screen (although the same random characters every time). Same if I reset it.
However, if I boot with the jumpers set to Grants Basic, then swap the jumpers around, it kind of works, and displays your copyright message. So this makes me think the reset routine isn't initialising the CPU properly?
If I type in a simple program, it gets confused. Sometimes it lists ok, and sometimes it has (consistently) random characters in it, but I can't get it to run. This might be because it had been "jump started" from Grants Basic though, so it might not have initialised what it needs. See attached screen shots.
(I love the error messages btw)
Let me know if there's any more tests you want me to do if it'll help.
Thanks
Spencer
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/CAK%2B%3DWr-YfN_JSHq%3D6uQJazEKTsr5QLNpXg%2BnK%2BcUEy-paV11Sw%40mail.gmail.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/CAO93PtdJejYE0bo3XXza2DBAFLdt7nu%2BmbivTvWGPyfindmZMQ%40mail.gmail.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/CAK%2B%3DWr9VTS4AjkgKhRtQCRmB6gP3OBy-FGoyQNEnhuyU%3DmJmYQ%40mail.gmail.com.
<TinyBasicPlus.hex>
<TinyBasicPlus.rom>
<pigfx_test.hex>
<pigfx_test.rom>
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/F424423F-142A-4839-AD7E-784E2CDC69E5%40gmail.com.
Ooops, maybe it's just me that inserts a silent U in PIGFX :-/
Yes! Tiny Basic works! See attached screenshots (including the broken one from earlier which I forgot to attach!). I'll have to go and look up what the advantages and limitations of this one is now.
Also, see screenshot from the pigfx_test rom. It looks like it works - assuming that's what it us supposed to do :)
Cheers
Spencer
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/7E611A91-CD6F-4B7D-AFE9-BE8A0D529484%40gmail.com.
Oh yea!!! I'm so happy that it works!
:020000040000FA--
You received this message because you are subscribed to the Google Groups "RC2014-Z80" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rc2014-z80+...@googlegroups.com.
To post to this group, send email to rc201...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/f895a0b1-e6e2-429e-bb61-f942c8d642a5%40googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "RC2014-Z80" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rc2014-z80+...@googlegroups.com.
To post to this group, send email to rc201...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/f63d9cb8-a169-4d37-b466-7141d8d3654d%40googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/CAK%2B%3DWr9YEnpCyVM0ZmwHbHdmiZxSYSEuU6i32EYYFRs2_age2A%40mail.gmail.com.
zcc +rc2014 -v -SO3 -startup=1 -clib=sdcc_iy --max-allocs-per-node200000 --c-code-in-asm --list -m test.c -o test
cat test_CODE.bin test_DATA.bin > test.bin
z80dasm --address --labels --origin=0x0 test.bin
appmake +hex --org=0x0 --binfile test.bin --output test.hex#include <stdio.h>
extern uint8_t rc2014_pollc(void);
extern uint8_t rc2014_getc(void);
extern void rc2014_putc(uint8_t);
uint8_t a;
uint8_t chr;
void main(void)
{
for(;;)
{
if (rc2014_pollc())
{
chr = rc2014_getc();
rc2014_putc(chr);
}
__critical{
a++;
}
}
}
void z80_rst_38h (void) __interrupt (1)
{
a--;
}
--
You received this message because you are subscribed to the Google Groups "RC2014-Z80" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rc2014-z80+unsubscribe@googlegroups.com.
To post to this group, send email to rc201...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/a86ce7c3-a8d4-4ca8-b27b-73931a416eec%40googlegroups.com.
-startup=xWell the good news is with the nonsensical mini test program, that there is life!
But it is not correct. Ideally the characters should be echoed. They aren't being echoed.
But, I'm afraid I won't be able to do any more debugging currently.
I've just been made aware that the 27C512 ROM is just that, ROM.
Silly me thought it was EEPROM...
And, I've run out of lives.
Stay tuned. ;-)
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/70901391-cb4b-441b-bbbd-16a13a323b9b%40googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/0a4f7d4b-c4a1-4c61-9dfc-d180ba58d51b%40googlegroups.com.
void z80_rst_38h (void) __interrupt (1)
{
a--;
}
zcc +rc2014 -v -SO3 -startup=1 -clib=sdcc_iy --max-allocs-per-node200000 --c-code-in-asm --list -m test.c -o test
cat test_CODE.bin test_DATA.bin > test.bin
z80dasm --address --labels --origin=0x0 test.bin
appmake +hex --org=0x0 --binfile test.bin --output test.hex
zcc +rc2014 -v -SO3 -startup=1 -clib=sdcc_iy --max-allocs-per-node200000 --c-code-in-asm --list -m test.c -o test -create-app -Cz--ihexz80dasm --address --labels --origin=0x0 test.bin
You will get the final binary "test.bin" (which has had the cat done already) and "test.ihx" with correct ORG set from the compile. create-app will work for all the compile models, including the compressed rom model in which create-app will also compress the data section for you.
Well the good news is with the nonsensical mini test program, that there is life!
But it is not correct. Ideally the characters should be echoed. They aren't being echoed.
| PUBLIC _rc2014_putc |
| _rc2014_putc: |
| ld a, l |
| rst $08 ; jump to Interrupt Address 0x0008 |
void z80_rst_38h (void) __critical __interrupt(1)
{
a--;
}Interrupts.Is the issue around provision of the __critical keyword?I would have thought that the code would need to refer to interrupt 1 as invoid z80_rst_38h (void) __critical __interrupt(1)
{
a--;
}
The table you refer to is not specific as to whether the bracketed variable needs to match, or not.
Or, is it always __critical __interrupt(0) ?
The documentation refers to the appmake tool only being able to be run in default mode from within the standard chain, and separating it out from the compilation was the only way that I could see to get a HEX file as output.
Is the .ihx file you refer to in standard HEX format with preamble, etc?I'll give this a go shortly.
OPTIONS -v -O2 -SO2 -I. -D__Z88DK -DZ80 -DRC2014 -D__RC2014__ -D__RC2014 -M -subtype=rom -clib=sdcc_iy
CLIB sdcc_iy -compiler=sdcc --reserve-regs-iy -D__SDCC -D__SDCC_IY -Ca-D__SDCC -Ca-D__SDCC_IY -Cl-D__SDCC -Cl-D__SDCC_IY -nostdlib -IDESTDIR/include/_DEVELOPMENT/sdcc -Ca-IDESTDIR/libsrc/_DEVELOPMENT/target/rc2014 -lrc2014 -
crt0=DESTDIR/libsrc/_DEVELOPMENT/target/rc2014/rc2014_crt
SUBTYPE rom -startup=1 -Cz+rom -Cz--org=0 -Cz--ihex
SUBTYPE rom_zx7 -startup=2 -Cz+rom -Cz--org=0 -Cz--ihex
On Friday, September 23, 2016 at 7:22:52 PM UTC-6, phillip.stevens wrote:The documentation refers to the appmake tool only being able to be run in default mode from within the standard chain, and separating it out from the compilation was the only way that I could see to get a HEX file as output.
zcc +rc2014 -subtype=rom --max-allocs-per-node200000 test.c -o test -create-appzcc +rc2014 -subtype=rom_zx7 --max-allocs-per-node200000 test.c -o test -create-appzcc +rc2014 -subtype=rom -v -m -SO3 --max-allocs-per-node200000 --c-code-in-asm --list test.c -o test -create-appOPTIONS -v -O2 -SO2 -I. -D__Z88DK -DZ80 -DRC2014 -D__RC2014__ -D__RC2014 -M -subtype=rom -clib=sdcc_iy
CLIB sdcc_iy -compiler=sdcc --reserve-regs-iy -D__SDCC -D__SDCC_IY -Ca-D__SDCC -Ca-D__SDCC_IY -Cl-D__SDCC -Cl-D__SDCC_IY -nostdlib -IDESTDIR/include/_DEVELOPMENT/sdcc -Ca-IDESTDIR/libsrc/_DEVELOPMENT/target/rc2014 -lrc2014 -
crt0=DESTDIR/libsrc/_DEVELOPMENT/target/rc2014/rc2014_crt
SUBTYPE rom -startup=1 -Cz+rom -Cz--org=0 -Cz--ihex
SUBTYPE rom_zx7 -startup=2 -Cz+rom -Cz--org=0 -Cz--ihex
zcc +rc2014 -subtype=rom --max-allocs-per-node200000 test.c -o test -create-app -pragma-define:CRT_ORG_CODE=0x100
On Monday, September 26, 2016 at 3:58:39 AM UTC-6, phillip.stevens wrote:OPTIONS -v -O2 -SO2 -I. -D__Z88DK -DZ80 -DRC2014 -D__RC2014__ -D__RC2014 -M -subtype=rom -clib=sdcc_iy
CLIB sdcc_iy -compiler=sdcc --reserve-regs-iy -D__SDCC -D__SDCC_IY -Ca-D__SDCC -Ca-D__SDCC_IY -Cl-D__SDCC -Cl-D__SDCC_IY -nostdlib -IDESTDIR/include/_DEVELOPMENT/sdcc -Ca-IDESTDIR/libsrc/_DEVELOPMENT/target/rc2014 -lrc2014 -
crt0=DESTDIR/libsrc/_DEVELOPMENT/target/rc2014/rc2014_crt
SUBTYPE rom -startup=1 -Cz+rom -Cz--org=0 -Cz--ihex
SUBTYPE rom_zx7 -startup=2 -Cz+rom -Cz--org=0 -Cz--ihex
That's a pretty good idea to use a more friendly subtype=rom,... to shorten the compile line.
I would take out the "-Cz--org=0" though -- appmake will pick up the org address from CRT_ORG_CODE after the compile so it will use your target default of 0x0000 anyway. If you leave it in there, it will override what the user supplies as ORG. So, eg:zcc +rc2014 -subtype=rom --max-allocs-per-node200000 test.c -o test -create-app -pragma-define:CRT_ORG_CODE=0x100
should be able to move the org address to 0x100 and it will do that if ""-Cz--org=0" is removed.
I'd also add a RAM model compile maybe with subtype=ram. There is a hex loader that loads programs to a fixed ram address so the default compile address could be that.
Maybe subtype=romc is quicker to type than subtype=rom_zx7 ?
In target defaults you're selecting a cmos z80 and enabling "sll r" instructions. Mainly the selection of cmos means the library will use "ld a,i" to find out if maskable interrupts are currently enabled. This works reliably on cmos z80s only and will occasionally fail on nmos z80s. "sll r" type instructions may not be reliable on cmos z80s (they are undocumented and are replaced in the z80's successor chips).
In "crt_interrupts.inc", I would move those subroutines into the rc2014 library. What will happen is if any of those restarts are enabled (and one is by default - CRT_ENABLE_RST = 0x8E) and the program does not supply them, the linker will find them in the library. But if the user program supplies them, the user's versions will override the library versions because the linker will preferentially search the user code for the restarts first. So if those routines are moved to the library, the user program has the ability to supply its own if that's what the user wants. If they are moved to the library, I would assign the code to section "code_crt_common". This will ensure the code is sequenced right after the crt startup code very early in the binary. In case someone tries bankswitching this will keep the restart code in an unbankswitched memory page.
So far so good :) The hookup to stdio comes with a bit of learning curve and lack of documentation but the cp/m drivers connected to bdos (not the dcio version as those are plugging into z88dk's terminal drivers) are simply outputting and reading single chars which I think should be very similar to how an rc2014 driver might look. If you are doing an interrupt driven version, you would have to write code that writes incoming chars to a circular buffer and then the driver would read from that circular buffer. There are a bunch of containers in the adt subdirectories but none are circular buffers.
I'd also add a RAM model compile maybe with subtype=ram. There is a hex loader that loads programs to a fixed ram address so the default compile address could be that.Not sure what the characteristics of a RAM load would look like right now. Either the existing hardware starting at 0x8000 or a new hardware starting at 0x2000. Depends on what Spencer comes up with. I'll leave this for the time being.
Maybe subtype=romc is quicker to type than subtype=rom_zx7 ?Yes, but not as clear... I'm a bit OCD about clarity.
I assumed that we're only dealing with CMOS (static) chips these days? The rc2014 comes so equipped. Is there any reason to believe that we have to deal with NMOS Z80s in the rc2014 target?
- Option a). Move everything in a C library for stdio interrupts, where I have access to a fast ring buffer implementation that I understand. And leave just the minimum start-up code in ASM. That would be setting the stack, heap, configuring interrupt IM 1. This is like the way I do AVR ATmega code.
- Option b). Keep the stdio routines for putc and getc characters to USART in ASM. There it would be a longer learning experience with Z80 assembler. But that's part of the fun. But on the upside it may also be easier to link to the ASM routines for stdio if the putc and getc routines are also in ASM.
Thanks for the tips on stdio. The documentation on integrating the stdio comes from the classic library and was last updated in 2003. I wasn't sure that it was still accurate. It would be good to have some current info on this.
I assumed that we're only dealing with CMOS (static) chips these days? The rc2014 comes so equipped. Is there any reason to believe that we have to deal with NMOS Z80s in the rc2014 target?
I was thinking more of the enabling of "sll r" instructions -- these might not work on all cmos z80s. We're careful to keep them out of most library code but some code comes from 3rd parties, one being zx7's decompressor. It uses "sll r" instructions that we kept but provided a way to opt out of with that flag.
- Option b). Keep the stdio routines for putc and getc characters to USART in ASM. There it would be a longer learning experience with Z80 assembler. But that's part of the fun. But on the upside it may also be easier to link to the ASM routines for stdio if the putc and getc routines are also in ASM.
Of course ideally it's in asm because there are probably a lot fewer cycles available on a z80 than an ATmega. But the C would work and would enable something to get going quickly if the driver is not trivial. Interfacing the C and asm is fairly simple -- you'd just need to be careful to save registers when passing to C. You could always rewrite in asm as time passes.
Thanks for the tips on stdio. The documentation on integrating the stdio comes from the classic library and was last updated in 2003. I wasn't sure that it was still accurate. It would be good to have some current info on this.The new c library stdio model is completely different. It's an object oriented model that is meant to simplify driver implementation by allowing code inheritance from the library, if that's desired. It also allows the library to behave like it does on larger machines. The difficulty is the new stdio model is not complete. The disk i/o is yet to come and that will cause some changes in the rest of the drivers and the rest of the drivers are going to see a version 3 to clean up data structures and introduce non-blocking i/o. So things are little bit fluid but the good news is, unless you want to go bare metal, it is possible to write terminal drivers by supplying a couple dozen lines of code to the current codebase. Once you understand how to do it of course! And your case of doing something interrupt driven will also mean more custom code has to be written by you but it would be fairly easy (in numbers of lines of code) to do a blocking driver now.
There is a short bit of information on the new c lib drivers here:
http://www.z88dk.org/wiki/doku.php?id=temp:front#device_drivers
Anyway that should get you started. Quick stdin/stdout/stderr drivers could be written by simply copying the cp/m bdos drivers.
This is something we don't expect people to be able to do without assistance so if you run into trouble just ask.
#include <stdio.h>
#include <string.h>
extern void rc2014_init_acia(void); // initialise the ACIA, and Interrupt
extern void rc2014_flush(void); // initialise the Tx & Rx buffers
extern uint8_t rc2014_pollc(void); // Rx polling routine, checks Rx buffer, not the ACIA
extern uint8_t rc2014_getc(void); // Rx receive routine, from Rx buffer
extern uint8_t rc2014_peekc(void); // Rx peek routine, reads Rx without removing it from buffer
extern void rc2014_putc(uint8_t) __z88dk_fastcall; // Tx write routine, writes to Tx buffer
void rc2014_Print( const uint8_t * str);// print out strings
uint8_t chr;
void main(void)
{
rc2014_init_acia();
rc2014_Print("Hello World\r\n");
for(;;)
{
if (rc2014_pollc())
{
chr = rc2014_getc();
rc2014_putc(chr);
}
}
}
void rc2014_Print( const uint8_t * str)
{
int16_t i = 0;
size_t stringlength;
stringlength = strlen((char *)str);
while(i < stringlength)
rc2014_putc( str[i++] );
}Ah, after spending a few hours trying to understand how the "correct" method for building the right low level drivers for the stdio library, I'm still at a complete loss. I would guess that the right way is to move the things I've just written into a library somewhere, and call them by the correct names (with public definitions). But beyond that it seems very confusing for me. Sorry for being thick.
Ah, after spending a few hours trying to understand how the "correct" method for building the right low level drivers for the stdio library, I'm still at a complete loss. I would guess that the right way is to move the things I've just written into a library somewhere, and call them by the correct names (with public definitions). But beyond that it seems very confusing for me. Sorry for being thick.
I had way too much trouble with guthub tonight so instead I'm just going to zip up the target/rc2014 directory:
https://drive.google.com/file/d/0B6XhJJ33xpOWdy1OSDhSZlZPYlE/view?usp=sharing
A list of changes:
8. device/acia is your driver code. There was a bug in the initialization (acia_init) where constants were loaded with "ld a,(n)" instead of "ld a,n". I don't know if this was the main cause of the problems.
I separated out a flush_Rx because the library needs a way to flush the input and output channels separately.
The acia initialization is wedged into the crt differently. It is placed into section "crt_code_init" which is a section sequenced just before main is called. So anything placed there will run before main. I do a little cheat to make sure acia_init is placed there when it is needed. In every acia function, you will see a "defc NEED_ACIA_INIT = _acia_init" at the bottom. This generates a reference to that function, guaranteeing the linker will pull it in.
There are a couple of things that came up: will there be more than one ACIA chip? If so, will there be one driver written for each of them with hard coded port addresses or will there be one driver shared amongst different ACIA instantiations? If the latter, then the buffer code can be modified to use a buffer stored with the driver, that way giving each ACIA instantiation its own buffer. Something like this probably needs more thought.
As interrupting devices are added, are they going to be added to im2 or will their isrs all be on im1? If the latter, some scheme to chain isrs can be thought up. The library does already have a "generic isr" that allows isrs to be registered with it. On interrupt all isrs registered get a chance to run. But it doesn't have to be done this way.
Anyway feel free to change what you don't like! This code should allow printf and scanf both to function. If they work, you can try to compile some of the examples in libsrc/_DEVELOPMENT/examples. Many of those programs are fairly big so won't fit into a small ROM but if you can compile to RAM, they should be runnable.
I could have employed 1,000,000 monkeys for 10 years, and never come up with that result. I know I certainly never would have gotten to this point. Thanks, again.I'm still not sure I understand the connection to the stdio platform. I'll have to digest this over the coming week.But, I've committed the changes to the repository.
My assumption is that this acia_init is now "mandatory" code and is run automatically at startup.So calling it again would result in a hang, because there is no ret at its end?
I'm assuming that Scott will want to do more things with the RC2014. Currently there is only one ACIA board available, so it makes sense to have the code written for one. I'm interested to know how to write for more I/O, as I'm building something with a z8s180 which has to integrated USARTs, but that's off topic here.
I'm wondering if the printf() in its standard form goes to the right place, ACIA Tx. Or, is there something that needs to be set to configure this?
include(../../clib_instantiate_begin.m4)
include(../driver/character/rc_00_input_acia.m4)
m4_rc_00_input_acia(_stdin, 0x0100)
include(../driver/character/rc_00_output_acia.m4)
m4_rc_00_output_acia(_stdout, 0x0100)
include(../../m4_file_dup.m4)
m4_file_dup(_stderr, 0x80, __i_fcntl_fdstruct_1)
include(../../clib_instantiate_end.m4)
Will keep on this over the week.
The FILE* are created by name. stdout is attached to m4_rc_00_output_acia so printf will go to that driver. By virtue of the dup, fprintf(stderr,...) will also go to that driver.
* Change of names from "__acia_XX_data" to "__acia_bss_XX" so that
data/bss variables are separated and sortable according to section
* Renamed the two flush functions to "*flush_XX_di" and "*flush_XX" so
that it is clear which version disables interrupts and which doesn't
* The acia_init function is now a callable function with return address.
The code_crt_init insert is now a call to this function.
* The acia's im1 routine is now called _acia_interrupt with no
z80_rst_38h alias. Instead the default selection of im1 routine is made
in a separate z80_rst_38h.asm file. This is to avoid a linking error
where user declares own z80_rst_38h and calls acia_interrupt directly;
this would bring two z80_rst_38h into global scope.
* Temporary fix to bug associated with declaring the aciaTxBuffer and
the aciaRxBuffer. At library build time their sizes "ACIA_TX_SIZE" and
"ACIA_RX_SIZE" were unavailable so the library was creating zero-size
buffers. The temporary fix is hardcoding the sizes but this should be
fixed up when a better way to instantiate devices is introduced.
// zcc +rc2014 -vn -subtype=rom test.c -o test -create-app -m --list --c-code-in-asm
#pragma output CLIB_OPT_PRINTF = 0 // disable all % converters
#include <stdio.h>
void main(void)
{
printf("Hello World\n");
}
--
You received this message because you are subscribed to a topic in the Google Groups "RC2014-Z80" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/rc2014-z80/-4jOOxYXGEo/unsubscribe.
To unsubscribe from this group and all its topics, send an email to rc2014-z80+unsubscribe@googlegroups.com.
To post to this group, send email to rc201...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/d1bddd70-e570-4103-8858-1d3dac0a6bfd%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Did you clone the repo? If so I can add you to enable further pulls. There was only one clone to date.
--
You received this message because you are subscribed to the Google Groups "RC2014-Z80" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rc2014-z80+unsubscribe@googlegroups.com.
To post to this group, send email to rc201...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/54974e5c-c055-48b3-b9d1-5e2b3db35d59%40googlegroups.com.
Then, you should simply follow these steps:
I don't have permission to send a pull request so I've zipped up the rc2014 directory again:
https://drive.google.com/open?id=0B6XhJJ33xpOWdy1OSDhSZlZPYlE
Some of the changes:* Change of names from "__acia_XX_data" to "__acia_bss_XX" so that
data/bss variables are separated and sortable according to section* Renamed the two flush functions to "*flush_XX_di" and "*flush_XX" so
that it is clear which version disables interrupts and which doesn't
* The acia_init function is now a callable function with return address.
The code_crt_init insert is now a call to this function.
* The acia's im1 routine is now called _acia_interrupt with no
z80_rst_38h alias. Instead the default selection of im1 routine is made
in a separate z80_rst_38h.asm file. This is to avoid a linking error
where user declares own z80_rst_38h and calls acia_interrupt directly;
this would bring two z80_rst_38h into global scope.
* Temporary fix to bug associated with declaring the aciaTxBuffer and
the aciaRxBuffer. At library build time their sizes "ACIA_TX_SIZE" and
"ACIA_RX_SIZE" were unavailable so the library was creating zero-size
buffers. The temporary fix is hardcoding the sizes but this should be
fixed up when a better way to instantiate devices is introduced.
With these changes I can see "Hello World" written to the Tx Buffer under emulation (not an rc2014 emulation since I have to figure out how to build under windows and I haven't done that).// zcc +rc2014 -vn -subtype=rom test.c -o test -create-app -m --list --c-code-in-asm
#pragma output CLIB_OPT_PRINTF = 0 // disable all % converters
#include <stdio.h>
void main(void)
{
printf("Hello World\n");
}
The main bug was in the declaration of the Tx and Rx buffers. When they are compiled into the library, their sizes must be known, but they were not since the size defines are in a compile-time definitions file. This led to Tx and Rx buffers of size 0 in the program. I made a temporary change where the sizes are hard coded to $80 bytes as defined by the compile-time constants.
#include <stdio.h>
#include <string.h>
extern void acia_init(void); // initialise the ACIA, and Interrupt
extern void acia_reset(void); // initialise the Tx & Rx buffers
extern void acia_flush_Rx(void); // initialise the Rx buffer
extern void acia_flush_Tx(void); // initialise the Tx buffer
extern uint8_t acia_pollc(void); // Rx polling routine, checks Rx buffer fullness
extern uint8_t acia_getc(void); // Rx receive routine, from Rx buffer
extern uint8_t acia_peekc(void); // Rx peek routine, reads Rx without removing it from buffer
extern uint8_t acia_putc(uint8_t) __z88dk_fastcall; // Tx write routine, writes to Tx buffer
void acia_print( uint8_t const * str);
void main(void)
{
uint8_t chr;
acia_print("Hello World\r\n");
printf("Hello World - Again\r\n");
for(;;)
{
if (acia_pollc())
{
chr = acia_getc();
acia_putc(chr);
}
}
}
void acia_print( const uint8_t * str)
{
int16_t i = 0;
size_t stringlength;
stringlength = strlen((char *)str);
while(i < stringlength)
acia_putc( str[i++]);
}
I have some ideas about how to instantiation devices so maybe a proper solution can be tried when that's hacked out in the next day or two.
--
You received this message because you are subscribed to the Google Groups "RC2014-Z80" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rc2014-z80+unsubscribe@googlegroups.com.
To post to this group, send email to rc201...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/159afe94-9391-4daf-86f9-cfb4e8360cf1%40googlegroups.com.
I don't have permission to send a pull request so I've zipped up the rc2014 directory again:
https://drive.google.com/open?id=0B6XhJJ33xpOWdy1OSDhSZlZPYlEI have added you to the repo as a collaborator, so you can commit directly now.I' pushed the latest changes to the repo, so I think that is close to final.But some questions below.Some of the changes:
Good news! We are close, very close!
One of the data fields I added early was an exclusion flag for the Tx. I don't know whether the stdio library automatically prevents multiple Tx threads from overwriting each other, but I find it a cheap way to prevent garbled messages when using freeRTOS (cheaper than a RTOS Semaphore, anyway). Should I add code to manage mutual exclusion on Tx? Or does that come for free with z88dk stdio?
Just looking at the code, I'm concerned by the acia_init routine. It doesn't preserve the af registers, yet it uses them. Also, it calls the acia_reset routine, that doesn't preserve af or hl, yet it in turn calls the versions of flush_rx flush_tx that don't preserve registers (this was moved out of the non interrupt protected versions of the code). Could this be an issue?
extern uint8_t acia_putc(uint8_t) __preserves_regs(b,c,d,e,iyl,iyh) __z88dk_fastcall; // Tx write routine, writes to Tx buffer
(try to compare the asm output with that preserve regs attribute there and not; most often the compiler can make best use of bc and de being unchanged)It looks like my "raw" drivers have also been adapted to no register preservation. I guess that means that they will also break things if called directly.I think that's probably the cause of my "echo" routine not working.
Another question that I'd pose is how the interface between the "device" and the "driver" works.
I would like to write some multi character buffer based puts(), and gets() kind of drivers.But if stdio can't use these interfaces, then it won't be worth doing. What do you think?
rc_00_output_acia:
cp OCHAR_MSG_PUTC
jp nz, character_00_output ; forward other messages to library
rc_00_output_acia_ochar_msg_putc:
; enter : c = char
; exit : carry set if error
; can use : af, bc, de, hl, af'
block_loop:
ld l,c
call _acia_putc
dec l
jr z, block_loop ; if Tx buffer is full
ret ; carry is reset
One of the data fields I added early was an exclusion flag for the Tx. I don't know whether the stdio library automatically prevents multiple Tx threads from overwriting each other, but I find it a cheap way to prevent garbled messages when using freeRTOS (cheaper than a RTOS Semaphore, anyway). Should I add code to manage mutual exclusion on Tx? Or does that come for free with z88dk stdio?It looks like there is a spinlock definition in the m4 character driver. defb 0xfe ; atomic spinlock Could this be the way to provide mutual exclusion for multithreaded applications?
Just looking at the code, I'm concerned by the acia_init routine. It doesn't preserve the af registers, yet it uses them. Also, it calls the acia_reset routine, that doesn't preserve af or hl, yet it in turn calls the versions of flush_rx flush_tx that don't preserve registers (this was moved out of the non interrupt protected versions of the code). Could this be an issue?
extern uint8_t acia_putc(uint8_t) __preserves_regs(b,c,d,e,iyl,iyh) __z88dk_fastcall; // Tx write routine, writes to Tx buffer(try to compare the asm output with that preserve regs attribute there and not; most often the compiler can make best use of bc and de being unchanged)
So there is no issue with C calling asm functions; the only requirement is that the asm implements the promised parameter linkage and returns values properly in a subset of DEHL.
It looks like my "raw" drivers have also been adapted to no register preservation. I guess that means that they will also break things if called directly.I think that's probably the cause of my "echo" routine not working.
They should still work fine from C.
Another question that I'd pose is how the interface between the "device" and the "driver" works.I would like to write some multi character buffer based puts(), and gets() kind of drivers.But if stdio can't use these interfaces, then it won't be worth doing. What do you think?
The sole interface from stdio to the device is through the driver using the small set of messages defined at ( http://www.z88dk.org/wiki/doku.php?id=temp:front#device_drivers ). You can think of those messages as function identifiers (not really function pointers since addresses are not being sent).
stdio does try to send entire buffers and you can implement buffer writes to the device by implementing the stdio messages directly rather than passing the responsibility to the library driver.
However, you can instead service the STDIO_MSG_WRIT message directly in this driver and send the entire string in one go. The driver will be a little bit faster as a result. It is up to you if you want to do that.
I also always make sure that the device is accessible outside of stdio, for example the low level acia_* routines you've written. Although the z88dk stdio implementation is about as light as it gets, the memory space is still tight, so people will sometimes prefer or even need to use the low level interface to gain in memory. If you think a low level puts and gets would work well in the absence of stdio, I'd add it. No one has to use it and if they don't use it, it doesn't cost anything.
One of the data fields I added early was an exclusion flag for the Tx. I don't know whether the stdio library automatically prevents multiple Tx threads from overwriting each other, but I find it a cheap way to prevent garbled messages when using freeRTOS (cheaper than a RTOS Semaphore, anyway). Should I add code to manage mutual exclusion on Tx? Or does that come for free with z88dk stdio?
stdio is preparing for multi-threading but it's not ready yet. The C11 standard has specified a number of multi-threading related functions and the z88dk c lib has mutexes and spinlocks tentatively implemented (see the libsrc/_DEVELOPMENT/threads directory) to implement those functions but since there is no thread scheduling code in the library there is nothing to do if a thread is supposed to block.
Maybe I should spend some time on that end of things if you are considering multi-threading and non-blocking i/o. Or if you'd like to contribute that's ok too :)
However, you can instead service the STDIO_MSG_WRIT message directly in this driver and send the entire string in one go. The driver will be a little bit faster as a result. It is up to you if you want to do that.Ok. I now understand a little better what the stdio library is expecting. So I'll have a go at the appropriate puts() and gets() functions for stdio.
I was thinking the other way around. Not the need to expose puts() and gets(), but rather could stdio use these functions to be faster?I think you've answered yes to that question. So yes, I'll have a go.
Maybe I should spend some time on that end of things if you are considering multi-threading and non-blocking i/o. Or if you'd like to contribute that's ok too :)I have a minimal AVR freeRTOS repo, which might be useful to look at the way that TCBs etc are implemented in freeRTOS. I think it would be pretty simple to implement this in C for z88dk and then performance profile it to see which parts need to be moved to ASM over time.
It looks like my "raw" drivers have also been adapted to no register preservation. I guess that means that they will also break things if called directly.I think that's probably the cause of my "echo" routine not working.
They should still work fine from C.Oh? That's disappointing. ;-(I thought I'd found the issue why the test didn't work... back to bug hunt.
#include <stdio.h>
void main(void)
{
uint8_t chr;
printf("Hello World\r\n");
while ((chr=getchar()) != EOF) /* read/print "abcde" from stdin */
printf("%c", chr);
}Phillip, just tell me when you want your changes being referenced (or included) in the official RC2014 repository.
--
You received this message because you are subscribed to the Google Groups "RC2014-Z80" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rc2014-z80+unsubscribe@googlegroups.com.
To post to this group, send email to rc201...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/CAFC0-0XPFBiA9REnmuJJAOgqHnhJZZPyRuyG7V43c_v4M%3DLoAg%40mail.gmail.com.
You received this message because you are subscribed to a topic in the Google Groups "RC2014-Z80" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/rc2014-z80/-4jOOxYXGEo/unsubscribe.
To unsubscribe from this group and all its topics, send an email to rc2014-z80+unsubscribe@googlegroups.com.
To post to this group, send email to rc201...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/CAK%2B%3DWr-B%3Dx1TByBXpZcMr0xQKBQ%3DLWSV2Bd0HAP%3DBK4JJR-zHw%40mail.gmail.com.
Could someone try this test.hex file on a real rc2014, please?It is implementing this C code below with the C stdio implementation from this repository.#include <stdio.h>
void main(void)
{
uint8_t chr;
printf("Hello World\r\n");
while ((chr=getchar()) != EOF) /* read/print "abcde" from stdin */
printf("%c", chr);
}It is working on the z80-machine emulator, but the Tx interrupt is not behaving the same as on a real machine.Any feedback welcome.
extern uint8_t acia_pollc(void) __preserves_regs(b,c,d,e,iyl,iyh); // Rx polling routine, checks Rx buffer fullnessextern uint8_t acia_getc(void) __preserves_regs(b,c,d,e,iyl,iyh); // Rx receive routine, from Rx bufferextern uint8_t acia_peekc(void) __preserves_regs(b,c,d,e,iyl,iyh); // Rx peek routine, reads Rx without removing it from bufferextern uint8_t acia_putc(uint8_t) __preserves_regs(b,c,d,e,iyl,iyh) __z88dk_fastcall; // Tx write routine, writes to Tx buffer
for(;;)
{
if (acia_pollc() != 0)
{
chr = acia_getc();
acia_putc( chr);
}
}rc_00_input_acia:
cp ICHAR_MSG_GETC
jr nz, no_match_0
rc_00_input_acia_ichar_msg_getc:
; exit : a = keyboard char after character set translation
; carry set on error, hl = 0 (stream error) or -1 (eof)
;
; can use : af, bc, de, hl
block_loop:
call _acia_pollc ; check whether any characters are in Rx buffer
jr nc, block_loop ; if Rx buffer is empty
call _acia_getc
; l = ascii code
ld a,l
cp CHAR_CTRL_Z
jp z, error_mc ; generate EOF (ctrl-z is from cp/m)
or a ; reset carry to indicate no error
ret
On Tuesday, October 4, 2016 at 5:32:22 AM UTC-6, phillip.stevens wrote:Could someone try this test.hex file on a real rc2014, please?It is implementing this C code below with the C stdio implementation from this repository.#include <stdio.h>
void main(void)
{
uint8_t chr;
printf("Hello World\r\n");
while ((chr=getchar()) != EOF) /* read/print "abcde" from stdin */
printf("%c", chr);
}It is working on the z80-machine emulator, but the Tx interrupt is not behaving the same as on a real machine.Any feedback welcome.
For devices and their low-level code I'm looking at making templates out of them using m4. This will make it possible to create multiple instances of devices mapped to different ports inside a target configuration file. This means you could define a variable system by plugging things in like lego.
The templatization does mean all the low-level interface code will be duplicated for each device with different names. I may try another method that doesn't duplicate the code later but I think the template method would be most often preferred since it will not slow down the code.
But now the bad news. I still haven't been able to get the linkage to the STDIO to work properly.I'm afraid that I'm a bit out of my depth. The intermediate routines look like they're right.I did change the input routine to use _acia_pollc to avoid needless IO reads from the ACIA device. But I think its ok.rc_00_input_acia:
cp ICHAR_MSG_GETC
jr nz, no_match_0
rc_00_input_acia_ichar_msg_getc:
; exit : a = keyboard char after character set translation
; carry set on error, hl = 0 (stream error) or -1 (eof)
;
; can use : af, bc, de, hl
block_loop:
call _acia_pollc ; check whether any characters are in Rx buffer
jr nc, block_loop ; if Rx buffer is empty
call _acia_getc
; l = ascii code
ld a,l
cp CHAR_CTRL_Z
jp z, error_mc ; generate EOF (ctrl-z is from cp/m)
or a ; reset carry to indicate no error
ret
On Sunday, November 6, 2016 at 5:20:53 AM UTC-7, phillip.stevens wrote:But now the bad news. I still haven't been able to get the linkage to the STDIO to work properly.I'm afraid that I'm a bit out of my depth. The intermediate routines look like they're right.I did change the input routine to use _acia_pollc to avoid needless IO reads from the ACIA device. But I think its ok.
It doesn't look like there's anything wrong with that. I'll take another look when I am home tonight.
Checking into this more. It is the printf() statement that doesn't work properly.Character input through getchar() works fine.The symptom for printf() failure is printing more than one character fails.When printing a string the first character will be output properly, but then no more.
The symptom for printf() failure is printing more than one character fails.When printing a string the first character will be output properly, but then no more.
The carry flag is used to indicate device error if the driver is unable to output a char. It looks like the carry flag can be set at the end of acia_putc even after a successful putc:
target/rc2014/driver/character/rc_00_output_acia.asm
.....
rc_00_output_acia_ochar_msg_putc:
; enter : c = char
; exit : carry set if error
; can use : af, bc, de, hl, af'
block_loop:
ld l,c
call _acia_putc
dec l
jr z, block_loop ; if Tx buffer is full
ret ; carry is reset
Add "or a" right before the ret.
I think that should do it.