RISC-V/debug/debug.cpp
2024-03-15 15:13:20 +01:00

81 lines
2.4 KiB
C++

#include "system.h"
#include "debug.h"
struct DEBUG_S {
uint32_t UNUSED0;
volatile uint32_t DATA0;
volatile uint32_t DATA1;
};
static DEBUG_S & DBGM = * reinterpret_cast<DEBUG_S * const> (0xe00000f0);
static constexpr unsigned FUNCONF_DEBUGPRINTF_TIMEOUT = 160000u;
// Převzato i když jsem to nekontroloval. Ono je to dost divoké.
extern "C" {
void handle_debug_input( int numbytes, uint8_t * data ) __attribute__((used,weak));
void handle_debug_input( int numbytes, uint8_t * data ) { }
void internal_handle_input( volatile uint32_t * dmdata0 ) {
uint32_t dmd0 = * dmdata0;
int bytes = (dmd0 & 0x3f) - 4;
if( bytes > 0 ) {
handle_debug_input( bytes, ((uint8_t*)dmdata0) + 1 );
}
}
};
// where [status word] is:
// b7 = is a "printf" waiting?
// b0..b3 = # of bytes in printf (+4). (5 or higher indicates a print of some kind)
// note: if b7 is 0 in reply, but b0..b3 have >=4 then we received data from host.
static int _write (const char * buf, const int size) {
char buffer[4] = { 0 };
int place = 0;
uint32_t lastdmd;
uint32_t timeout = FUNCONF_DEBUGPRINTF_TIMEOUT; // Give up after ~40ms
if( size == 0 ) {
lastdmd = DBGM.DATA0;
if( lastdmd && !(lastdmd & 0x80) ) internal_handle_input( (uint32_t*) & DBGM.DATA0 );
}
while( place < size ) {
int tosend = size - place;
if( tosend > 7 ) tosend = 7;
while( ( lastdmd = DBGM.DATA0 ) & 0x80 )
if( timeout-- == 0 ) return place;
if( lastdmd ) internal_handle_input( (uint32_t*) & DBGM.DATA0 );
timeout = FUNCONF_DEBUGPRINTF_TIMEOUT;
int t = 3;
while( t < tosend ) {
buffer[t-3] = buf[t+place];
t++;
}
DBGM.DATA1 = *(uint32_t*)&(buffer[0]);
t = 0;
while( t < tosend && t < 3 ) {
buffer[t+1] = buf[t+place];
t++;
}
buffer[0] = 0x80 | (tosend + 4);
DBGM.DATA0 = *(uint32_t*)&(buffer[0]);
//buf += tosend;
place += tosend;
}
return size;
}
Debug::Debug() noexcept : BaseLayer() {
// Clear out the sending flag.
DBGM.DATA1 = 0u;
DBGM.DATA0 = 0x80u;
// Tohle je asi zbytečné.
while ( DBGM.DATA0 & 0x80 );
}
uint32_t Debug::Down(const char * buf, const uint32_t size) {
/* Z nějakého záhadného důvodu pokud namastím kód přímo sem,
* optimalizace ho vyhodí. Nějak se to nesnáší s virtuálními
* metodami.
* */
return _write (buf, size);
}