188 lines
4.6 KiB
C
188 lines
4.6 KiB
C
#include <stdint.h>
|
|
|
|
#include "stm32f4xx.h"
|
|
|
|
int putchar(int c) {
|
|
// if(c=='\r') putchar('\n');
|
|
while (!(USART1->SR & USART_SR_TXE)) {
|
|
}; // wait until we are able to transmit
|
|
USART1->DR = c; // transmit the character
|
|
return c;
|
|
}
|
|
|
|
void print_string(const char* s) {
|
|
while (*s) putchar(*s++);
|
|
}
|
|
|
|
int getchar() {
|
|
while (!(USART1->SR & USART_SR_RXNE)) {
|
|
}; // wait until something received
|
|
return USART1->DR; // find out what it is
|
|
}
|
|
|
|
void alertCrash() {
|
|
print_string("Crashed, restart required\n");
|
|
while (1)
|
|
;
|
|
}
|
|
|
|
int strlen(const char* str) {
|
|
const char* end = str;
|
|
while (*end != 0) {
|
|
end++;
|
|
}
|
|
return end - str;
|
|
}
|
|
|
|
void greet() {
|
|
print_string("STM32F4 rootshell\n");
|
|
print_string("Commands: \n");
|
|
print_string(" \"H\" this message.\n");
|
|
print_string(
|
|
" \"R aabbccdd 000000FF\" read FF bytes from address aabbccdd. Both "
|
|
"arguments must be zero-padded to 8 characters.\n");
|
|
}
|
|
|
|
const uint8_t hexMap[] = "0123456789ABCDEF";
|
|
|
|
void printByteHex(uint8_t b) {
|
|
putchar(hexMap[b >> 4]);
|
|
putchar(hexMap[b & 0x0F]);
|
|
}
|
|
|
|
void printWordHexBigEndiand(uint32_t word) {
|
|
printByteHex((word & 0xFF000000) >> 24);
|
|
printByteHex((word & 0x00FF0000) >> 16);
|
|
printByteHex((word & 0x0000FF00) >> 8);
|
|
printByteHex((word & 0x000000FF));
|
|
}
|
|
|
|
void printWordHexLittleEndian(uint32_t word) {
|
|
printByteHex((word & 0x000000FF));
|
|
printByteHex((word & 0x0000FF00) >> 8);
|
|
printByteHex((word & 0x00FF0000) >> 16);
|
|
printByteHex((word & 0xFF000000) >> 24);
|
|
}
|
|
|
|
int parseHexToInt(const char* line, uint32_t* int_out) {
|
|
uint32_t num = 0;
|
|
for (int i = 0; i < 8; i++) {
|
|
const char c = line[i];
|
|
int digit;
|
|
if (c >= '0' && c <= '9') {
|
|
digit = c - '0';
|
|
} else if (c >= 'a' && c <= 'f') {
|
|
digit = c - 'a' + 10;
|
|
} else if (c >= 'A' && c <= 'F') {
|
|
digit = c - 'A' + 10;
|
|
} else {
|
|
print_string("ERROR: unexpected character while parsing hex string: 0x");
|
|
printByteHex(c);
|
|
putchar('\n');
|
|
return 1;
|
|
}
|
|
num = digit | (num << 4);
|
|
}
|
|
if (line[8] != 0 && line[8] != ' ') {
|
|
print_string("ERROR: hex string too long, got char 0x");
|
|
printByteHex(line[8]);
|
|
putchar('\n');
|
|
return 1;
|
|
}
|
|
*int_out = num;
|
|
return 0;
|
|
}
|
|
|
|
void processReadCommand(const char* line) {
|
|
const int len = strlen(line);
|
|
int pos = 1;
|
|
while (pos < len && line[pos] == ' ') {
|
|
pos++;
|
|
}
|
|
uint32_t address;
|
|
if (parseHexToInt(line + pos, &address)) {
|
|
return;
|
|
}
|
|
pos += 8;
|
|
while (pos < len && line[pos] == ' ') {
|
|
pos++;
|
|
}
|
|
uint32_t read_size;
|
|
if (parseHexToInt(line + pos, &read_size)) {
|
|
return;
|
|
}
|
|
print_string("Reading 0x");
|
|
printWordHexBigEndiand(read_size);
|
|
print_string(" bytes from 0x");
|
|
printWordHexBigEndiand(address);
|
|
putchar('\n');
|
|
|
|
const uint32_t* last_word = (uint32_t*)(address + read_size);
|
|
const uint32_t* read_address = (uint32_t*)address;
|
|
int word_no = 0;
|
|
while (read_address < last_word) {
|
|
if ((word_no % 8) == 0) {
|
|
putchar('\n');
|
|
printWordHexBigEndiand((uint32_t)read_address);
|
|
print_string(": ");
|
|
}
|
|
printWordHexLittleEndian(*read_address);
|
|
read_address++;
|
|
word_no++;
|
|
}
|
|
}
|
|
|
|
void parseLine(const char* line) {
|
|
switch (line[0]) {
|
|
case 'r':
|
|
case 'R':
|
|
processReadCommand(line);
|
|
break;
|
|
case 'h':
|
|
case 'H':
|
|
greet();
|
|
break;
|
|
}
|
|
}
|
|
|
|
int main(void) {
|
|
// Set pins PA9 (TX) and PA10 (RX) for serial communication
|
|
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; // enable RCC for port A
|
|
GPIOA->MODER |=
|
|
(GPIO_MODER_MODER9_1 |
|
|
GPIO_MODER_MODER10_1); // PA9/10 alternate functions for USART1 TX/RX
|
|
GPIOA->AFR[1] |= ((7 << GPIO_AFRH_AFSEL9_Pos) | (7 << GPIO_AFRH_AFSEL10_Pos));
|
|
|
|
RCC->APB2ENR |= RCC_APB2ENR_USART1EN; // enable RCC for USART1
|
|
|
|
// Set the baud rate, which requires a mantissa and fraction
|
|
const uint32_t baud_rate = 256000;
|
|
SystemCoreClockUpdate();
|
|
uint16_t uartdiv = SystemCoreClock / baud_rate;
|
|
USART1->BRR = (((uartdiv / 16) << USART_BRR_DIV_Mantissa_Pos) |
|
|
((uartdiv % 16) << USART_BRR_DIV_Fraction_Pos));
|
|
|
|
// Mpw enable the USART peripheral
|
|
USART1->CR1 |= USART_CR1_RE // enable receive
|
|
| USART_CR1_TE // enable transmit
|
|
| USART_CR1_UE // enable usart
|
|
;
|
|
greet();
|
|
char last_line[512];
|
|
int last_line_len = 0;
|
|
while (1) {
|
|
int c = getchar();
|
|
putchar(c);
|
|
if (c == '\r') {
|
|
putchar('\n');
|
|
}
|
|
if (c == '\r' || c == '\n') {
|
|
last_line[last_line_len++] = 0;
|
|
parseLine(last_line);
|
|
last_line_len = 0;
|
|
} else {
|
|
last_line[last_line_len++] = c;
|
|
}
|
|
}
|
|
}
|