[ion] add millis() and micros() using systick on device

This commit is contained in:
Damien Nicolet
2018-08-09 00:59:13 +02:00
parent 9825c73238
commit 940270e78a
12 changed files with 107 additions and 7 deletions

View File

@@ -27,6 +27,8 @@ namespace Ion {
void msleep(long ms);
void usleep(long us);
extern "C" long millis();
extern "C" long micros();
const char * serialNumber();
const char * softwareVersion();

View File

@@ -3,3 +3,17 @@
void Ion::msleep(long ms) {
}
#include <chrono>
static auto start = std::chrono::high_resolution_clock::now();
long Ion::millis() {
auto elapsed = std::chrono::high_resolution_clock::now() - start;
return std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();
}
long Ion::micros() {
auto elapsed = std::chrono::high_resolution_clock::now() - start;
return std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count();
}

View File

@@ -28,7 +28,7 @@ ISR InitialisationVector[INITIALISATION_VECTOR_SIZE]
0, // DebugMonitor service routine,
0, // Reserved
0, // PendSV service routine,
0, // SysTick service routine
sysTick, // SysTick service routine
0, // WWDG service routine
0, // PVD service routine
0, // TampStamp service routine

View File

@@ -92,3 +92,9 @@ void start() {
abort();
}
volatile long millis_elapsed = 0;
void __attribute__((interrupt)) sysTick() {
millis_elapsed++;
}

View File

@@ -4,4 +4,6 @@
void start();
void abort();
void sysTick();
#endif

View File

@@ -39,6 +39,22 @@ void Ion::usleep(long us) {
}
}
extern volatile long millis_elapsed;
long Ion::millis() {
return millis_elapsed;
}
long Ion::micros() {
uint32_t c1 = CM4.STCVR()->getCURRENT();
uint32_t ms1 = millis_elapsed;
uint32_t c2 = CM4.STCVR()->getCURRENT();
uint32_t ms2 = millis_elapsed;
uint32_t load = CM4.STRVR()->getRELOAD();
return ((c1 > c2) ? ms1 : ms2) * 1000 + ((load - c2) * 1000) / (load + 1);
}
uint32_t Ion::crc32(const uint32_t * data, size_t length) {
bool initialCRCEngineState = RCC.AHB1ENR()->getCRCEN();
RCC.AHB1ENR()->setCRCEN(true);
@@ -184,9 +200,17 @@ void initPeripherals() {
#endif
Console::Device::init();
SWD::Device::init();
CM4.STRVR()->setRELOAD(11999);
CM4.STCVR()->setCURRENT(0);
CM4.STCSR()->setCLKSOURCE(CM4::STCSR::CLKSOURCE::AHB_DIV8);
CM4.STCSR()->setTICKINT(true);
CM4.STCSR()->setENABLE(true);
}
void shutdownPeripherals(bool keepLEDAwake) {
CM4.STCSR()->setENABLE(false);
SWD::Device::shutdown();
Console::Device::shutdown();
#if USE_SD_CARD

View File

@@ -19,6 +19,8 @@ void shutdownPeripherals(bool keepLEDAwake = false);
void initClocks();
void shutdownClocks(bool keepLEDAwake = false);
void sysTick();
/* The serial number is 96 bits long. That's equal to 16 digits in base 64. We
* expose a convenient "copySerialNumber" routine which can be called without
* using a static variable (and therefore without a .bss section). This is used

View File

@@ -40,14 +40,39 @@ public:
REGS_BOOL_FIELD(SLEEPDEEP, 2);
};
class STCSR : public Register32 {
public:
enum class CLKSOURCE : uint8_t {
AHB_DIV8 = 0,
AHB = 1
};
REGS_BOOL_FIELD(COUNTFLAG, 16);
REGS_TYPE_FIELD(CLKSOURCE, 2, 2);
REGS_BOOL_FIELD(TICKINT, 1);
REGS_BOOL_FIELD(ENABLE, 0);
};
class STRVR : public Register32 {
public:
REGS_FIELD(RELOAD, uint32_t, 23, 0);
};
class STCVR : public Register32 {
public:
REGS_FIELD(CURRENT, uint32_t, 23, 0);
};
constexpr CM4() {};
REGS_REGISTER_AT(VTOR, 0x08);
REGS_REGISTER_AT(AIRCR, 0x0C);
REGS_REGISTER_AT(SCR, 0x10);
REGS_REGISTER_AT(CPACR, 0x88);
REGS_REGISTER_AT(STCSR, 0x10);
REGS_REGISTER_AT(STRVR, 0x14);
REGS_REGISTER_AT(STCVR, 0x18);
REGS_REGISTER_AT(VTOR, 0xD08);
REGS_REGISTER_AT(AIRCR, 0xD0C);
REGS_REGISTER_AT(SCR, 0xD10);
REGS_REGISTER_AT(CPACR, 0xD88);
private:
constexpr uint32_t Base() const {
return 0xE000ED00;
return 0xE000E000;
}
};

View File

@@ -50,7 +50,7 @@ typedef Register<uint32_t> Register32;
typedef Register<uint64_t> Register64;
#define REGS_FIELD_R(name,type,high,low) type get##name() volatile { return (type)getBitRange(high,low); };
#define REGS_FIELD_W(name,type,high,low) void set##name(type v) volatile { static_assert(sizeof(type) <= 2, "Invalid size"); setBitRange(high, low, static_cast<uint16_t>(v)); };
#define REGS_FIELD_W(name,type,high,low) void set##name(type v) volatile { static_assert(sizeof(type) <= 4, "Invalid size"); setBitRange(high, low, static_cast<uint32_t>(v)); };
#define REGS_FIELD(name,type,high,low) REGS_FIELD_R(name,type,high,low); REGS_FIELD_W(name,type,high,low);
#define REGS_TYPE_FIELD(name,high,low) REGS_FIELD(name,name,high,low)
#define REGS_BOOL_FIELD(name,bit) REGS_FIELD(name,bool,bit,bit)

View File

@@ -9,6 +9,7 @@ namespace USB {
namespace Device {
void Calculator::PollAndReset(bool exitWithKeyboard) {
CM4.STCSR()->setTICKINT(false);
char serialNumber[Ion::Device::SerialNumberLength+1];
Ion::Device::copySerialNumber(serialNumber);
Calculator c(serialNumber);
@@ -37,6 +38,7 @@ void Calculator::PollAndReset(bool exitWithKeyboard) {
* will enter the newly flashed firmware. */
Ion::Device::jumpReset();
}
CM4.STCSR()->setTICKINT(true);
}
Descriptor * Calculator::descriptor(uint8_t type, uint8_t index) {

View File

@@ -2,6 +2,9 @@
#include "display.h"
#include "events_keyboard.h"
#include "../../../apps/global_preferences.h"
extern "C" {
#include <SDL/SDL.h>
}
extern "C" {
const char * IonSoftwareVersion();
@@ -21,3 +24,7 @@ int main(int argc, char * argv[]) {
void Ion::msleep(long ms) {
}
long Ion::millis() {
return SDL_GetTicks();
}

View File

@@ -116,3 +116,19 @@ void Ion::msleep(long ms) {
}
}
}
static auto start = std::chrono::high_resolution_clock::now();
long Ion::millis() {
sDisplay->redraw();
Fl::wait(0);
auto elapsed = std::chrono::high_resolution_clock::now() - start;
return std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();
}
long Ion::micros() {
sDisplay->redraw();
Fl::wait(0);
auto elapsed = std::chrono::high_resolution_clock::now() - start;
return std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count();
}