I would like to know the difference between DisableAllInterrupts and SuspendAllInterrupts in OSEK?
The disable/enable interface is unsuitable for nesting. The suspend/resume can be nested so that if a function suspends and resumes when the caller has already suspended, the interrupts will only be enabled on the outermost resume call.
The documentation also states that suspend saves the "recognition status". It is not clear to me what that means; I have looked throughout the entire document and nowhere does it define that term clearly. I assume that all interrupts that are recognised before are restored after the call. That would (I guess) mean that if you enabled a new interrupt while suspended, the the resume might disable it. Enabling a new interrupt in a disabled section on the other hand would persist after enable. It is less than clear however IMO.
Nested suspend/resume will work as follows:
There will be a counter, that when suspend is called, if the counter is zero, then the interrupts are suspended, the recognition state is saved. In any event the counter is incremented.
When resume is called, the counter is decremented, and if it becomes zero, then the recognition state is restored and interrupts enabled.
The effect of that is if you for example:
Nest-count Interrupts
-----------------------------------------------
0 Enabled
suspend() ; 1 Disabled
suspend() ; 2 Disabled
resume() ; 1 Disabled
suspend() ; 2 Disabled
suspend() ; 3 Disabled
resume() ; 2 Disabled
resume() ; 1 Disabled
resume() ; 0 Enabled
If you are writing a critical section in a function that may be called from some other function you should use suspend/resume. If you use disable/enable in the above scenario it would enable interrupts prematurely:
Interrupts
--------------------------------
Enabled
disable() ; Disabled
enable() ; Enabled
enable() ; Enabled
disable() ; Disabled
disable() ; Disabled
enable() ; Enabled
enable() ; Enabled
enable() ; Enabled
See in the enable/disable the nesting has no effect. You should use nesting if you call functions from a critical section when such functions might also have critical sections within them - to ensure the outer critical section is not terminated prematurely.
Related
The TIM SR register value always be 0x1F, And Can not use to clear the reg.
HAL Lib Always runs into time interrupt really fast, and Can not clear SR register.
How to fix the promble?
Cubemx set
NVIC
`
void TIM3_IRQHandler(void)
{
/* USER CODE BEGIN TIM3_IRQn 0 */
/* USER CODE END TIM3_IRQn 0 */
HAL_TIM_IRQHandler(&htim3);
/* USER CODE BEGIN TIM3_IRQn 1 */
/* USER CODE END TIM3_IRQn 1 */
}
`
`
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if ( htim == &htim3){
__HAL_TIM_CLEAR_FLAG(&htim3,TIM_FLAG_UPDATE) ;
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13) ;
}
}
`
I will base my explanation on STM32F746's TIM3. Timers across STM32 that share number are usually identical or very similar.
TIM3->SR has 0x1F? That's 5 flags set! TIM3 is a general purpose STM32 timer. These 5 flags mean you have counter interrupt and four capture/compare interrupt status flags set at the same time. Something weird is going on. Are you sure you're supposed to have those flags set? Well, if their interrupts are not enabled, it doesn't matter.
You can clear these flags in TIM3->SR by writing zero to the specific position you want to clear and 1 everywhere else. As per reference manual, this register ignores if you write 1. It doesn't set bits when you do that. It only resets when you write zero. So,
TIM3->SR = 0; //clear all interrupt flags
TIM3->SR = ~TIM_SR_UIF; //clear update interrupt flag only
This works because the bits in the reference manual are marked rc_w0 - read, clear by writing zero. If bits in your SR register work differently, you may have to clear them differently. For example, sometimes status register is read-only and you clear it via write to flag clear register. Check reference manual of your MCU.
I have enabled the interrupts for channel set (SETx1) and channel reset (RSTx1) by setting bits RSTx1IE and SET1xIE. I am trying to drive the outputs to active-inactive state via software by writing to SST and RST bits of the TIMERA.
Inside the TIMAISR register I can see the SETx1 and RSTx1 interrupt event flags are set. This indicates the fact that output active-inactive state changes are driving the interrupts.
But I cannot see the respective ISR HRTIM1_TIMA_IRQHandler getting hit. While other interrupts are working fine and I can see the ISR gets executed in those situations, it is only for the SETx1 and RSTx1/SETx2 and RSTx2 I see this problem.
Is there any settings I could me missing that might cause this issue?
Image that shows global interrupt for TimerA is enabled in NVIC
Image that shows HRTIM peripheral interrupt are enabled for SET and RST
Image that shows Interrupt occured inside HRTIM peripheral for SET and RST
I am new to stm32, I tried to implement an interrupt using the user button of stm32F407VG.
I added a HAL_Delay() inside the interrupt function.
When the button is pressed, the Interrupt service routine start executing but it never comes back to the main() function.
That's the part of the code which is responsible for the interrupt:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin==GPIO_PIN_0)
{
if(prev_val==false)
{
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14, 1);
prev_val=true;
}
else
{
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14, 0);
prev_val = false;
}
HAL_Delay(1000);
}
}
Take care: If using the default HAL settings provided by ST, the priority for SysTick IRQ is set to 15 when calling HAL_Init().
So you have to change that in the stm32f7xx_hal_conf.h file or by using the HAL_InitTick(TickPriority) function.
See also Usermanual page 31:
HAL_Delay(). this function implements a delay (expressed in milliseconds) using the SysTick timer.
Care must be taken when using HAL_Delay() since this function provides an accurate delay (expressed in
milliseconds) based on a variable incremented in SysTick ISR. This means that if HAL_Delay() is called from
a peripheral ISR, then the SysTick interrupt must have highest priority (numerically lower) than the
peripheral interrupt, otherwise the caller ISR is blocked.
I found the way to deal with it, my interrupt priority was 0 by default. And HAL_Delay() also has the priority 0.
So I reduced the priority of the external interrupt and set it to 1.
Now its working fine
In short, SLAK bit won't reset when SLEEP bit is manually reset. In details :
I am trying to achieve a successful transmission in loopback mode before venturing into making a network. I had it working at a point after a lot of documentation reading, but now I have a new issue. (Sadly I do not remember what I changed, played with the timings maybe)
After setting the peripheral to loopback and providing coherent bit timing values (so I may have played with them but they are back to being ok), I generate the code with Cube. This implies that the flow should first exit the sleep mode, enter the init mode, do the settings, exit the init mode, and start normal mode. According to the reference manual :
If software requests entry to initialization mode by setting the INRQ bit while bxCAN is in
Sleep mode, it must also clear the SLEEP bit. [...] After the SLEEP bit has been cleared, Sleep mode is exited once bxCAN has synchronized
with the CAN bus [...]. The Sleep mode is exited
once the SLAK bit has been cleared by hardware
and
To synchronize, bxCAN waits until the CAN bus is idle, this means 11
consecutive recessive bits have been monitored on CANRX.
According to wiki
A 0 data bit encodes a dominant state, while a 1 data bit encodes a recessive state
So
Checking the code generated by Cube this is exactly what is happening. I pasted here the essential part from stm32f4xx_hal_can.c :
HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef *hcan)
{
[...]
/* Exit from sleep mode */
CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_SLEEP);
/* Get tick */
tickstart = HAL_GetTick();
/* Check Sleep mode leave acknowledge */
while ((hcan->Instance->MSR & CAN_MSR_SLAK) != 0U)
{
if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE)
{
[...]
/*Error*/
}
}
/* Request initialisation */
SET_BIT(hcan->Instance->MCR, CAN_MCR_INRQ);
/* Get tick */
tickstart = HAL_GetTick();
/* Wait initialisation acknowledge */
while ((hcan->Instance->MSR & CAN_MSR_INAK) == 0U)
{
if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE)
{
[...]
/*Error*/
}
The SLEEP bit of CAN_MSR is reset and waits for the SLAK bit from CAN_MSR to be reset by the hardware. CAN_TIMEOUT_VALUE is set to 10, basically giving time for the 11 recessive bits to settle in.
And this is where I am stuck. SLACK would not reset... I tried to remove if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE) so that the MCU waits indefinitely for a SLAK reset. Did not help.
Looking at the CAN_MSR RX register, giving the current value on RX, while waiting for SLACK to change, I noticed that it is always at 0. So I tried to set GPIOs as pull-up and pull-downs for RX and TX, but I think it has no effect since, in loopback mode, RX of bxCAN is isolated from GPIOs :) This meaning also, that the issue should not be on the hardware side (like wiring and stuff, external things, not internal hardware). Leading me to believe that something is wrong during the global HAL_Init() or MX_GPIO_Init() or other stuff, but since it is generated by Cube and I did not change anything, I don't see how it could have an effect on SLAK not going away.
My idea was maybe to do a software reset, on something, but I don't know where this path will lead me since powering off and on the chip do not resolve the issue...
I want to understand meaning of the following function mode definition, there is explanation in the library. But I don't understand that because explanations are very short and not enough. I searched on the net I couldnt find any information about.
CAN_InitStructure.CAN_TTCM = DISABLE;
CAN_InitStructure.CAN_ABOM = DISABLE;
CAN_InitStructure.CAN_AWUM = DISABLE;
CAN_InitStructure.CAN_NART = ENABLE;
CAN_InitStructure.CAN_RFLM = DISABLE;
CAN_InitStructure.CAN_TXFP = ENABLE;
These are the names of the bits located in the CAN master control register (CAN_MCR). So, the proper source for their meaning is the reference manual. My following answer will be somewhat copy & paste from the reference manual, but I will try to explain these bits in detail.
TTCM (Time triggered communication mode): This bit activates the Time Triggered Communication (TTCAN) mode, which is an extension to the CAN standard. I don't know much about TTCAN, but as I understand, it assigns time windows to messages to satisfy some real-time requirements. So, normally this bit should remain 0.
ABOM (Automatic bus-off management): If the transmit error counter (TEC) becomes greater than 255, the CAN hardware switches to bus-off state. To recover, it must wait for the recovery sequence, 128 occurrences of 11 consecutive recessive bits. Only after that, the CAN hardware may return to the normal operating state. This bit controls the returning behavior. If it's 1, returning to normal state is automatic. Otherwise, software should make the request, provided that the recovery sequence has been observed.
AWUM (Automatic wakeup mode): The CAN module can be in one of 3 modes: Initialization mode, normal mode or sleep (low power) mode. Sleep mode is requested by the software. However, you have 2 options to exit sleep mode. If this bit is 0, then you have to exit sleep mode manually. You may enable CAN wakeup interrupt to inform you about bus activity, then exit the sleep mode in ISR. But if this bit is 1, the hardware returns to normal mode automatically when it detects bus activity.
NART (No automatic retransmission): Normally, CAN hardware retries to transmit a message if its previous attempts fail, because of arbitration lost etc. But if you make this bit 1, the transmitter does not retry. This is required when you use Time Triggered Communication (TTCAN). Otherwise, you should keep this bit 0.
RFLM (Receive FIFO locked mode): Your receive mailboxes have 3 levels depth, meaning that they can store maximum 3 messages before they are overrun. This bit controls what happens in case of mailbox overrun. Default behavior is to keep the oldest 2 messages and the newest one. For example, if you received 5 messages, the buffer keeps the messages 1, 2 & 5. However, if you make this bit 1, the mailbox keeps the messages 1, 2 & 3 and discards the new arrivals.
TXFP (Transmit FIFO priority): You have 3 transmit mailboxes. When you fill more than one, the hardware must decide which one to transmit first. Normally, one can assume that a message with a lower ID number is more important and should be transmitted first. But if you want to transfer them in a first-comes-first-served fashion for some reason, you need to make this bit 1. Of course, this is just a local priority. On the physical bus, the messages with lower ID always have priority.