I have a STM32 BluePill Board (STM32F103C8 with 8Mhz Quarz) and tried to upload a small blink program made with LibOpenCM3 and FreeRTOS. But for some reason FreeRTOS hangs in vTaskStartScheduler() the sys_tick_handler also doesn't do anything.
I didn't use a debugger and just placed a gpio_reset inside the sys_tick_handler function and after the vTaskStartScheduler call to test if the code gets executed but it didn't seem to do anything and I can't figure out why.
The code is available here: https://gitlab.com/feldim2425/stm32-testing
UPDATE: I debugged with OpenOCD and fount out that it jumps into the hard_fault_handler
UPDATE 2: The UsageFault-Status-Register has the NOCP bit set
Ok I found the issue. Many examples seem to rely on compiler optimization to directly link the vPortSVCHandler, xPortPendSVHandler and xPortSysTickHandler from FreeRTOS into the vector table if you call them inside your own handler vector implementation for sv_call_handler, pend_sv_handler and sys_tick_handler. But that didn't work here, the functions have to be called directly by the processor.
Adding these 3 Lines to the bottom of the FreeRTOSConfig.h file and removing my own function declarations for the vectors fixed the problem:
#define vPortSVCHandler sv_call_handler
#define xPortPendSVHandler pend_sv_handler
#define xPortSysTickHandler sys_tick_handler
The fix is described here: https://www.freertos.org/FreeRTOS_Support_Forum_Archive/January_2012/freertos_LPC1768_FreeRTOS_4964917.html
It is described for CMSIS but the only difference (in this case) are just the names of the vectors/handler functions.
Related
I've looked through both <avr/io.h>, and <avr/iom328p.h> for a macro which defines the ISR macro, as well as the datasheet for the ATmega328P and I have yet to find anything. All I can find is external sources saying that you make an interrupt service routine by writing
ISR (/*<ISR-vector>*/)
{
/* ISR code here */
}
but I haven't found its source/definition anywhere.
The macro is defined in avr/interrupt.h, which you can view for example here (github mirror, not an official source). In case you were looking for it to understand how it works i also recommend you read about interrupt and signal function attributes here, because all that the ISR macro does is define a function with a specific attribute and name.
I'm in the process of transferring the code from STM32L0 to STM32L4. The project was working fine on the L0 but on the L4 when one of the functions is used then... the processor is going immediately into hard fault, straight away after I turn the debug session on (I even don't have to start the program, it starts it immediately and goes into hard fault).
The weird things:
The function that causes the problem is actualy the macro in the __STATIC_INLINE void LL_SPI_Enable(SPI_TypeDef *SPIx) from stm32l4xx_ll_spi.hex: SET_BIT(SPIx->CR1, SPI_CR1_SPE).
The .s file which uses the the LL_SPI_Enable() is not created when I comment out that line containing the function. When the function is there it creates the .s file from the .c file which uses the function.
The LL_SPI_Enable() function exists in many other places and it is fine. There is only one of my functions (defined as static inline __attribute__((__always_inline__)) ) in one file which causes that weird behaviour. There are other functions doing the same thing (turning the SPI on) using the same LL_SPI_Enable() and those are not a problem. It looks like there is only one of my functions which cannot use LL_SPI_Enacle()
The function to disable SPI doesn't cause any issues.
The program doesn't hit even first line of the code, it goes into hard fault immediately.
I thought the scatter file was the problem so I used the default config for my CPU and the result is the same. I also tried different optimization levels and also no change. I don't have any errors from compiler or linker.
Did anybody have something like that?
There is nothing "weird" in it.
If you land immediately (ie before the main function is called) there are usually three possible problems:
Linker file not for your micro
Startup files not for your micro
Wrong register addresses (wrong header files used)
In keil see in the Peripherals -> Core Peripherals -> Fault report.
You will see there the registers and the address of the place there the HF occurred and other information (depending on the actual HF source)
Further reading: www.keil.com/appnotes/files/apnt209.pdf
I am struggling to get my code down to minimal bare bones size! I am using a STM32F0 with only 32k flash and need a good part of the flash for data storage. My code is already at approx 20k flash size! Some of this is due to use of the STM32 HAL functions which I can account for and optimise later if needed.
However, my biggest consumer of flash is all the implicitly included library routines. I can not seem to remove these functions. They are not called anywhere in my code or any HAL code. Functions such as _malloc_r (1.3k Bytes), and __vfiprintf_r (3kB) and many others are using a large part of my flash. I think these are all the libc functions. I do not use these and would like them gone!
Does anybody know how to remove these?
I have tried different optimisation levels and linker options but no luck so far. I have tried -nostdlib and --specs=nosys.specs with no change. If I remove my file with definitions for functions such as _exit I get a linker error suggesting that the library is still included and needs these. Also linker map confirms presence of a lot of unwanted functions!
Any suggestions?
When you are wondering about what takes space, or why functions and libraries have been linked in, generate a map file with cross references - something like "-Wl,-Map=program.map,--cref". Look at the file with a text editor, and you can see why a function like malloc has been included.
Solved... Some of my code included and called assert. The moment I removed assert calls my code size more than halved! I instead used the STM32 HALs assert_param macro that is a light weight assert that just redirects to a user defined function.
It would be helpful if someone could explain to me how gcc decides to include library functions when assert is called? I see that assert.h declares an external function __assert_func. How does the linker know to reference it from a library rather than just say "undefined reference to __asert_func"?
I am trying to build a simple logic analyzer with TM4c123 but anytime when I use the function ROM_.... it appears to be an error( implicit of function ROM_..) Anyone knows why?
for example:
ROM_FPUEnable();
ROM_FPULazyStackingEnable();
// run from crystal, 80 MHz
ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
// enable peripherals
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
// set UART pins
GPIOPinConfigure(0x00000001);
GPIOPinConfigure(0x00000401);
ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
// init PORTB
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
GPIO_PORTB_DIR_R = 0x00;
GPIO_PORTB_DEN_R = 0xff;
// configure uart
ROM_UARTConfigSetExpClk(UART0_BASE, ROM_SysCtlClockGet(), 115200,
(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
All of the function ROM are errors, why? I already include rom.h and rom_map.h
You probably didn't defined your target device.
Try to add something like -DTARGET_IS_TM4C123_RB1 to your Makefile.
This define is necessary in order for the ROM_* symbols be defined.
You are using a combination of driverlib (tivaware) and direct register modification (DRM). Use one or the other, preferably driverlib.
You should actually be using the MAP_ calls instead of ROM_. ROM_ is deprecated but still usable for testing. Don't put ROM_ in production code. I know the examples still use ROM_.
You are missing the header file for ROM anyways. If you want to use ROM_, you need to include driverlib/rom.h. That's why it's complaining about the implicit function call. Any call to a ROM_somethingsomethingdarkside() is not defined. You will also need to include stdint and stdbool, as driverlib uses those c99 types. To use the map calls, you'll need to include driverlib/rom_map.h
You may also need to include driverlib/gpio.h, driverlib/sysctrl.h. Not sure on that. I've never mixed things like you have done, and I always debug using the compiled in driverlib first, then prefixed the driverlib calls with MAP_ after I know things are working. I haven't ever gone back to remove my includes for the compiled in driverlib libraries. The toolchain seems to be smart enough to not compile them in after I stop calling them anyways. Now I kinda want to try that though.
To be clear, ROM_ or MAP_ is calling driverlib calls out of the on chip ROM.
I suspect that you are not sure what the code you are using really is and what it does by the way you're mixing DRM and driverlib libraries. I HIGHLY suggest you take the time to go through the online workshop for the Tiva C. It's a series of short videos and labs that will clear up all of this. I went intentionally neurotically slow and it took me a weekend. You can do it in a day, and it'll be a day well spent. It'll save you that many times over. It's out of date slightly as far as code composer goes, but it's still useable. I have all my students go through it before they start work on this platform.
http://processors.wiki.ti.com/index.php/Getting_Started_with_the_TIVA™_C_Series_TM4C123G_LaunchPad
Edit: yes, and as vitor points out, you also need that define as well.
I would reccommend using "driverlib/gpio.h" and "driverlib/sysctl.h"
for the Pin configuration with TM4C devices
I am working with XC8 1.20 and a PIC18F66K80 and having some trouble with using the pwm.h library. Whenever I open pwm.h, the only functions that are actually being generated (IE, the #ifdef compile time conditionals are returning true) are for PWM1. After tracing through the code, I came to the pconfig.h file and went down to the section regarding the 18F66K80, and it was all being ignored.
The conditional that was returning false is:
#ifdef __18F66K80
In fact, there were no sections that were being compiled. It was like I had no chip selected, even though the project was targeting the 18F66K80. I went into the compiler macro options and add __18F66K80 as a defined macro, and this block suddenly was compiling, giving me access to PWM2-5.
My question is - what is the correct way to tell pconfig.h what chip I am using? My project settings clearly show the PIC18F66K80 as the target device, but pconfig.h was acting like I had no chosen device. By adding this macro, it appears to work, but I have a feeling this is a hack and not the right way to do things.