Created
December 17, 2019 04:05
-
-
Save mofosyne/08a9f19a4ed029b1f80709d8cde7a5b2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*********************** | |
SEMIHOSTING | |
************************/ | |
#define SEMIHOSTING | |
#ifdef SEMIHOSTING | |
#include <stdarg.h> | |
#include <ctype.h> //isprint | |
/* | |
Note: This semihost printing utility functions is targeted towards STM32 based chips | |
*/ | |
void arm_semihosting_print_string(char* str) | |
{ | |
int len = 0; | |
/* Check if debugger is attached */ | |
if (!((CoreDebug->DHCSR & 1) == 1 )) | |
return; | |
/* Calculate String Length */ | |
for (len = 0; str[len]; (len)++); | |
/* Call Semihost */ | |
int args[3] = {2 /*stderr*/, (int) str, (int)len}; | |
asm volatile ( | |
" mov r0, %[reason] \n" | |
" mov r1, %[arg] \n" | |
" bkpt %[swi] \n" | |
: /* Output */ | |
: [reason] "r" (0x05), [arg] "r" (args), [swi] "i" (0xAB) /* Inputs */ | |
: "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc" | |
); | |
} | |
void arm_semihosting_printf(char* format, ...) | |
{ | |
char buff[400] = {0}; | |
size_t buff_size = sizeof(buff); | |
/* Check if debugger is attached */ | |
if (!((CoreDebug->DHCSR & 1) == 1 )) | |
{ | |
return; | |
} | |
/* Format String */ | |
va_list argptr; | |
va_start(argptr, format); | |
vasnprintf(buff, &buff_size, format, argptr); | |
va_end(argptr); | |
/* Print */ | |
arm_semihosting_print_string(buff); | |
} | |
void arm_semihosting_hex_dump( const void *addr, const uint32_t nBytes) | |
{ | |
const uint8_t byte_per_row = 16; | |
const uint8_t *addr_ptr = addr; | |
uint32_t offset = 0; | |
while (offset < nBytes) | |
{ | |
char buff[400] = {0}; // Line Buff | |
char *buff_ptr = buff; | |
const char *buff_end = buff + sizeof(buff) - 1; | |
buff_ptr += snprintf(buff_ptr, buff_end-buff_ptr, " %4u | ", (unsigned) offset); | |
for (uint8_t i = 0 ; i < byte_per_row ; i++) | |
{ /* Hex */ | |
if ((offset + i) >= nBytes) | |
break; | |
buff_ptr += snprintf(buff_ptr, buff_end-buff_ptr, " %02x", addr_ptr[offset+i]); | |
} | |
buff_ptr += snprintf(buff_ptr, buff_end-buff_ptr, " : "); | |
for (uint8_t i = 0 ; i < byte_per_row ; i++) | |
{ /* Printables */ | |
if ((offset + i) >= nBytes) break; | |
char c = isprint(addr_ptr[offset+i]) ? addr_ptr[offset+i] : '.'; | |
buff_ptr += snprintf(buff_ptr, buff_end-buff_ptr, "%c", c); | |
} | |
offset += byte_per_row; | |
arm_semihosting_print_string(buff); | |
arm_semihosting_print_string("\r\n"); | |
} | |
arm_semihosting_print_string("\r\n"); | |
} | |
#else | |
#define arm_semihosting_print_string(...) | |
#define arm_semihosting_printf(...) | |
#define arm_semihosting_hex_dump(...) | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example output
Useful for bootloader dev and other development where you don't have access to the serial console.