6502 Emulator on GD32F103

Boards based on the GigaDevices GD32F103 microcontroller
Post Reply
User avatar
ahull
Posts: 1630
Joined: Mon Apr 27, 2015 11:04 pm
Location: Sunny Scotland
Contact:

6502 Emulator on GD32F103

Post by ahull » Sun Sep 20, 2015 5:12 pm

First, a big thank you to Roger, who popped a GD32F103 bard in the post while he was visiting the UK. :D
Image
The first thing I thought I would try, was the 6502 emulator, I had no particular reason, other than that this was the last thing I was playing with when last I had some spare time, and therefore that is what the IDE loaded.

It *almost* compiles with the latest version of Rogers repo (I just did a git pull), however the compilation dies with ...

Code: Select all

/home/ahull/.arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-gcc -c -g -Os -DDEBUG_LEVEL=DEBUG_NONE -MMD -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -DBOARD_generic_GD32f103c -DVECT_TAB_ADDR=0x8002000 -DERROR_LED_PORT=GPIOC -DERROR_LED_PIN=13 -mcpu=cortex-m3 -DF_CPU=120000000L -DARDUINO=10605 -DARDUINO_GENERIC_GD32F103C -DARDUINO_ARCH_GD32F1 -DSERIAL_USB -DGENERIC_BOOTLOADER -DMCU_STM32F103CB -mthumb -march=armv7-m -D__STM32F1__ -I/home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/system/libmaple -I/home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/system/libmaple/include -I/home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/system/libmaple/stm32f1/include -I/home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/system/libmaple/usb/stm32f1 -I/home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/system/libmaple/usb/usb_lib -I/home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/cores/maple -I/home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/variants/generic_GD32f103c /tmp/build8631056794938416052.tmp/cpu.c -o /tmp/build8631056794938416052.tmp/cpu.c.o 
/home/ahull/.arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-g++ -c -g -Os -DDEBUG_LEVEL=DEBUG_NONE -MMD -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -DBOARD_generic_GD32f103c -DVECT_TAB_ADDR=0x8002000 -DERROR_LED_PORT=GPIOC -DERROR_LED_PIN=13 -mcpu=cortex-m3 -DF_CPU=120000000L -DARDUINO=10605 -DARDUINO_GENERIC_GD32F103C -DARDUINO_ARCH_GD32F1 -DSERIAL_USB -DGENERIC_BOOTLOADER -DMCU_STM32F103CB -mthumb -march=armv7-m -D__STM32F1__ -DMCU_STM32F103CB -mthumb -march=armv7-m -D__STM32F1__ -I/home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/system/libmaple -I/home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/system/libmaple/include -I/home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/system/libmaple/stm32f1/include -I/home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/system/libmaple/usb/stm32f1 -I/home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/system/libmaple/usb/usb_lib -I/home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/cores/maple -I/home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/variants/generic_GD32f103c /tmp/build8631056794938416052.tmp/arduino_6502.cpp -o /tmp/build8631056794938416052.tmp/arduino_6502.cpp.o 
In file included from /home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/cores/maple/boards.h:37:0,
                 from /home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/cores/maple/wirish.h:53,
                 from /home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/cores/maple/Arduino.h:30,
                 from arduino_6502.ino:5:
/home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/system/libmaple/include/libmaple/libmaple_types.h:60:0: warning: "__always_inline" redefined [enabled by default]
 #define __always_inline inline __attribute__((always_inline))
 ^
In file included from /home/ahull/.arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/arm-none-eabi/include/string.h:12:0,
                 from /home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/cores/maple/wirish.h:45,
                 from /home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/cores/maple/Arduino.h:30,
                 from arduino_6502.ino:5:
/home/ahull/.arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/lib/gcc/arm-none-eabi/4.8.3/include-fixed/sys/cdefs.h:368:0: note: this is the location of the previous definition
 #define __always_inline __attribute__((__always_inline__))
 ^
In file included from /home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/cores/maple/boards.h:37:0,
                 from /home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/cores/maple/wirish.h:53,
                 from /home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/cores/maple/Arduino.h:30,
                 from arduino_6502.ino:5:
/home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/system/libmaple/include/libmaple/libmaple_types.h:61:0: warning: "__unused" redefined [enabled by default]
 #define __unused __attribute__((unused))
 ^
In file included from /home/ahull/.arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/arm-none-eabi/include/string.h:12:0,
                 from /home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/cores/maple/wirish.h:45,
                 from /home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/cores/maple/Arduino.h:30,
                 from arduino_6502.ino:5:
/home/ahull/.arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/lib/gcc/arm-none-eabi/4.8.3/include-fixed/sys/cdefs.h:257:0: note: this is the location of the previous definition
 #define __unused __attribute__((__unused__))
 ^
In file included from arduino_6502.ino:5:0:
/home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/cores/maple/Arduino.h:42:21: fatal error: variant.h: No such file or directory
 #include "variant.h"
                     ^
compilation terminated.
Error compiling.
.. so I thought I'd share this and see if I am missing something obvious, before I start diving down too many rabbit holes.

EDIT: My STM32Blink sketch compile dies in a similar manner...

Code: Select all

/home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/cores/maple/boards.h:39:25: fatal error: board/board.h: No such file or directory
 #include <board/board.h>
 
.. leading me to suspect perhaps missing files in the repo, or Windows paths somewhere that are tripping up my Linux build.
Last edited by ahull on Wed Sep 23, 2015 7:49 pm, edited 1 time in total.
- Andy Hull -

User avatar
ahull
Posts: 1630
Joined: Mon Apr 27, 2015 11:04 pm
Location: Sunny Scotland
Contact:

Re: 6502 Emulator on GD32F103

Post by ahull » Tue Sep 22, 2015 8:49 am

Now there's yer prablem....
The compiler looks for....

/home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/GD32F1/variants/generic_GD32f103c

... but the folder is called ..

generic_gd32f103c

rename the folder and....

/home/ahull/.arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-objcopy -O binary /tmp/build8259259394612873790.tmp/sketch_sep21a.cpp.elf /tmp/build8259259394612873790.tmp/sketch_sep21a.cpp.bin

Sketch uses 11,964 bytes (18%) of program storage space. Maximum is 65,536 bytes.
Global variables use 2,560 bytes of dynamic memory.


Result!
- Andy Hull -

User avatar
ahull
Posts: 1630
Joined: Mon Apr 27, 2015 11:04 pm
Location: Sunny Scotland
Contact:

Re: 6502 Emulator on GD32F103

Post by ahull » Tue Sep 22, 2015 9:38 am

However.... now it compiles, but when I attempt to upload, I get...

/home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/tools/linux/maple_upload ttyACM3 2 1EAF:0003 /tmp/build8259259394612873790.tmp/arduino_6502.cpp.bin
java.io.IOException: Cannot run program "/home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/tools/linux/maple_upload": error=2, No such file or directory


.. so close, but no cigar.
- Andy Hull -

User avatar
ahull
Posts: 1630
Joined: Mon Apr 27, 2015 11:04 pm
Location: Sunny Scotland
Contact:

Re: 6502 Emulator on GD32F103

Post by ahull » Tue Sep 22, 2015 9:44 am

That maple_upload script exists but is broken because it has been edited in Windows and the Unix line endings screwed up.

Fixed by passing it through dos2unix

Code: Select all

dos2unix /home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/tools/linux/maple_upload
dos2unix: converting file /home/ahull/PersonalApps/Arduino.cc/beta/arduino-nightly/hardware/Arduino_STM32/tools/linux/maple_upload to Unix format ...
.. and now it uploads without any problems.....

Code: Select all

6502 EhBASIC [C]old/[W]arm ?
6502 EhBASIC [C]old/[W]arm ?
6502 EhBASIC [C]old/[W]arm ?
6502 EhBASIC [C]old/[W]arm ?

Memory size ? 

15615 Bytes free

Enhanced BASIC 2.22

Ready
Furthermore... it runs the emulator with the GD core running at 120 MHz. :D
- Andy Hull -

User avatar
ahull
Posts: 1630
Joined: Mon Apr 27, 2015 11:04 pm
Location: Sunny Scotland
Contact:

Re: 6502 Emulator on GD32F103

Post by ahull » Tue Sep 22, 2015 12:34 pm

I also tried my very messy STM32F103 RTC test code below. I fitted a RTC battery to the board *without* blowing the battery up this time ;)

Code: Select all

// SeralCommand -> https://github.com/kroimon/Arduino-SerialCommand.git
#include "RTClock.h"
RTClock rt (RTCSEL_LSE); // initialise
uint32 tt;

// Define the Base address of the RTC  registers (battery backed up CMOS Ram), so we can use them for config of touch screen and other calibration.
// See http://stm32duino.com/viewtopic.php?f=15&t=132&hilit=rtc&start=40 for a more details about the RTC NVRam
// 10x 16 bit registers are available on the STM32F103CXXX more on the higher density device.

#define BKP_REG_BASE   (uint32_t *)(0x40006C00 +0x04)

// Defined for power and sleep functions pwr.h and scb.h
#include <libmaple/pwr.h>
#include <libmaple/scb.h>


// Time library - https://github.com/PaulStoffregen/Time
#include "Time.h"
#define TZ    "BST"

int globAlmCnt = 0;
int globOvCnt = 0;
int globSecCnt = 0;
int specAlmCnt = 0;
int lastGlobAlmCnt = -1;
int lastSpecAlmCnt = -1;

// void rtc_sec_intr() { if (rtc_is_second()) globSecCnt++; }
void rtc_ovf_intr() {
  if (rtc_is_overflow()) globOvCnt++;
}
void rtc_glob_alm_intr() {
  if (rtc_is_alarm()) globAlmCnt++;
}
void rtc_spec_alm_intr() {
  if (rtc_is_alarm()) specAlmCnt++;
}

// Create USB serial port
USBSerial serial_debug;

// SeralCommand -> https://github.com/kroimon/Arduino-SerialCommand.git
#include <SerialCommand.h>

// Create Serial Command Object.
SerialCommand sCmd;

// Sunrise stuff
#include <math.h>
//#define PI 3.1415926
#define ZENITH -.83
/*
#define Stirling_Latitude 56.138607900000000000
#define Stirling_Longitude -3.944080100000064700
*/

// Lat long for your location
#define HERE_LATITUDE  56.1386079
#define HERE_LONGITUDE -3.9440801

// Somne sane ish defaults in case the RTC battery has been disconnected or run flat.
int thisYear = 2015;
int thisMonth = 6;
int thisDay = 29;
int lastDay = 0;
int thisHour = 12;
int thisMinute = 0;
int thisSecond = 0;

// Set to a recent value - 29th June 2015 12:25 (just after mid day)
#define RESET_TO_TIMESTAMP 1435580711

float thisLat = HERE_LATITUDE;
float thisLong = HERE_LONGITUDE;
int thisLocalOffset = 0;
int thisDaylightSavings = 1;

// Pin for Relay switched by alarm
#define RELAY_1 PC14
bool relayOneOn =  false;
#define RELAY_2 PC13
bool relayTwoOn = false;

void setup() {


  // Set up the Relay pins
  pinMode(RELAY_1, OUTPUT);
  pinMode(RELAY_2, OUTPUT);
  // Open the serial port for debug messages
  serial_debug.begin();

  // Check time, and set a sensible time, if this board has no battery, or the time is unset
  tt = rt.getTime();
  // Check to see if we are close to the epoch, and if so, bad things must have happened to the RTC backup power domain.
  if ( tt < 1024 )
  {
    rt.setTime(RESET_TO_TIMESTAMP);
  }

  sCmd.addCommand("timestamp",   setCurrentTime);          // Set the current time based on a unix timestamp
  sCmd.addCommand("date",        serialCurrentTime);       // Show the current time from the RTC
  sCmd.addCommand("sleep",       sleepMode);               // Experimental - puts system to sleep
  sCmd.setDefaultHandler(unrecognized);                    // Handler for command that isn't matched  (says "Unknown")
  sCmd.clearBuffer();

  rtc_init(RTCSEL_LSI);
  rtc_set_prescaler_load(0x7fff);
  rtc_set_count(0);

  rtc_attach_interrupt(RTC_SECONDS_INTERRUPT, rtc_sec_intr);
  rtc_attach_interrupt(RTC_OVERFLOW_INTERRUPT, rtc_ovf_intr); // expected every 128000 seconds
  rtc_attach_interrupt(RTC_ALARM_GLOBAL_INTERRUPT, rtc_glob_alm_intr);
  rtc_attach_interrupt(RTC_ALARM_SPECIFIC_INTERRUPT, rtc_spec_alm_intr);
  //rt.attachSecondsInterrupt(secondsISR);
  // put your setup code here, to run once:


}

void loop() {
  // Setting the clock from the serial port is a matter of doing this in Linux...
  // NOW=$(date --date "+1hour" +"%s"); echo -e "\n\ntimestamp $NOW\n\n" >/dev/ttyACMx
  // where /dev/ttyACMx is the tty of the STM board. In my case /dev/ttyACM3
  // You can't do this if something else, for example tha arduino Serial Monitor, is attached to the port.

  sCmd.readSerial();     // Process serial commands

  tt = rt.getTime();
  thisYear = year(tt);
  thisMonth = month(tt);
  thisDay = day(tt);
  thisHour = hour(tt);
  thisMinute = minute(tt);
  thisSecond = second(tt);

  serial_debug.print("# Global Seconds Interrupts[ ");
  serial_debug.print(globSecCnt);
  serial_debug.println(" ]");
  //serialCurrentTime();
  /*
  delay(998);
  relayOneOn = !relayOneOn;
  relayTwoOn = !relayTwoOn;
  digitalWrite(RELAY_1, relayOneOn);
  digitalWrite(RELAY_2, relayTwoOn);
  */
  delay(500);
  //relayOneOn = !relayOneOn;
  //digitalWrite(RELAY_1, relayOneOn);
  //relayTwoOn = !relayTwoOn;
  // digitalWrite(RELAY_2, relayTwoOn);


  // put your main code here, to run repeatedly:
  //sleepMode();

}

void setCurrentTime() {
  char *arg;
  arg = sCmd.next();
  String thisArg = arg;
  serial_debug.print("# Time command [");
  serial_debug.print(thisArg.toInt() );
  serial_debug.println("]");
  setTime(thisArg.toInt());
  time_t tt = now();
  rt.setTime(tt);
  // serialCurrentTime();
}

void serialCurrentTime() {
  serial_debug.print("# Current time - ");
  if (hour(tt) < 10) {
    serial_debug.print("0");
  }
  serial_debug.print(hour(tt));
  serial_debug.print(":");
  if (minute(tt) < 10) {
    serial_debug.print("0");
  }
  serial_debug.print(minute(tt));
  serial_debug.print(":");
  if (second(tt) < 10) {
    serial_debug.print("0");
  }
  serial_debug.print(second(tt));
  serial_debug.print(" ");
  serial_debug.print(day(tt));
  serial_debug.print("/");
  serial_debug.print(month(tt));
  serial_debug.print("/");
  serial_debug.print(year(tt));
  serial_debug.println("("TZ")");

}

void unrecognized(const char *command) {
  serial_debug.print("# Unknown Command.[");
  serial_debug.print(command);
  serial_debug.println("]");
}

void sleepMode()
{
  serial_debug.println("# Nighty night!");
  // Set PDDS and LPDS bits for standby mode, and set Clear WUF flag (required per datasheet):
  PWR_BASE->CR |= PWR_CR_CWUF;
  PWR_BASE->CR |= PWR_CR_PDDS;

  // set sleepdeep in the system control register
  SCB_BASE->SCR |= SCB_SCR_SLEEPDEEP;

  // Now go into stop mode, wake up on interrupt
  // disableClocks();
  asm("wfi");
}

void rtc_sec_intr()
{
  if (rtc_is_second()) {
    globSecCnt++;
    if (!(globSecCnt % 10 ) ) {
      relayOneOn = !relayOneOn;
      relayTwoOn = !relayTwoOn;
      digitalWrite(RELAY_1, relayOneOn);
      digitalWrite(RELAY_2, relayTwoOn);
      // serialCurrentTime();
    }
  }
}

Code: Select all

...
# Global Seconds Interrupts[ 33 ]
# Global Seconds Interrupts[ 33 ]
# Global Seconds Interrupts[ 34 ]
# Global Seconds Interrupts[ 34 ]
# Global Seconds Interrupts[ 35 ]
# Global Seconds Interrupts[ 35 ]
# Current time - 13:36:14 22/9/2015(BST)
# Global Seconds Interrupts[ 36 ]
# Global Seconds Interrupts[ 36 ]
# Global Seconds Interrupts[ 37 ]
# Global Seconds Interrupts[ 37 ]
# Global Seconds Interrupts[ 38 ]
# Global Seconds Interrupts[ 38 ]
# Global Seconds Interrupts[ 39 ]
# Global Seconds Interrupts[ 39 ]
# Global Seconds Interrupts[ 40 ]
...
It appears to work, however I haven't tested the relay board yet, but since the LED blinks, I have no reason to suspect there will be any problems.
- Andy Hull -

User avatar
ahull
Posts: 1630
Joined: Mon Apr 27, 2015 11:04 pm
Location: Sunny Scotland
Contact:

Re: 6502 Emulator on GD32F103

Post by ahull » Tue Sep 22, 2015 12:43 pm

In conclusion - there may still be a bit of work to do, but over all things appear to work.

The board is fast, and the bootloader has performed flawlessly, I haven't had to connect the serial or ST-Link board to the thing to fix any of my screw ups yet (give me time :twisted: ).

The build quality may be a little less than perfect, with a few tin whiskers and some less than stellar soldering visible when I inspected the GD pins, but other than that, I'm impressed. For the price, its a certain winner.

Hats of to Roger once again. :D
- Andy Hull -

Post Reply