I am developing an application that I compile with the IAR Embedded Workbench solution. In this application, I have embedded the expat library - a tiny XML parser that works fine - which uses the time() standard function to generate a salt, as you can see in this chunk of code:
static unsigned long
generate_hash_secret_salt(void)
{
unsigned int seed = time(NULL) % UINT_MAX;
srand(seed);
return rand();
}
It appears that the time() function works fine on semihosting mode (while debugging with the J-link JTAG device by Segger, I guess) but does not work at all when I am running my application without the j-link debugger.
So I've run into the assembly code of time() function - which actually appears to be a proprietary implementation by IAR - and saw this single instruction:
BPKT #0xab
By seeking information through the web, I came up with the following paragraph:
If required, a debugger can use it to store additional information
about the breakpoint. ARM does not recommend the use of the BKPT instruction with an immediate
value set to 0xAB for any purpose other than Semi-hosting.
Is it due to such an issue? I must admit that my knowledge in ARM assembler is poor, and since I cannot debug my application while it is not on semi-hosting mode, I am pretty confused.
For your information, regardless of the argument you may pass to time(), it is always freezing in non semihosting mode.
Finally, what could you suggest me to do in order to bypass such an implementation? Shall I import another one into my C project? ...
Thanks
You're right that this breakpoint instruction is being used to trigger some kind of semihosting operation. If your code contains such instructions, you'll need to always run it attached to a debugger that knows what to do when such an instruction is encountered. If you need to run the device standalone, find out what code you're using that causes the semihosting operations to take place, and make sure that code isn't in the standalone build. This situation is a good opportunity to set up "debug" and "release" builds of your software - maybe using #ifdef DEBUG or something along those lines to exclude the semihosting code from your release build.
In this specific case, it looks like your C library's time implementation is using semihosting to get the host time over the debugger connection. You'll have to come up with a different solution if you want to run your program disconnected from the debugger.
Related
I got some source code in plain C. It is built to run on ARM with a cross-compiler on Windows.
Now I want to do some white-box unit testing of the code. And I don't want to run the test on an ARM board because it may not be very efficient.
Since the C source code is instruction set independent, and I just want to verify the software logic at the C-level, I am wondering if it is possible to build the C source code to run on x86. It makes debugging and inspection much easier.
Or is there some proper way to do white-box testing of C code written for ARM?
Thanks!
BTW, I have read the thread: How does native android code written for ARM run on x86?
It seems not to be what I need.
ADD 1 - 10:42 PM 7/18/2021
The physical ARM hardware that the code targets may not be ready yet. So I want to verify the software logic at a very early phase. Based on John Bollinger's answer, I am thinking about another option: Just build the binary as usual for ARM. Then use QEMU to find a compatible ARM cpu to run the code. The code is assured not to touch any special hardware IO. So a compatible cpu should be enough to run all the code I think. If this is possible, I think I need to find a way to let QEMU load my binary on a piece of emulated bare-metal. And to get some output, I need to at least write a serial port driver to bridge my binary to the serial port.
ADD 2 - 8:55 AM 7/19/2021
Some more background, the C code is targeting ARMv8 ISA. And the code manipulates some hardware IPs which are not ready yet. I am planning to create a software HAL for those IPs and verify the C code over the HAL. If the HAL is good enough, everything can be purely software and I guess the only missing part is a ARMv8 compatible CPU, which I believe QEMU can provide.
ADD 3 - 11:30 PM 7/19/2021
Just found this link. It seems QEMU user mode emulation can be leveraged to run ARM binaries directly on a x86 Linux. Will try it and get back later.
ADD 4 - 11:42 AM 7/29/2021
An some useful links:
Override a function call in C
__attribute__((weak)) and static libraries
What are weak functions and what are their uses? I am using a stm32f429 micro controller
Why the weak symbol defined in the same .a file but different .o file is not used as fall back?
Now I want to do some white-box unit testing of the code. And I don't want to run the test on an ARM board because it may not be very efficient.
What does efficiency have to do with it if you cannot be sure that your test results are representative of the real target platform?
Since the C source code is instruction set independent,
C programs vary widely in how portable they are. This tends to be less related to CPU instruction set than to target machine and implementation details such as data type sizes, word endianness, memory size, and floating-point implementation, and implementation-defined and undefined program behaviors.
It is not at all safe to assume that just because the program is written in C, that it can be successfully built for a different target machine than it was developed for, or that if it is built for a different target, that its behavior there is the same.
I am wondering if it is possible to build the C source code to run on x86. It makes debugging and inspection much easier.
It is probably possible to build the program. There are several good C compilers for various x86 and x86_64 platforms, and if your C code conforms to one of the language specifications then those compilers should accept it. Whether the behavior of the result is representative of the behavior on ARM is a different question, however (see above).
It may nevertheless be a worthwhile exercise to port the program to another platform, such as x86 or x86_64 Windows. Such an exercise would be likely to unmask some bugs. But this would be a project in its own right, and I doubt that it would be worth the effort if there is no intention to run the program on the new platform other than for testing purposes.
Or is there some proper way to do white-box testing of C code written for ARM?
I don't know what proper means to you, but there is no substitute for testing on the target hardware that you ultimately want to support. You might find it useful to perform initial testing on emulated hardware, however, instead of on a physical ARM device.
If you were writing ARM code for a windows desktop application there would be no difference for the most part and the code would just compile and run. My guess is you are developing for some device that does some specific task.
I do this for a lot of my embedded ARM code. Typically the core algorithms work just fine when built on x86 but the whole application does not. The problems come in with the hardware other than the CPU. For example I might be using a LCD display, some sensors, and Free RTOS on the ARM project but the code that runs on Windows does not have any of these. What I do is extract important pieces of C/C++ code and write a test framework around it. In the real ARM code the device is reading values from a sensor and doing something with it. In the test code that runs on a desktop the code reads from a data file with fake sensor values and writes its output to a datafile that can be analyzed. This way I can have white box tests for the most complicated code.
May I ask, roughly what does this code do? An ARM processor with no peripherals would be kind of useless. Typically we use the processor to interact with some other hardware like a screen, some buttons, or Bluetooth. It's those interactions that are going to be the most problematic.
I'm a newbie to learning OS development. From the book I read, it said that boot loader will copy first MBR into 0x7c00, and starts from there in real mode.
And, example starts with 16 bit assembly code.
But, when I looked at today's linux kernel, arch/x86/boot has 'header.S' and 'boot.h', but actual code is implemented in main.c.
This seems to be useful by "not writing assembly."
But, how is this done specifically in Linux?
I can roughly imagine that there might be special gcc options and link strategy, but I can't see the detail.
I'm reading this question more as an X-Y problem. It seems to me the question is more about whether you can write a bootloader (boot code) in C for your own OS development. The simple answer is YES, but not recommended. Modern Linux kernels are probably not the best source of information for creating bootloaders written in C unless you have an understanding of what their code is doing.
If using GCC there are restrictions on what you can do with the generated code. In newer versions of GCC there is an -m16 option that is documented this way:
The -m16 option is the same as -m32, except for that it outputs the ".code16gcc" assembly directive at the beginning of the assembly output so that the binary can run in 16-bit mode.
This is a bit deceptive. Although the code can run in 16-bit real mode, the code generated by the back end uses 386 address and operand prefixes to make normally 32-bit code execute in 16-bit real mode. This means the code generated by GCC can't be used on processors earlier than the 386 (like the 8086/80186/80286 etc). This can be a problem if you want a bootloader that can run on the widest array of hardware. If you don't care about pre-386 systems then GCC will work.
Bootloader code that uses GCC has another downside. The address and operand prefixes that get get added to many instructions add up and can make a bootloader bloated. The first stage of a bootloader is usually very constrained in space so this could potentially become a problem.
You will need inline assembly or assembly language objects with functions to interact with the hardware. You don't have access to the Linux C library (printf etc) in bootloader code. For example if you want to write to the video display you have to code that functionality yourself either writing directly to video memory or through BIOS interrupts.
To tie it altogether and place things in the binary file usable as an MBR you will likely need a specially crafted linker script. In most projects these linker scripts have an .ld extension. This drives the process of taking all the object files putting them together in a fashion that is compatible with the legacy BIOS boot process (code that runs in real mode at 0x07c00).
There are so many pitfalls in doing this that I recommend against it. If you are intending to write a 32-bit or 64-bit kernel then I'd suggest not writing your own bootloader and use an existing one like GRUB. In the versions of Linux from the 1990s it had its own bootloader that could be executed from floppy. Modern Linux relies on third party bootloaders to do most of that work now. In particular it supports bootloaders that conform to the Multiboot specification
There are many tutorials on the internet that use GRUB as a bootloader. OS Dev Wiki is an invaluable resource. They have a Bare Bones tutorial that uses the original Multiboot specification (supported by GRUB) to boot strap a basic kernel. The Mulitboot specification can easily be developed for using a minimal of assembly language code. Multiboot compatible bootloaders will automatically place the CPU in protected mode, enable the A20 line, can be used to get a memory map, and can be told to place you in a specific video mode at boot time.
Last year someone on the #Osdev chat asked about writing a 2 stage bootloader located in the first 2 sectors of a floppy disk (or disk image) developed entirely in GCC and inline assembly. I don't recommend this as it is rather complex and inline assembly is very hard to get right. It is very easy to write bad inline assembly that seems to work but isn't correct.
I have made available some sample code that uses a linker script, C with inline assembly to work with the BIOS interrupts to read from the disk and write to the video display. If anything this code should be an example why it's non-trivial to do what you are asking.
OK, so I am trying to connect an emulated (Through TSIM) LEON3 processor to a UART terminal. If I am not mistaken I believe I need to compile a C program to enable it to talk with a terminal as I am having difficulties doing it another way.
I found some source code for UART communication here and it all seems to be OK.
However, I am having issues compiling it using the SPARC Bare C Toolchain in Eclipse as it is saying that the windows.h file does not exist. Now I know it exists as I've compiled it successfully using the GCC Toolchain and can't find any similar cases on the web as to why this would be happening.
Is there anyone out there who has had a similar problem or knows the solution?
Additionally, if you know me to be doing the wrong thing in regards to the LEON3 UART comms, please let me know and I will just leave.
Thanks.
BCC is a cross compiler targeting standalone, LEON3- and LEON4-based environments. As a cross compiler, its job is to build binaries for a different environment than the one in which it runs.
Relevant header files describe functions available to a program in its runtime (target) environment. Build-environment libraries and their headers are irrelevant when cross compiling because the build and target environments differ. BCC is correct to expose only the headers for the environment for which it compiles, and that environment does not provide Windows API functions. If the code you're trying to build depends on the Windows API, then you'll need to modify it to remove that dependency, or else find something different.
On the other hand, I strongly suspect that you're going about this whole thing the wrong way. In particular, when you say,
I believe I need to compile a C program to enable it to talk with a terminal
it sounds like you think you're going to build some kind of helper program, but if that's your idea then either you're building it for the wrong environment or you have the wrong idea altogether.
If you want a Windows program that talks to the emulated machine, then you should be building that as a Windows program, and BCC doesn't do that. In that case, you should be using MinGW's gcc, or another C compiler for the emulator's host environment. Moreover, the host-side interface to the emulated environment's UART is an aspect of the emulator. I haven't a clue what emulator you're using, but it might not present the host (Windows) side of that interface as a UART, and it might not require using the Windows API at all.
Or if you indeed do intend to build a program for the standalone LEON3 target environment, then you need to understand that when it runs, it will be the only program that will be running in that environment. That's what "standalone" means -- no OS underneath, therefore no separate processes, and often not even multiple threads of execution. Thus, you do not need a helper program; you just need a program.
The BCC documentation talks about the libraries available there, and in particular, it describes how in that environment, file I/O is allowed only on the standard input and output streams, which are mapped to UART A. Thus, if you use BCC to build the program to run in the emulator, then you don't need to do anything special on that end to talk to the UART. You just use stdio functions directed at stdin and stdout.
On the third hand, if you are running an actual operating system in your emulated environment, then to build programs that run on it you should be using either a native compiler for that environment, in that environment, or else a cross compiler targeting that hosted environment. Either way, BCC is not such a compiler, but GCC might be. Anyway, since Windows does not run on LEON3, it's safe to say that if this is what you're trying to do then you still need something that does not depend on the Windows API.
I have Fedora installed on my PC and I have a Friendly ARM Mini2440 board. I have successfully installed Linux kernel and everything is working. Now I have some image processing program, which I want to run on the board without OS. The only process running on board should be my program. And in that program how can I access the on board camera to take image from, and serial port to send output to the PC.
You're talking about what is often called a bare-metal environment. Google can help you, for example here. In a bare-metal environment you have to have a good understanding of your hardware because you have to take care of a lot of things that the OS normally handles.
I've been working (off and on) on bare-metal support for my ELLCC cross development tool-chain. I have the ARM implementation pretty far along but there is still quite a bit of work to do. I have written about some of my experiences on my blog.
First off, you have to get your program started. You'll need to write some start-up code, usually in assembly, to handle the initialization of the processor as it comes out of reset (or is powered on). The start-up code then typically passes control to code written in C that ultimately directly or indirectly calls your main() function. Getting to main() is a huge step in your bare-metal adventure!
Next, you need to decide how to support your hardware's I/O devices which in your case include the camera and serial port. How much of the standard C (or C++) library does your image processing require? You might need to add some support for functions like printf() or malloc() that normally need some kind of OS support. A simple "hello world" would be a good thing to try next.
ELLCC has examples of various levels of ARM bare-metal in the examples directory. They range from a simple main() up to and including MMU and TCP/IP support. The source for all of it can be browsed here.
I started writing this before I left for work this morning and didn't have time to finish. Both dwelch and Clifford had good suggestions. A bootloader might make your job a lot simpler and documentation on your hardware is crucial.
First you must realise that without an OS, you are responsible for bringing the board up from reset including configuring the PLL and SDRAM, and also for the driver code for every device on the board you wish to use. To do that required adequate documentation of the board and it devices.
It is possible that you can use the existing bootloader to configure the core and SDRAM, but that may not meet your requirement for the only process running on the board should be your image processing program.
Additionally you will need some means of loading and bootstrapping; again the existing Linux bootstrapper may suit.
It is by no means straightforward and cannot really be described in detail here.
I have coded a project of mine in C on a Windows machine in the software IAR Embedded Workbench IDE. The project compiles and runs fine. I have a couple of printf functions in my code. But the thing is that the project is intended for a microcontroller AT91SAM7X256. I've successfully built my application to run on the sram of the microcontroller, and the application was loaded successfully. But the printf function is being directed to the USART port of the controller (I can only assume), and so I would like to redirect the printf to display the text on my terminal I/O. Does anyone have an idea on how I can do that?
I use the ARM, AVR32 and MSP430 processor versions of the IAR toolchain. In each of these you have to implement your own low level functionality to handle the stdin and stdout streams. The ARM compiler manual has a section on "Standard streams for input and output" which says that you need to write your own version of the __write() function, and it provides an example version where the data is written to a memory mapped LED display.
Knowing IAR I would expect they will have a similar example for your processor/toolchain combination.
I don't know why your printf is being redirected but to do what you want to do I did the following:
First show the console window. (while running debug go to menu View-> Terminal I/O
then stopping the application, go to Project->Options and in Linker-> Library check Include C-SPY debugging support
Be warned that this makes the running of the program considerably slower, than it should be. Comment out all printfs later when finishing your debugging
The standard answer is to select "Semihosted" and "Via semihosting" (Or via SWO -- but I have been using the other.) And "buffered terminal output" for speed under library options 1.
However, I am poking about here because I have a demo program from ST that won't printf to the console and I don't know why -- have many applications that work. So if anyone can remember some detail that gets left out of the standard information feel free to say something...
all you have to do is to #include <stdio.h> and use printf() in your code. For this to work with the debugger console you will have to go to Project options -> Linker -> Output (tab) and in the "Format" section where you have selected "Debug information for C-SPY" you need to have "With I/O emulation modules" checked (this requires "with runtime control modules"). This will make the linker use its special low-level I/O routines (putchar() , getchar() ) which will route it to/from the debug terminal I/O console.
When entering debug mode you get the debug console window displayed by selecting View -> Terminal I/O from the top menu. You will probably notice that if you try to printf too much text it will make the output lag a bit. But it can surely be a handy tool for debugging your application anyway.
(For the curious, you can see in the disassembler that the putchar() / getchar() functions linked into the code when using I/O emulation are just NOP instruction dummy functions. The C-SPY debugger will set a hardware breakpoint in this function, and whenever this breakpoint is reached it will read out the register to read/write the character. The communication overhead causes a small delay for each character. A side-effect of using I/O emulation is that the debugger will reserve one hardware breakpoint for each of these two functions (if you are using them), so you will get fewer hardware breakpoints available to use in your other application debugging.)
You can find some more information about "I/O emulation modules" in the IAR user manual: Help -> 8051 Embedded Workbench User Guide.