6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Mon May 20, 2024 2:56 pm

All times are UTC




Post new topic Reply to topic  [ 2 posts ] 
Author Message
PostPosted: Sat Apr 02, 2022 2:53 pm 
Offline

Joined: Sat Apr 02, 2022 2:25 pm
Posts: 1
*** EDIT ***
It works now -- once I rebuilt the whole project (including asm parts) with the --cpu=65c02 flag and rebuilt the library (I'd made a few changes to the crt0.s to put the interrupt service routine back, which I had disabled while debugging)

I shall leave this here in case someone else runs into this so hopefully their Google search will hit it
*** END EDIT ***

I'm building an FPGA based SoC, inside a Lattice (formerly SiliconBlue) ICE40 FPGA. I'm using the 65c02 core from https://github.com/hoglet67/verilog-6502 (which is itself a fork of the 6502 found here https://github.com/Arlet/verilog-6502 ). The whole shebang is running off the primary oscillator which is at 25 MHz.

It does seem to work OK; so far I'm using block ram and have a 9600 baud UART implemented, and some LEDs for status:

LEDs - at 0xE000
UART - 0xE001 (transmit/receive byte), 0xE002 (transmit busy), receive byte interrupts
Interrupt status byte - 0xE003 (UART and timer can set a bit here when they cause an interrupt)
32-bit timer - 0xE004-E007

Internal FPGA block RAM is from 0xF000-0xFFFF and 0x0000 to 0x0FFF, external static ram at 0x1000 and up.

I followed the steps in https://cc65.github.io/doc/customizing.html to create the new platform.

I'm not very experienced with the 65C02 - nearly all of my 8-bit work has been Z80 based, but I want to learn about the 6502 as well as learn Verilog, and it seems to make better use of memory bandwidth than the Z80 (especially when you've got very fast block ram to hand that doesn't need any wait states). I mostly want to use C when I need to manipulate strings, as this is pretty tedious and slow to write in asm, and someone's already written the code anyway.

However, sprintf doesn't seem to work right. The output I expect would be an infinite loop of:

val1 = 123, val2 = 159

Instead I get

val1 = , val2 =

The code in main() is:

Code:
#include <stdlib.h>
#include <stdio.h>

#include "uart.h"

int main() {
   int val1 = 123;
   int val2 = 345;
   char buf[128];
   sprintf(buf, "val1 = %d, val2 = %x\r\n", val1, val2);

   while(1) {
      uart_tx(buf);
   }

   return 0;
}


The code in uart_tx.s is:

Code:
.export     _uart_tx
.exportzp   _uart_data: near

.define     TX_BYTE $e001
.define     TX_IDLE $e002

.zeropage
_uart_data: .res 2, $00       ; Reserve zero page pointer

.segment "CODE"

.proc _uart_tx: near

   ; store the pointer
   sta _uart_data
   stx _uart_data + 1
   ldy #0

   ; busy wait until the UART is idle
@rdy_loop:
   lda TX_IDLE
   bne @rdy_loop

   ; send a character, exit if zero terminator
   lda (_uart_data), y
   beq @done
   sta TX_BYTE
   iny
   jmp @rdy_loop

@done:
   rts

.endproc


The linker cfg is this:

Code:
MEMORY {
   ZP:      start =     $0, size = $100, type = rw, define = yes;
   BUFFERS: start =   $200, size = $0100, type = rw, define = yes;
   RAM:     start =   $300, size = $0C00, define = yes;
   ROM:     start =  $F000, size = $1000, file = %O;
}

SEGMENTS {
    ZEROPAGE: load = ZP,  type = zp,  define   = yes;
    DATA:     load = ROM, type = rw,  define   = yes, run = RAM;
    BSS:      load = RAM, type = bss, define   = yes;
    HEAP:     load = RAM, type = bss, optional = yes;
    STARTUP:  load = ROM, type = ro;
    ONCE:     load = ROM, type = ro,  optional = yes;
    CODE:     load = ROM, type = ro;
    RODATA:   load = ROM, type = ro;
    VECTORS:  load = ROM, type = ro,  start    = $FFFA;
}

FEATURES {
    CONDES:    segment = STARTUP,
               type    = constructor,
               label   = __CONSTRUCTOR_TABLE__,
               count   = __CONSTRUCTOR_COUNT__;
    CONDES:    segment = STARTUP,
               type    = destructor,
               label   = __DESTRUCTOR_TABLE__,
               count   = __DESTRUCTOR_COUNT__;
}

SYMBOLS {
    # Define the stack size for the application
    __STACKSIZE__:   type = weak, value = $0200;
}


Incidentally, are there any good resources (google has failed me in this respect) to find out how to make a more comprehensive custom platform - in other words, what functions are absolutely required to support the C libraries? Bear in mind I don't have a ROM of any sort (basically, the output binary from cc65 is my ROM)


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 02, 2022 3:48 pm 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1930
Location: Sacramento, CA, USA
Welcome, Mack. I'm glad you got it figured out.

While not perfect, the 65xx family has an excellent cycle/instruction ratio, at least compared to its peers.

_________________
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: