Good day, i have a problem with the loading of
firmware of the mc stm32f205rg. i used function
boot_softs to enter to the bootloader , which is
situated in system memory.
void boot_softs() {
volatile uint32_t addr = 0x1FFF0000;
void (*SysMemBootJump)(void);
SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4)));
HAL_RCC_DeInit();
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
_disable_irq();
SYSCFG->MEMRMP = 0x01;
__set_MSP(*(__IO uint32_t*)0x20001000);
SysMemBootJump();
}
But during the checking with the help of Flash loader
demonstrator program i have found out that mc dont
enter in firmware reloading state.
I rechecked the same function on stm32f207 with no
changes and stm32f103c8 with address of programm
beginning changed.in both cases everything works
correctly and mc reloades.
Maybe someone faced such a problem and can help me
with this problem. Thanks in advance.
I don't think system memory can be accessed via code, You need to make changes to the external PINs that are responsible for mode selection. M0 and M1.
Upon selecting these pins , you may enter in system mode of your STM32. Here is one link that explains how to send command to bootloader. Click here!
You have to check in system bootloader address because it varies depending on MCU.
So check out this documentation from ST: in system bootloader guide from ST
As I see you are using wrong RAM address.
Part from bootloader cook book:
Moreover, there should be a trigger for entering to system bootloader. As I understand you are using software call method from your main application. This method is not reliable if BOOT pins of MCU are uncontrolled because if serial line or updating software fails you will loose main application and you will be unable to update device. Than you'll need programmer.
So updating, overwriting software which has system bootloader call is unsafe updating method. I would suggest it only as a own usage update method.
To have safety you should control BOOT pins.
Or implement mini custom bootloader which could be triggered by button (to start main app) and before triggering that mini bootloader would stay quiet and let system bootloader update main app. Update can't touch mini bootloader memory, this own customized bootloader should be untouched while update. But that is a suggestion.
Easer way to take control on update is to control BOOT pins.
For example:
put 3.3V or GND (depends on MCU) on BOOT pins with jumpers , set power and than device automatically will enter to system bootloader.
After update remove jumpers, and after power reset device will enter to your new update application.
That's all.
If you do not have BOOT0, BOOT1 pins control from hardware. I strongly recommending you to check those pins control.
There is a guide from ST about BOOT pins: reference manual
Part of description from reference manual:
Related
I'm trying to play a note through the speaker of my board. Currently, I have an interrupt as follows:
void sampleISR(void) {
static uint32_t phaseAcc = 0;
phaseAcc += a; //this `a` is modified outside
analogWrite(OUTR_PIN, phaseAcc);
}
It is attached in the setup() function as follows:
TIM_TypeDef *Instance = TIM1;
HardwareTimer *sampleTimer = new HardwareTimer(Instance);
sampleTimer->setOverflow(22000, HERTZ_FORMAT);
sampleTimer->attachInterrupt(sampleISR);
sampleTimer->resume();
I am trying to use a DMA to reduce the strain on my CPU and also increase the sampling rate (making the 22000 bigger). I am trying to use this as my board supports it, however, I am conceptually confused as to what the transformation entails. Currently, I have an interrupt which modifies the analogWrite value to pin OUTR_PIN every 22000 samples. My current understanding is that a DMA is a tool that connects memory to peripherals or memory to memory, in such a way that data can be transferred without the need for the CPU to do it. However, I am uncertain as to what that means in the current context. Would I need to create a memory-to-periphery DMA where the source is memory (my phaseAcc variable and the output is a periphery (my OUTR_PIN?). I am not sure how I would go around doing this, or if what I described above is correct. I am trying to directly mimic the functionality described above.
I am using a board from the stm32 family.
To drive a speaker you normally use the DAC (digital to analog converter) with a PWM signal (pulse width modulation) On STM32 the DAC / PWM can be linked with DMA (Direct Memory Access), see i.e. HAL_TIM_PWM_Start_DMA from the HAL library, in https://deepbluembedded.com/stm32-dac-sine-wave-generation-stm32-dac-dma-timer-example/ and https://community.st.com/s/question/0D50X0000AAJMUVSQ5/start-pwm-with-dma-haltimpwmstartdma-results-in-hardfault is example code, however you should not drive a speaker with a pure sine wave
For details see also this Application Note : https://www.st.com/resource/en/application_note/cd00259245-audio-and-waveform-generation-using-the-dac-in-stm32-products-stmicroelectronics.pdf
To generate a desired waveform you have to adapt the waveform lookup table described in https://deepbluembedded.com/stm32-dac-sine-wave-generation-stm32-dac-dma-timer-example/
I am currently playing with L152C Discovery board and trying to make simple clock that would use the RTC build into the STM32 and onboard Glass LCD with LCD HAL library configured via CubeMX.
But I am currently facing a problem I can't get my head around:
CubeMX does not have an option to enable segment mux in the LCD_CR register. I would like to enable it, because it would make the segment mapping easier.
So I thought, fine, I will make an direct register manipulation, enabling the mux (bit 7 in the LCD_CR).
I used the command LCD->CR |= LCD_CR_MUX_SEG; But even after executing the command, the MUX_SEG bit is still zero. (I checked in the debug session with command stepping and SFRs memory map)
Is there something that I am doing wrong? Or is there another way to change init parameters that CubeMX configured but does not have graphical implementation of this settings option?
The application is using FreeRTOS and I executed LCD->CR |= LCD_CR_MUX_SEG; after HAL_LCD_Init(&hlcd); so I sappose that the LCD peripheral clock is running (and segments are updating).
I recorded a short video showing this problem:
https://youtu.be/0X6Zu5EPudU
To be honest, I am not skilled at direct register manipulation, so I am probably doing something wrong.
Any help would be appreciated!😇
As #KIIV said:
RM0038 Liquid crystal display controller (LCD) Note: The VSEL, MUX_SEG, BIAS and DUTY bits are write protected when the LCD is enabled (ENS bit in LCD_SR to 1).
The LCD must be disabled when making changes to the above registers.
I have write a bootloader to jump into my app.
First I have try with a simple blinky-led app => I am able to jump into the app from the bootloader.
Now I want to jump into my real app. The app is working well alone but when I jump into it from my bootloader the app crash as soon as the interrupts are enabled, my jumping code :
__disable_irq();
SCB->VTOR = (uint32_t)0x0800BA00;
JumpAddress = *(__IO uint32_t*) (0X0800BA04);
JumpToApplication = (pFunction) JumpAddress;
__set_MSP(*(__IO uint32_t*) 0X0800BA00);
JumpToApplication();
I don't know what is wrong and why the activation of interruptions crash the app.
Thank you for your help
Before you jump to the application, you should deinitialize everything that you've initialized in the bootloader. If your bootloader uses USART with interrupts, you should disable this USART (for example using RCC->AHBxRST/RCC->APBxRST registers) and disable its interrupts. You should also jump to your application with interrupts enabled. Your application should get the chip just as it would be after a normal reset.
If your application uses this crap code from ST called SPL or HAL, then make sure that this code does NOT reset SCB->VTOR back to 0 or 0x8000000, because normally it does that in SystemInit(), which is called from Reset_Handler(), before main().
BTW - are you absolutely sure about the address of your application? You usually put the application at the page boundary, while your code does not indicate that - 0x800ba00 (46.5kB) is pretty far from the closest page boundaries 32kB and 48kB...
set clock setting of boot code & application code same
I am using PIC16F877a and I need program reset without using button. When I looked at datasheet and referance designs, there is a button on MLCR pin. If button was pushed, MCU was reset. But I need reset that can control with C code, I don't want to use reset button. Is there another way to do it?
PIC 8-bit MCUS have a software reset assembly instruction:
RESET
http://microchip.wikidot.com/8bit:rst
You will have to use inline assembly. I've never used inline assembly for a PIC, but from this page it looks like this is the correct syntax for MPLAB:
void soft_reset(void)
{
_asm
reset
_endasm
}
Do note that, as the linked page states, an external watchdog timer is generally a better way to trigger a full system reset. With a soft reset, external devices are not also reset. With an external WDT, you simply stop petting the watchdog, and then it resets the whole board.
The format for MPLABX XC16 (assuming that this is the compiler you are using) is:
__asm__ volatile ("reset");
Depending on your processor, you can also examine the contents of the RCON register on startup to find out the cause of the reset (MCLR, software, watchdog timer, brownout, etc.)
For XC8, use #asm and #endasm. Using the example from the XC8 manual
#asm
RESET
#endasm
// do it again the other way...
asm("RESET");
A microcontroller needs to be reset to get to a known state before program execution. Reset is typically generated by hardware signal from external sources, for example, you might find a reset button on the development board. Most microcontroller devices have an input pin for reset.
I have splitted software into two parts: Bootloader(without RTX), Application image with RTX.
But the bootloader could not load the application image with RTX.
The Flash settings are:
--------------------------------------------------------------------
start address size
IROM 1: 0x08000000 0x2800 - Bootloader (without RTX)
IROM 2: 0x08002800 0xD000 - Application Image (with RTX)
I have test 3 ways:
(1) Use another App without RTX. The bootloader could load the app successfully.
(2) Change the application with RTX project IROM setting. I change the application project IROM start address from 0x08002800 to 0x08000000. And I download the application image into flash from the address 0x08000000. Ihe image could run from 0x08000000 successfully.
(3) The application image IROM start address setting is 0x08002800. After downloading bootloader and app image into flash, I debug the app project in keil step by step. I found that there is a "osTimerthread stack overflow" error. Then the main thread stack is also overflowed. I have tried to increase the stack size, but it doesn't work.
I found that the app starks in the RTX kernel switching. All threads are in the waiting state, and are not running.
Ps, when I am debugging in the keil,test item(2) also have stack overflow errors during kernel initialization. The item(2) works fine till now. So I just put any information needed here.
This is the debugging picture for item (3).
Are you actually changing the linker script to link starting at 0x08002800 when using the bootloader or just loading the application (linked at 0x08000000) at an offset of 0x2800? Double check this (look in the map file) for your linked output to ensure that all your symbols are not linked in the 0x08000000 - 0x08002800 range.
Additionally, make sure you are using the correct entry point and stack pointer. The application's stack pointer should be at 0x08002800, and the reset vector will be at 0x08002804. Your bootloader will need to setup the MSP register with the correct stack pointer before jumping to the application. Here is some example code from ST's USB DFU bootloader:
typedef void (*pFunction)(void);
pFunction JumpToApplication;
uint32_t JumpAddress;
/* Jump to user application */
JumpAddress = *(__IO uint32_t*) (USBD_DFU_APP_DEFAULT_ADD + 4);
JumpToApplication = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) USBD_DFU_APP_DEFAULT_ADD);
JumpToApplication();
Additionally, depending on how much your bootloader configures before jumping to the application, you may need to 'deconfigure' certain peripherals. As an example, if you setup your clocks in the bootloader before deciding to jump to the application, you may run into problems in your application if it assumes that the clocks are in the default configuration already. Similar things can happen with the NVIC and SysTick if your bootloader is using these before jumping to the application.
Lastly, along the same lines as the previous section, the application may be making assumptions about the state of peripherals being default, but it also may be making assumptions that the peripheral defaults are correct. For example: SCB->VTOR has a default value (I believe it is always 0x00000000), and this points to the vector table. Your bootloader will be linked to have its vector table at that location. You'll need to make sure that when your application is starting up, it updates the VTOR register to point to the actual location of its vector table.
Hopefully one of these sections helps you identify the problem.