2020-03-03 11:54 PM
Hello community!
My mcu is STM32H743IIT6 tqsp176 from blue waveshare board. I create a new project from Cube with HAL. Then I make the simplest flashing cycle of the LED:
volatile unsigned long x = 0;
while (1)
{
while (x++ < 2000000) {}
x = 0;
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_0, GPIO_PIN_RESET);
while (x++ < 2000000) {}
x = 0;
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_0, GPIO_PIN_SET);
}
Any changes in code result in accidental change in frequency and DUTY CYCLE. For example:
1) When I make variable x global or local.
2) When i put beforce blink cycle this line HAL_GPIO_WritePin(GPIOI, GPIO_PIN_0, GPIO_PIN_RESET);
3) When i add new variable such Y to cycle:
volatile unsigned long x = 0;
volatile unsigned long y = 0;
while (1)
{
while (x++ < 2000000) {}
y = x;
x = 0;
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_0, GPIO_PIN_RESET);
while (x++ < 2000000) {}
y = x;
x = 0;
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_0, GPIO_PIN_SET);
}
In this case frequesy change in random range. Can get X times higher, and can get X times lower. Duty cycle can become 10% / 90% or 30% / 70% and other.
4) When i put some code before this cycle frequency and duty cycle also change!!!
5) Even just when I move some code in places!!!
volatile unsigned long y = 0; // <<<<<<< declare first
volatile unsigned long x = 0;
while (1)
{
x = 0; // << move x here
while (x++ < 2000000) {}
y = x;
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_0, GPIO_PIN_RESET);
x = 0; // << move x here
while (x++ < 2000000) {}
y = x;
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_0, GPIO_PIN_SET);
}
Absolutely any changes in code result in accidental change in frequency and DUTY CYCLE.
I try mcu work on HSE, PLL, HSI... there is no difference. I try keil compiler v5 & v6.. no difference. I try to create project without CUBE and HAL ... there is no difference. I try any dividers and clocks ... there is no difference.
MCU broken?
2020-03-04 12:13 AM
Citing differences between busy-wait loops is not really a bug report.
Compare the resulting assembler code if you want to know what happens.
For a stable PWM signal, use a timer peripheral.
2020-03-04 12:16 AM
These high-performance MCUs have loads of things that make them faster - several caches, FLASH memory pre-fetchers, dual execution paths (and maybe a few I've forgotten).
One consequence is that timings are not deterministic.
Things like where in memory program code happens to reside does make a difference. Instruction fetches are probably done on a 64-bit width bus. That can store up to four 16-bit thumb instructions. If you jump to the first of these instructions, as soon as the memory-fetch is complete for that instruction, the next three are immediately available and can be executed without further delay. But if you jump to the last of these four, the processor will have to wait after executing that one for the next four instructions to be fetched.
The arm cortex m7 has a longer pipeline than m4, so although m7 can run at a faster clock frequency than m4, branches have to flush the execution pipeline so they have a higher penalty. Tight loops like the examples in your code are not the sort of thing that the processor is optimised for. ST provide many timers to allow you to set up delays (while the the processor goes and does something else useful during the delay, or even goes to sleep to save power).
I do not regard the measurements you give as signs of a broken MCU.
Hope this helps,
Danish
2020-03-04 12:17 AM
I not need stable PWM signal. It simple "hello word" project and it doesnt work!
Before STM32H7 I worked with F1, F2, F4, PIC16, PIC18, PIC24, PIC32, AVR microcontrollers and all of them ran this program expected correctly!
2020-03-04 01:18 AM
Forget software delay.
I used a timer and in it interrupt handler i toggle led pin. It did not help!
unsigned char flag = 0;
void TIM8_BRK_TIM12_IRQHandler (void)
{
if (TIM12->SR & 1UL)
{
TIM12->SR = 0;
if (flag)
{
H12_ON;
flag = 0;
}
else
{
H12_OFF;
flag = 1;
}
}
}
int main (void)
{
RCC->APB1LENR |= RCC_APB1LENR_TIM12EN;
TIM12->ARR = 10000;
TIM12->DIER |= TIM_DIER_UIE;
TIM12->PSC = 1000;
TIM12->CR1 |= TIM_CR1_URS;
TIM12->CR1 |= TIM_CR1_CEN;
// timer configured for 0.1s period with 400 MHz clock core
//LED_ON;
NVIC_EnableIRQ(TIM8_BRK_TIM12_IRQn);
__enable_irq();
while (1)
{
}
}
Then i uncomment // LED_ON; before main cycle!!
It is norm?
2020-03-04 01:27 AM
> It simple "hello word" project and it doesnt work!
It's neither "simple hello world", nor does it "not work".
> Before STM32H7 I worked with F1, F2, F4, PIC16, PIC18, PIC24, PIC32, AVR microcontrollers and all of them ran this program expected correctly!
Specify "correctly".
2020-03-04 01:30 AM
Did you check the generated code ?
> unsigned char flag = 0;
> ...
> if (flag)
Decent compilers tend to optimize out such constructs.
Try "volatile".
2020-03-04 01:40 AM
I tried this many times. There 's no difference between volatile there or not.
2020-03-04 03:14 AM
Did you check that the rest of the code works as supposed, i.e. do you ever hit the interrupt handler ?
And with the intended timing ?
2020-03-04 04:55 AM
That 's the whole code. There is nothing any more. The MCU runs RCC, GPIO and TIMER12 with interrupt.