diff --git a/Makefile b/Makefile index d9e36d5..72ee0c9 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ OBJS = armc-start.o armc-cstartup.o armc-cstubs.o armc-cppstubs.o \ rpi-gpio.o rpi-interrupts.o cache.o ff.o interrupt.o Keyboard.o performance.o \ Drive.o Pi1541.o DiskImage.o iec_bus.o iec_commands.o m6502.o m6522.o \ gcr.o prot.o lz.o emmc.o diskio.o options.o Screen.o SSD1306.o ScreenLCD.o \ - Timer.o FileBrowser.o DiskCaddy.o ROMs.o InputMappings.o xga_font_data.o m8520.o wd177x.o Pi1581.o + Timer.o FileBrowser.o DiskCaddy.o ROMs.o InputMappings.o xga_font_data.o m8520.o wd177x.o Pi1581.o SpinLock.o SRCDIR = src OBJS := $(addprefix $(SRCDIR)/, $(OBJS)) diff --git a/src/SpinLock.cpp b/src/SpinLock.cpp new file mode 100644 index 0000000..af9a27d --- /dev/null +++ b/src/SpinLock.cpp @@ -0,0 +1,76 @@ +// +// spinlock.cpp +// +// Circle - A C++ bare metal environment for Raspberry Pi +// Copyright (C) 2015 R. Stange +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +#include "SpinLock.h" + +//#ifdef HAS_MULTICORE + +bool SpinLock::s_bEnabled = true; + +SpinLock::SpinLock() + : m_bLocked(false) +{ +} + +SpinLock::~SpinLock(void) +{ +} + +void SpinLock::Acquire(void) +{ + if (s_bEnabled) + { + // See: ARMv7-A Architecture Reference Manual, Section D7.3 + asm volatile + ( + "mov r1, %0\n" + "mov r2, #1\n" + "1: ldrex r3, [r1]\n" + "cmp r3, #0\n" + "wfene\n" + "strexeq r3, r2, [r1]\n" + "cmpeq r3, #0\n" + "bne 1b\n" + "dmb\n" + + : : "r" ((u32)&m_bLocked) + ); + } +} + +void SpinLock::Release(void) +{ + if (s_bEnabled) + { + // See: ARMv7-A Architecture Reference Manual, Section D7.3 + asm volatile + ( + "mov r1, %0\n" + "mov r2, #0\n" + "dmb\n" + "str r2, [r1]\n" + "dsb\n" + "sev\n" + + : : "r" ((u32)&m_bLocked) + ); + } +} + +//#endif diff --git a/src/SpinLock.h b/src/SpinLock.h new file mode 100644 index 0000000..d00c586 --- /dev/null +++ b/src/SpinLock.h @@ -0,0 +1,46 @@ +// +// spinlock.h +// +// Circle - A C++ bare metal environment for Raspberry Pi +// Copyright (C) 2015 R. Stange +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +#ifndef SPINLOCK_H +#define SPINLOCK_H + +#include "types.h" + +//#ifdef HAS_MULTICORE + +class SpinLock +{ +public: + SpinLock(); + ~SpinLock(void); + + void Acquire(void); + void Release(void); + + static void Enable(void); + +private: + boolean m_bLocked; + + static bool s_bEnabled; +}; + +//#endif +#endif + diff --git a/src/main.cpp b/src/main.cpp index b662c37..dda50f0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,13 +41,14 @@ extern "C" #include "Pi1581.h" #include "FileBrowser.h" #include "ScreenLCD.h" +#include "SpinLock.h" #include "logo.h" #include "sample.h" #include "ssd_logo.h" unsigned versionMajor = 1; -unsigned versionMinor = 18; +unsigned versionMinor = 19; // When the emulated CPU starts we execute the first million odd cycles in non-real-time (ie as fast as possible so the emulated 1541 becomes responsive to CBM-Browser asap) // During these cycles the CPU is executing the ROM self test routines (these do not need to be cycle accurate) @@ -115,6 +116,8 @@ bool USBKeyboardDetected = false; bool selectedViaIECCommands = false; u16 pc; +SpinLock core0RefreshingScreen; + unsigned int screenWidth = 1024; unsigned int screenHeight = 768; int i2cLcdUseCBMChar = 0; @@ -504,14 +507,21 @@ void UpdateScreen() if (screenLCD) { + core0RefreshingScreen.Acquire(); + + IEC_Bus::WaitMicroSeconds(100); + screenLCD->PrintText(false, 0, 0, tempBuffer, 0, RGBA(0xff, 0xff, 0xff, 0xff)); // screenLCD->SetContrast(255.0/79.0*track); screenLCD->RefreshRows(0, 1); + + IEC_Bus::WaitMicroSeconds(100); + core0RefreshingScreen.Release(); } } } - else + else if (emulating == EMULATING_1581) { track = pi1581.wd177x.GetCurrentTrack(); if (track != oldTrack) @@ -523,9 +533,13 @@ void UpdateScreen() if (screenLCD) { + core0RefreshingScreen.Acquire(); + IEC_Bus::WaitMicroSeconds(100); screenLCD->PrintText(false, 0, 0, tempBuffer, 0, RGBA(0xff, 0xff, 0xff, 0xff)); // screenLCD->SetContrast(255.0/79.0*track); screenLCD->RefreshRows(0, 1); + IEC_Bus::WaitMicroSeconds(100); + core0RefreshingScreen.Release(); } } @@ -1069,6 +1083,9 @@ void emulator() IEC_Bus::LetSRQBePulledHigh(); + core0RefreshingScreen.Acquire(); + IEC_Bus::WaitMicroSeconds(100); + // workaround for occasional oled curruption if (screenLCD) screenLCD->ClearInit(0); @@ -1085,6 +1102,8 @@ void emulator() // else fileBrowser->RefeshDisplay(); // Just redisplay the current folder. + core0RefreshingScreen.Release(); + // resetWhileEmulating = false; selectedViaIECCommands = false; @@ -1215,8 +1234,6 @@ void emulator() // if (screenLCD) // screenLCD->ClearInit(0); - fileBrowser->ClearSelections(); - fileBrowser->RefeshDisplay(); // Just redisplay the current folder. IEC_Bus::WaitUntilReset(); //DEBUG_LOG("6502 resetting\r\n");