I am attempting to set up ARM-Semihosting to free up the use of the USB and Uart ports on my project. I am using the baremetal Wizio-Pico platform for Platformio. I've fought with it to the point where calling puts_raw() will print to the Debug Console. However, when I try to use puts() or printf() nothing is output. I've tried stepping through the program from a breakpoint on both puts() and printf() but it just moves to the sleep_ms call right below it. This makes me think that there is something wrong with the implementation of puts and printf when using the PICO_STDIO_SEMIHOSTING flag.
I am hoping to get printf working so that I don't have to change my code depending on the stdio method defined by the build flags.
Platformio.ini
[env]
platform = wizio-pico
framework = baremetal
board = raspberry-pi-pico
lib_compat_mode = off
lib_archive = false
;;lib_extra_dirs = "/lib"
build_src_filter =
+<*.h>
+<App/main-${PIOENV}.cpp>
+<App/main-${PIOENV}.c>
+<Common/*.cpp>
+<Common/*.c>
build_flags =
-D TARGET_RP2040
board_build.boot= w25q080
[DEBUG]
upload_protocol = picoprobe
debug_tool = picoprobe
build_flags = -D DEBUG
[env:semihosting]
extends = DEBUG
;board_build.nano = disable
lib_deps=
wiring
build_unflags =
-lnosys
--specs=nosys.specs
build_flags =
${env.build_flags}
${DEBUG.build_flags}
-D PICO_STDIO_SEMIHOSTING
-D PICO_STDIO_ENABLE_CRLF_SUPPORT=0
-D LIB_PICO_PRINTF_PICO
-l rdimon
--specs=rdimon.specs
debug_extra_cmds =
monitor arm semihosting enable
monitor arm semihosting_fileio enable
monitor reset halt
monitor debug_level -2
main-semihosting.c
#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/printf.h"
int main(){
stdio_init_all();
while(1) {
puts_raw("yo"); // Works!
puts("ya\n"); // Doesn't work
printf("ye\n"); // Doesn't Work
sleep_ms(1000);
}
}
Related
I'm trying to implement an embedded firmware on an stm32 F4 micro that takes an binary code from the serial and execute it on the micro.
The idea is pretty simple of course the only tricky part is that since on the serial is complicate to send raw binary data I'm going to send everything through base64 encoding.
Here's the code:
#include <Arduino.h>
#include <base64.hpp>
size_t read_serial_line(char *msg, size_t len, size_t timeout = 0) {
const auto start = millis();
size_t sz = 0;
do {
while (not Serial.available()) {
if (timeout > 0 and millis() > start + timeout) {
return -1;
}
}
msg[sz] = Serial.read();
if (msg[sz] == '\r') {
msg[sz] = '\0'; // replacing the end line with the end string
// the next char must be a \n char since the Serial.println of arduino
// works like that
while (Serial.read() != '\n')
; // I discard it
// now sz contains the length of the string as returned by strlen
break; // end of line
}
if (timeout > 0 and millis() > start + timeout) {
return -1;
}
} while (++sz < len);
return sz;
}
void setup() {
Serial.begin(9600);
Serial.println("begin!");
}
void loop() {
char *msg = new char[2048](); // big line
auto sz = read_serial_line(msg, 2048);
Serial.print("\tlooping...");
Serial.println(sz);
Serial.print("received: ");
Serial.println(msg);
uint8_t *code = new uint8_t[2048]();
sz = decode_base64(msg, code);
Serial.println(sz);
delay(1000);
int (*code_fn)() = (int (*)())code;
int c = code_fn();
Serial.println(c);
delete code;
delete msg;
delay(1000);
}
The next problem is to be able to compile and get the compiled binary code from this simple C function:
int fn() {
return 3;
}
Here you can see the assembly of this stupid function.
I tried, of course using the same tool chain used for the main code of the micro, to compile it with gcc using the option for the position independent code and then I tried to copy the .text secion with objcopy, to finish I took the text returned from the xxd command, I encoded it in base64 and I sent it to the micro.
here are the commands that I used:
$ arm-none-eabi-gcc -fPIC -c test.c
$ arm-none-eabi-objcopy -j .text test.o test.bin
$ xxd -p test.bin
As I expected this idea is not working, my hypothesis is that I'm getting more then just the binary codes of the function from this process.
I have this idea because the output file test.bin is pretty big 440 bytes that seems to me a little bit too much for literally 7 assembly instructions.
So that's the reason of my question: How do I get the binary code and only that code?
You accidentally produced an ELF file instead of a simple BIN file. (You can verify this using the file utility if your system has it.)
To produce a small BIN file from your code, change your second command to:
arm-none-eabi-objcopy -j .text test.o -O binary test.bin
Note that there are likely to be tons of complications and security issues when you execute arbitrary machine code received over a serial line. I am not recommending that as a design, just trying to answer the question you asked.
I am very new to the FreeBSD world and am currently porting my terminal emulation library from Linux to FreeBSD and Mac OS. I've encountered some very strange behavior such that when I pass a struct by pointer to a subroutine the member values become zeroed out. This does not happen on Linux or Mac OS. It also does not matter if the compiler is GCC or Clang.
I've confirmed that the member value is correct before the subroutine is called and the parent struct is passed by pointer.
I've tested the same code on Linux and Mac OS and they do not exhibit the problem.
I've switched between GCC and Clang on FreeBSD and that seems to have no effect.
I've consider that stack smashing could be happening but it seems unlikely because ulimit shows that the stack size on Linux is 8M but on FreeBSD it's much larger (524 MB). I've also tried compiling with -fstack-protector-strong but none of this matters.
#include "vterm.h"
#include "vterm_private" // vterm_t and vterm_desc_t defined here
void vterm_cursor_move_backward(vterm_t* vterm) {
vterm_desc_t* v_desc = NULL;
int min_row;
int idx;
// idx = vterm_buffer_get_active(vterm);
idx = 0; // hard set to 0 just for debugging
v_desc = &vterm->vterm_desc[idx];
// printf() will display a value of zero
printf("%d\n\r", v_desc->ccol);
fflush(stdout);
}
void vterm_interpret_ctrl_char(vterm_t* vterm, const char* data) {
vterm_desc_t *v_desc = NULL;
int idx;
char verb;
// idx = vterm_buffer_get_active(vterm);
idx = 0; // hard set to 0 just for debugging
v_desc = &vterm->vterm_desc[idx];
verb = data[0];
switch (verb) {
case '\b': {
// the following printf will print a positive number
printf("%d\n\r", v_desc->ccol);
fflush(stdout);
vterm_cursor_move_backward(vterm);
break;
}
}
}
I expect the value of v_desc->ccol to be identical in both functions. Godbolt Link Github Link See files vterm_ctrl_char.c and vterm_cursor.c
After countless hours of debugging I figured out that data in the vterm_desc_t structure was actually being shifted causing the member value to be set to zero. Although, the ncurses header file is included via vterm_private.h, on FreeBSD that doesn't seem to matter. Both GCC and Clang are happy to silently compile the vterm_cursor.c translation unit with bad / incomplete alignment.
I would recommend anyone running into kind of problem to try and compile each translation unit individually which is how I unearthed it. For example gcc -S vterm_cursor.c
Thank you to everyone who took a look at this.
I'm trying to enable hot plug-in debug option on RL78 MCU by setting the HPIEN bit in the corresponding option byte.
When I attach the E1 debugger to the running target, I can use Live Watch to inspect the RAM variables, however, trying to break the execution results in "can not compulsory break" error message:
The test software I'm trying to debug is a simple infinite loop incrementing a variable, toggling a pin and servicing the watchdog:
volatile long i = 0;
void main( void )
{
hpi_initialize_prog();
PM8_bit.no5 = 0;
while (1)
{
i++;
P8_bit.no5 = i;
WDTE = 0xAC;
}
}
Did anyone manage to use breakpoints / step through the program using the hot plug-in debug?
I am trying to debug this code:
#include <stdio.h>
int main()
{
int firstNumber, secondNumber, sumOfTwoNumbers;
printf("Enter two integers: ");
// Two integers entered by user is stored using scanf() function
scanf("%d %d", &firstNumber, &secondNumber);
// sum of two numbers in stored in variable sumOfTwoNumbers
sumOfTwoNumbers = firstNumber + secondNumber;
// Displays sum
printf("%d + %d = %d", firstNumber, secondNumber, sumOfTwoNumbers);
return 0;
}
Here are debugger logs (as described here):
1show version
2show debug-file-directory
3set print object on
4set breakpoint pending on
5set print elements 10000
6set unwindonsignal on
7set width 0
8set height 0
9set substitute-path C:/work/build/qt5_workdir/w/s C:/msys64/mingw32/qt5-static
10set substitute-path Q:/qt5_workdir/w/s C:/msys64/mingw32/qt5-static
11set substitute-path c:/Users/qt/work/install C:/msys64/mingw32/qt5-static
12set substitute-path c:/users/qt/work/qt C:/msys64/mingw32/qt5-static
13python sys.path.insert(1, 'C:/msys64/mingw64/share/qtcreator/debugger/')
14python sys.path.append('C:/msys64/mingw64/bin/data-directory/python')
15python from gdbbridge import *
16python theDumper.loadDumpers({"token":16})
17-interpreter-exec console "set target-async off"
18-break-insert -f "\"main.c\":12"
19attach 7444
20-exec-continue
21importPlainDumpers off
22-thread-info
23python theDumper.fetchStack({"limit":20,"nativemixed":0,"token":23})
24set disassembly-flavor att
25-interpreter-exec console "disassemble /rm 0x8ddf8"
26-stack-select-frame 0
27python theDumper.fetchVariables({"autoderef":1,"context":"","displaystringlimit":"100","dyntype":1,"expanded":["watch","return","inspect","local"],"fancy":1,"formats":{},"nativemixed":0,"partialvar":"","passexceptions":0,"qobjectnames":1,"resultvarname":"","stringcutoff":"10000","token":27,"typeformats":{},"watchers":[]})
28-interpreter-exec console "disassemble /rm 0x8dde4,0x8de5c"
<Rebuild Watchmodel 1 # 12:59:48.782 >
and
(exceeded max char limit, thats why I am posting at pastebin)
https://pastebin.com/rLDsWd9N
When I try to debug code and when there is breakpoint I get a window:
The inferior stopped because it received a signal from the operating system.
Signal name: ?
Signal meaning: Unknown signal
Screenshot:
Also, I get issue:
:-1: error: An exception was triggered:
Exception at 0x4015f6, code: 0x4000001f: Win32 x86 emulation subsystem breakpoint hit, flags=0x0.
Screenshot:
Also some screenshot:
Building and running code gives me no error. I have read this but I have no antivirus other than Windows Defender and I disabled it real-time protection. I use Windows 8.1
I also use QT, mingw and gdb from msys2.
Question: What is the problem and how to solve it?
I was using qtcreator 64 bit but for the project selected kit mingw-w64 32 bit. I think that difference in bitness caused error.
Now when I use qtcreator 64 bit with kit mingw-w64 64 bit, debugger works fine
I got by help from Reddit user jedwardsol:
4000001f is coming from the x86 emulation layer of 64-bit Windows. Perhaps your debugger doesn't understand it.
Try building a 64-bit program instead.
I recently wrote a little curses game and as all it needs to work is some timer mechanism and a curses implementation, the idea to try building it for DOS comes kind of naturally. Curses is provided by pdcurses for DOS.
Timing is already different between POSIX and Win32, so I have defined this interface:
#ifndef CSNAKE_TICKER_H
#define CSNAKE_TICKER_H
void ticker_init(void);
void ticker_done(void);
void ticker_start(int msec);
void ticker_stop(void);
void ticker_wait(void);
#endif
The game calls ticker_init() and ticker_done() once, ticker_start() with a millisecond interval as soon as it needs ticks and ticker_wait() in its main loop to wait for the next tick.
Using the same implementation on DOS as the one for POSIX platforms, using setitimer(), didn't work. One reason was that the C lib coming with djgpp doesn't implement waitsig(). So I created a new implementation of my interface for DOS:
#undef __STRICT_ANSI__
#include <time.h>
uclock_t tick;
uclock_t nextTick;
uclock_t tickTime;
void
ticker_init(void)
{
}
void
ticker_done(void)
{
}
void
ticker_start(int msec)
{
tickTime = msec * UCLOCKS_PER_SEC / 1000;
tick = uclock();
nextTick = tick + tickTime;
}
void
ticker_stop()
{
}
void
ticker_wait(void)
{
while ((tick = uclock()) < nextTick);
nextTick = tick + tickTime;
}
This works like a charm in dosbox (I don't have a real DOS system right now). But my concern is: Is busy waiting really the best I can do on this platform? I'd like to have a solution allowing the CPU to at least save some energy.
For reference, here's the whole source.
Ok, I think I can finally answer my own question (thanks Wyzard for the helpful comment!)
The obvious solution, as there doesn't seem any library call doing this, is putting a hlt in inline assembly. Unfortunately, this crashed my program. Looking for the reason, it is because the default dpmi server used runs the program in ring 3 ... hlt is reserved to ring 0. So to use it, you have to modify the loader stub to load a dpmi server running your program in ring 0. See later.
Browsing through the docs, I came across __dpmi_yield(). If we are running in a multitasking environment (Win 3.x or 9x ...), there will already be a dpmi server provided by the operating system, and of course, in that case we want to give up our time slice while waiting instead of trying the privileged hlt.
So, putting it all together, the source for DOS now looks like this:
#undef __STRICT_ANSI__
#include <time.h>
#include <dpmi.h>
#include <errno.h>
static uclock_t nextTick;
static uclock_t tickTime;
static int haveYield;
void
ticker_init(void)
{
errno = 0;
__dpmi_yield();
haveYield = errno ? 0 : 1;
}
void
ticker_done(void)
{
}
void
ticker_start(int msec)
{
tickTime = msec * UCLOCKS_PER_SEC / 1000;
nextTick = uclock() + tickTime;
}
void
ticker_stop()
{
}
void
ticker_wait(void)
{
if (haveYield)
{
while (uclock() < nextTick) __dpmi_yield();
}
else
{
while (uclock() < nextTick) __asm__ volatile ("hlt");
}
nextTick += tickTime;
}
In order for this to work on plain DOS, the loader stub in the compiled executable must be modified like this:
<path to>/stubedit bin/csnake.exe dpmi=CWSDPR0.EXE
CWSDPR0.EXE is a dpmi server running all code in ring 0.
Still to test is whether yielding will mess with the timing when running under win 3.x / 9x. Maybe the time slices are too long, will have to check that. Update: It works great in Windows 95 with this code above.
The usage of the hlt instruction breaks compatibility with dosbox 0.74 in a weird way .. the program seems to hang forever when trying to do a blocking getch() through PDcurses. This doesn't happen however on a real MS-DOS 6.22 in virtualbox. Update: This is a bug in dosbox 0.74 that is fixed in the current SVN tree.
Given those findings, I assume this is the best way to wait "nicely" in a DOS program.
Update: It's possible to do even better by checking all available methods and picking the best one. I found a DOS idle call that should be considered as well. The strategy:
If yield is supported, use this (we are running in a multitasking environment)
If idle is supported, use this. Optionally, if we're in ring-0, do a hlt each time before calling idle, because idle is documented to return immediately when no other program is ready to run.
Otherwise, in ring-0 just use plain hlt instructions.
Busy-waiting as a last resort.
Here's a little example program (DJGPP) that tests for all possibilities:
#include <stdio.h>
#include <dpmi.h>
#include <errno.h>
static unsigned int ring;
static int
haveDosidle(void)
{
__dpmi_regs regs;
regs.x.ax = 0x1680;
__dpmi_int(0x28, ®s);
return regs.h.al ? 0 : 1;
}
int main()
{
puts("checking idle methods:");
fputs("yield (int 0x2f 0x1680): ", stdout);
errno = 0;
__dpmi_yield();
if (errno)
{
puts("not supported.");
}
else
{
puts("supported.");
}
fputs("idle (int 0x28 0x1680): ", stdout);
if (!haveDosidle())
{
puts("not supported.");
}
else
{
puts("supported.");
}
fputs("ring-0 HLT instruction: ", stdout);
__asm__ ("mov %%cs, %0\n\t"
"and $3, %0" : "=r" (ring));
if (ring)
{
printf("not supported. (running in ring-%u)\n", ring);
}
else
{
puts("supported. (running in ring-0)");
}
}
The code in my github repo reflects the changes.