#include <stdint.h>
uint32_t volatile * const rccApb2 = (uint32_t *) 0x40021018u;
uint32_t volatile * const ioAModerH = (uint32_t *) 0x40010804u;
uint32_t volatile * const uart1Ctrl = (uint32_t *) 0x40013800u;
void readChar( uint8_t const chr );
void writeByte( uint8_t b );
void writeStr( uint8_t const * const str );
void writeChar( uint8_t const chr );
void writeWordLe( uint32_t const word );
void writeWordBe( uint32_t const word );
void readCmd( uint8_t const * const cmd);
uint32_t hexToInt(uint8_t const * const hex);
void readMem(uint32_t const addr, uint32_t const len);
void writeMem(uint32_t const addr, uint32_t const data);
uint8_t const strHelp[] = "Help\r\n-----------\r\n"
"ADDR, VAL, LEN: 32-bit Hex encoded:\r\n e.g., 0A1337FF\r\n"
"-----------\r\n"
"R ADDR LEN - Read 32-bit word\r\n"
"W ADDR VAL - Write 32-bit word\r\n"
"D - Dump all flash memory\r\n"
"P - Jump into chall4 function\r\n"
"S - Reboot\r\n"
"E - Exit\r\n"
"H - Show help \r\n"
"---------------\r\n";
int main(void)
{
/* IOA + USART1 clock enable */
*rccApb2 = (uint32_t) 0x4004u;
/* USART1 TX+RX (PA9, PX10) on */
*ioAModerH = (uint32_t) 0x444444B4u;
/* config and enable uart */
uart1Ctrl[2] = 0x00000341u;
uart1Ctrl[3] = 0x0000200Cu;
writeStr("\r\n##############################\r\n"
"# Low-Level Shell v.0xRoM #\r\n"
"# CPU-ID: 0x");
uint32_t cpuid = *((uint32_t *) 0xe000ed00);
writeWordBe(cpuid);
writeStr( " #\r\n");
writeStr("##############################\r\n\r\n");
writeStr("> ");
while (1)
{
if ((uart1Ctrl[0] & 0x80u) && (0))
{
uart1Ctrl[1] = 0x33u;
}
if (uart1Ctrl[0] & 0x20u)
{
uint32_t data = uart1Ctrl[1];
readChar((uint8_t) data);
}
}
}
/* hex must have length 8 */
uint32_t hexToInt(uint8_t const * const hex)
{
uint32_t ind = 0u;
uint32_t res = 0u;
for (ind = 0; ind < 8; ++ind)
{
uint8_t chr = hex[ind];
uint32_t val = 0u;
res <<= 4u;
if ((chr >= '0') && (chr <= '9'))
{
val = chr - '0';
}
else if ((chr >= 'a') && (chr <= 'f'))
{
val = chr - 'a' + 0x0a;
}
else if ((chr >= 'A') && (chr <= 'F'))
{
val = chr - 'A' + 0x0a;
}
else
{
val = 0u;
}
res |= val;
}
return res;
}
void readChar( uint8_t const chr )
{
#define CMDBUF_LEN (64u)
static uint8_t cmdbuf[CMDBUF_LEN] = {0u};
static uint32_t cmdInd = 0u;
switch (chr)
{
case '\n':
case '\r':
cmdbuf[cmdInd] = 0u;
if (cmdInd != 0)
{
writeStr("\r\n");
}
readCmd(cmdbuf);
cmdInd = 0u;
writeStr("\r\n> ");
{
uint32_t ind = 0u;
for (ind = 0; ind<CMDBUF_LEN; ++ind)
{
cmdbuf[ind]=0x00u;
}
}
break;
case 8:
case 255:
case 127: /* TODO backspace */
if (cmdInd > 0u)
--cmdInd;
writeChar(chr);
break;
default:
if (cmdInd < (CMDBUF_LEN - 1))
{
cmdbuf[cmdInd] = chr;
++cmdInd;
writeChar(chr);
}
break;
}
}
void readCmd( uint8_t const * const cmd )
{
void (*chall4)(void) = (void (*)(void))0x08000ba9;
switch (cmd[0])
{
case 0:
return;
break;
/* chall4 function */
case 'p':
case 'P':
writeStr("time to change baudrate to 115200\r\n");
for (volatile uint32_t i = 0; i < 5000000; i++); // Crude delay
chall4();
break;
/* read 32-bit command */
case 'r':
case 'R':
/* r 08000000 00000100 */
readMem(hexToInt(&cmd[2]), hexToInt(&cmd[11]));
break;
/* write 32-bit command */
case 'w':
case 'W':
/* w 20000000 12345678 */
writeMem(hexToInt(&cmd[2]), hexToInt(&cmd[11]));
break;
/* Dump all flash */
case 'd':
case 'D':
writeStr("\r\n\r\n");
{
uint32_t const * addr = (uint32_t*) 0x08000000;
uint32_t br = 8u;
while (((uintptr_t) addr) < (0x08000000 + 64u * 1024u))
{
if (br == 8u)
{
writeStr("\r\n[");
writeWordBe((uint32_t) addr);
writeStr("]: ");
br = 0u;
}
writeWordBe(*addr);
writeChar(' ');
++addr;
++br;
}
}
writeStr("\r\n\r\n");
break;
/* Help command */
case 'h':
case 'H':
writeStr(strHelp);
break;
/* Reboot */
case 's':
case 'S':
writeStr("Rebooting...\r\n\r\n");
*((uint32_t *) 0xE000ED0C) = 0x05FA0004u;
break;
/* exit */
case 'e':
case 'E':
writeStr("Bye.\r\n");
while (1)
{
__asm__ volatile("wfi");
}
break;
default:
writeStr("Unknown command: ");
writeStr(cmd);
writeStr("\r\n");
break;
}
}
const uint8_t txtMap[] = "0123456789ABCDEF";
void writeByte( uint8_t b )
{
writeChar(txtMap[b >> 4]);
writeChar(txtMap[b & 0x0F]);
}
void writeStr( uint8_t const * const str )
{
uint32_t ind = 0u;
while (str[ind])
{
writeChar(str[ind]);
++ind;
}
}
void writeChar( uint8_t const chr )
{
while (!(uart1Ctrl[0] & 0x80u))
{
/* wait */
}
uart1Ctrl[1] = chr;
}
void writeWordLe( uint32_t const word )
{
writeByte((word & 0x000000FF));
writeByte((word & 0x0000FF00) >> 8);
writeByte((word & 0x00FF0000) >> 16);
writeByte((word & 0xFF000000) >> 24);
}
void writeWordBe( uint32_t const word )
{
writeByte((word & 0xFF000000) >> 24);
writeByte((word & 0x00FF0000) >> 16);
writeByte((word & 0x0000FF00) >> 8);
writeByte((word & 0x000000FF));
}
void alertCrash( uint32_t crashId )
{
writeStr("!!! EXCEPTION !!!\r\nID: ");
writeByte(crashId);
writeStr("\r\nRestart required!\r\n\r\n");
*((uint32_t *) 0xE000ED0C) = 0x05FA0004u;
while (1);
}
void readMem(uint32_t const addr, uint32_t const len)
{
uint32_t it = 0u;
uint32_t addrx = 0u;
uint32_t lenx = 0u;
lenx = len;
if (lenx == 0u)
{
lenx = 4u;
}
for (it = 0u; it < (lenx / 4u); ++it)
{
addrx = addr + it*4u;
writeStr("Read [");
writeWordBe(addrx);
writeStr("]: ");
writeWordBe(*((uint32_t*)addrx));
writeStr("\r\n");
}
}
void writeMem(uint32_t const addr, uint32_t const data)
{
writeStr("Write [");
writeWordBe(addr);
writeStr("]: ");
writeWordBe(data);
*((uint32_t*) addr) = data;
writeStr("\r\n");
}