[英]STM32F103 priorities to handle nested interrupts
I could find a problem related to NVIC_Init in STM32F10x library related to priorities to handle nested interrupts. 我可以在STM32F10x库中找到与NVIC_Init有关的问题,该问题与处理嵌套中断的优先级有关。 We know that any interrupt with a priority value equal or higher than BASEPRI ( 11 in our case) can call FromISR() FreeRTOS API functions.
我们知道,任何优先级值等于或高于BASEPRI(在我们的例子中为11)的中断都可以调用FromISR()FreeRTOS API函数。
FreeRTOS uses 15 level ( the lowest priority). FreeRTOS使用15级(最低优先级)。
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY 15
In other words, FreeRTOS allows us to call API fuctions ( see xQueueSendToBackFromISR) from ISR with 15-11 priority. 换句话说,FreeRTOS允许我们以15-11优先级从ISR调用API函数(请参阅xQueueSendToBackFromISR)。 When we initialize the NVIC we use level #11
初始化NVIC时,使用级别11
#define WRTU2_DMA1_SPI2_IRQ_PRIORITY (configLIBRARY_KERNEL_INTERRUPT_PRIORITY-4*)
/* DMA1 Channel4 interrupt setting */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = WRTU2_DMA1_SPI2_IRQ_PRIORITY;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = WRTU2_DMA1_SPI2_IRQ_PRIORITY;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
So, we should be OK. 因此,我们应该可以。 But the problem exists.
但是问题仍然存在。 I decided to check NVIC_Init.
我决定检查NVIC_Init。
According to the information from STM32 datasheet the priority register is 0xe000e40e ( NVIC channel 14 belongs to DMA1_Channel4 interrupts). 根据STM32数据表中的信息,优先级寄存器为0xe000e40e (NVIC通道14属于DMA1_Channel4中断)。
And I could read 0x00 from that register after NVIC was initialized. 在NVIC初始化之后,我可以从该寄存器读取0x00 。 It means NVIC channel #14 has the highest priority in the system.
这意味着NVIC通道#14在系统中具有最高优先级。
And it causes all problems. 这会导致所有问题。
I added the simplest fix NVIC->IP[DMA1_Channel4_IRQn] = 0xF0; 我添加了最简单的修复程序NVIC-> IP [DMA1_Channel4_IRQn] = 0xF0; And the system does not fail anymore.
并且系统不再失败。 So, our current problem is solved.
这样,我们当前的问题就解决了。
Of course, I tried to analyze what happens in NVIC_Init 当然,我试图分析NVIC_Init中发生的情况
**
* @brief Initializes the NVIC peripheral according to the specified
* parameters in the NVIC_InitStruct.
* @param NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains
* the configuration information for the specified NVIC peripheral.
* @retval None
*/
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
{
uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));
assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority));
assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));
if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)
{
/* Compute the Corresponding IRQ Priority --------------------------------*/
tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
tmppre = (0x4 - tmppriority);
tmpsub = tmpsub >> tmppriority;
tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;
tmppriority |= NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;
tmppriority = tmppriority << 0x04;
NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;
/* Enable the Selected IRQ Channels --------------------------------------*/
NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
(uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
}
else
{
/* Disable the Selected IRQ Channels -------------------------------------*/
NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
(uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
}
}
So, I added the similar test code to my application to see how it converts all values 因此,我向应用程序中添加了类似的测试代码,以查看其如何转换所有值
uint32_t NVIC_IRQChannelPreemptionPriority=0xFF,NVIC_IRQChannelSubPriority=0xFF;
int32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;
tprintf("\n\rSCB->AIRCR=0x%08x",SCB->AIRCR);
tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
tprintf("\n\rtmppriority=0x%08x",tmppriority);
tmppre = (0x4 - tmppriority);
tmpsub = tmpsub >> tmppriority;
tprintf("\n\rtmppre=0x%08x",tmppre);
tprintf("\n\rtmpsub=0x%08x",tmpsub);
tmppriority = (uint32_t)NVIC_IRQChannelPreemptionPriority << tmppre;
tmppriority |= NVIC_IRQChannelSubPriority & tmpsub;
tmppriority = tmppriority << 0x04;
tprintf("\n\rtmppriority=0x%08x",tmppriority);
There is a log 有一个日志
SCB->AIRCR=0xfa050000
tmppriority=0x00000007
tmppre=0xfffffffd
tmpsub=0x00000000
tmppriority=0x00000000
Note, even I specify 0xFF for both input parameters it returns 0x00. 注意,即使我为两个输入参数都指定了0xFF,它也会返回0x00。
I am really surprised about that behavior. 我真的为这种行为感到惊讶。 This is a library function.
这是一个库函数。
People use it for many years. 人们使用了很多年。 So, I am really confused I can find find the problem in that function.
因此,我真的很困惑,我无法找到该函数中的问题。
Maybe it is related to Application interrupt and reset control register (SCB_AIRCR) Address offset: 0x0C Reset value: 0xFA05 0000 Required privilege: Privileged The AIRCR provides priority grouping control for the exception model, endian status for data accesses, and reset control of the system. 可能与应用程序中断和复位控制寄存器(SCB_AIRCR)有关。地址偏移量:0x0C复位值:0xFA05 0000所需特权:Privileged AIRCR为异常模型提供优先级分组控制,为数据访问提供字节顺序状态,并为系统提供复位控制。
Note, in the library sources I can see #define AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000)
注意,在库源代码中,我可以看到
#define AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000)
So, it looks like we have some kind of BIG vs LITTLE ENDIAN byte order in the 16-bit nibble. 因此,看起来我们在16位半字节中具有某种BIG vs LITTLE ENDIAN字节顺序。
Do you have any suggestion or knowledge about the problem? 您对此问题有任何建议或知识吗?
I found the problem, the problem is I should use NVIC_SetPriorityGrouping(3); 我发现了问题,问题是我应该使用NVIC_SetPriorityGrouping(3); as 3 for the cortex-m3.
对于cortex-m3为3。
then it provides 4-bit preemptive priority and 0 bit for subpriority. 然后提供4位抢占优先级和0位子优先级。 At final when I initiliase like that it works as I expected.
最后,当我像这样初始化时,它会按预期工作。
/* DMA1 Channel4 interrupt setting */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 11;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.