分类目录归档:STM32

转载——SysTick中断优先级

原文链接:https://www.cnblogs.com/Rainingday/p/14648048.html

查看stm32的SysTick中断的优先级,比外设中断优先级高吗?

默认SysTick中断优先级

 1 //core_cm4.h
 2 
 3 __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
 4 {
 5   if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); }    /* Reload value impossible */
 6 
 7   SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */
 8   NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
 9   SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
10   SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
11                    SysTick_CTRL_TICKINT_Msk   |
12                    SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */
13   return (0UL);                                                     /* Function successful */
14 }

第8行设置了SysTick中断的优先级,

#define __NVIC_PRIO_BITS          4       /*!< STM32F4XX uses 4 Bits for the Priority Levels */

在看NVIC_SetPriority函数:NVIC_SetPriority对中断分了类,分内核中断和外设中断,内核外设中断枚举值小于0,普通外设>=0。其中,SysTick_IRQn = -1。

1 __STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
2 {
3   if((int32_t)IRQn < 0) {
4     SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8 - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
5   }
6   else {
7     NVIC->IP[((uint32_t)(int32_t)IRQn)]               = (uint8_t)((priority << (8 - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
8   }
9 }

因为SysTick属于内核外设,跟普通外设的中断优先级有些区别,并没有抢占优先级和子优先级的说法。在STM32F4中,内核外设的中断优先级由内核SCB这个外设的寄存器:SHPRx(x=1.2.3)来配置。有关SHPRx寄存器的详细描述可参考《Cortex-M4内核编程手册》4.4.8章节。下面我们简单介绍下这个寄存器。

 SPRH1-SPRH3是一个32位的寄存器,但是只能通过字节访问,每8个字段控制着一个内核外设的中断优先级的配置。在STM32F4中,只有位7:4这高四位有效,低四位没有用到,所以内核外设的中断优先级可编程为:0~15,只有16个可编程优先级,数值越小,优先级越高。如果软件优先级配置相同,那就根据他们在中断向量表里面的位置编号来决定优先级大小,编号越小,优先级越高。

 在SysTick_Config中,配置优先级为(1UL << __NVIC_PRIO_BITS) – 1UL),其中宏__NVIC_PRIO_BITS为4,那计算结果就等于15,可以看出SysTick此时设置的优先级在内核外设中是最低的。

SysTick和外设中断的优先级大小

但是,问题来了,如果我同时使用了systick和片上外设呢?而且片上外设也刚好需要使用中断,那systick的中断优先级跟外设的中断优先级怎么设置?会不会因为systick是内核里面的外设,所以它的中断优先级就一定比内核之外的外设的优先级高?

从《STM32中断应用概览》这章我们知道,外设在设置中断优先级的时候,首先要分组,然后设置抢占优先级和子优先级。而systick这类内核的外设在配置的时候,只需要配置一个寄存器即可,取值范围为0~15。既然配置方法不同,那如何区分两者的优先级?下面举例说明。
比如配置一个外设的中断优先级分组为2,抢占优先级为1,子优先级也为1,systick的优先级为固件库默认配置的15。当我们比较内核外设和片上外设的中断优先级的时候,我们只需要抓住NVIC的中断优先级分组不仅对片上外设有效,同样对内核的外设也有效。我们把systick的优先级15转换成二进制值就是1111(0b),又因为NVIC的优先级分组2,
那么前两位的11(0b)就是3,后两位的11(0b)也是3。无论从抢占还是子优先级都比我们设定的外设的优先级低。

如果当两个的软件优先级都配置成一样,那么就比较他们在中断向量表中的硬件编号,编号越小,优先级越高。

Jlink V9固件修复

参考链接:
https://blog.csdn.net/qq_39738885/article/details/102530414

https://blog.csdn.net/yekui6254/article/details/85272767

https://blog.csdn.net/qq_26904271/article/details/82726657

https://blog.csdn.net/yunjie167/article/details/117998428
https://www.cnblogs.com/xiaoheikkkk/articles/11193741.html
http://blog.chinaunix.net/uid-20788517-id-263475.html

一、起因

起因是在淘宝购买的Jlink,下载程序的时候会弹出警告

然后有时MDK会异常退出。

继续阅读

stm8l timer 设置问题

系统时钟配置为16M,程序使用TIMER4做为系统定时器,使用如下配置
TIM4_TimeBaseInit(TIM4_Prescaler_16, 99); //100us
程序可以正常运行。

我想把定时器的周期改为10us,使delay()的精度达到10us,
TIM4_TimeBaseInit(TIM4_Prescaler_16, 9); //10us
这样修改之后,发现系统不能正常运行了,程序启动的打印信息都没有。我一度怀疑是程序跑飞了!

经过排查发现是TIMER的中断响应太快,占用了系统的全部资源,主程序的运行完全被TIMER中断打断了。我测试在TIMER中断里面点灯操作是功能正常的。

STM32 SAI问题

STM32F446 SAI blockA和blockB配置为从模式,如果MCU先启动SAI,再打开音频芯片SAI时钟信号,此时MCU不能进入DMA中断,采集不到数据。用Jlink复位一下MCU,SAI接口的数据采集和发送才正常。不知道这个问题是什么原因。

解决方法有2种:1.MCU启动先不使能SAI,把音频芯片SAI时钟打开后再启动MCU SAI;2.把MCU的SAI配置为主模式。

但是对于这个问题还是感到很奇怪。

关于数组清零

不要使用赋值方法清零。对于16位数组,或者32位数组,赋值清零并没有把所有位都置零。

int32_t mix_data_new[SAI_SLOTS_SIZE][2] = {0};
#if 0
for (j = 0; j < 2; j++)
{
for (k = 0; k < SAI_SLOTS_SIZE; k++)
{
mix_data_new[j][k] = 0;
}
}
#endif

使用memset清零,可以确保每个数组中的每一位都被清零。
memset(mix_data_new, 0, sizeof(mix_data_new));

奇怪的问题

第1段:
int16_t data;
const char pcm_data2[] = {…};

data = pcm_data2[i];
data += pcm_data2[i+1]<<8;

第2段:
data = ((int16_t)pcm_data2[i+1] << 8 + pcm_data2[i]);

很奇怪,上面2段代码,在STM32F401上用MDK编译出来执行的结果不一样。第1段执行出来的结果是正确的,第2段执行出来的结果是错误的,并且不知道是怎么算出来的。

 

 

转载——关于STM32 SPI NSS的讨论

原文链接:https://www.cnblogs.com/shangdawei/p/4756415.html

NSS分为内部引脚和外部引脚。

NSS外部引脚可以作为输入信号或者输出信号,

输入信号一般用作硬件方式从机的片选,

而输出信号一般用于主SPI去片选与之相连的从SPI。

NSS从设备选择有两种模式:

1、软件模式

可以通过设置SPI_CR1寄存器的SSM位来使能这种模式,当它为1时,NSS引脚上的电平由SSI决定。
在这种模式下NSS外部引脚可以用作它用,而内部NSS信号电平可以通过写SPI_CR1的SSI位来驱动。

2、硬件模式两种方式:

(1)对于主SPI,NSS可以直接接高电平,对于从SPI,可以直接接低电平。

(2)当STM32F10xxx工作为主SPI,并且NSS输出已经通过SPI_CR2寄存器的SSOE位使能,
这时主机的NSS讲作为输出信号,引脚信号被拉低,所有NSS引脚与这个主SPI的NSS引脚相连
并配置为硬件NSS的STM32F10xxx SPI设备,将自动变成从SPI设备。

此时两个的NSS信号线可以接个上拉电阻直连。

继续阅读

STM32关闭全局中断时需要注意的问题

原文链接:https://blog.csdn.net/niepangu/article/details/49443557

STM32在使用时有时需要禁用全局中断,比如MCU在升级过程中需禁用外部中断,防止升级过程中外部中断触发导致升级失败。
ARM MDK中提供了如下两个接口来禁用和开启总中断:
__disable_irq(); // 关闭总中断
__enable_irq(); // 开启总中断
但测试发现这样一个问题,在关闭总中断后,如果有中断触发,虽然此时不会引发中断,但在调用__enable_irq()开启总中断后,MCU会立即处理之前触发的中断。这说明__disable_irq()只是禁止CPU去响应中断,没有真正的去屏蔽中断的触发,中断发生后,相应的寄存器会将中断标志置位,在__enable_irq()开启中断后,由于相应的中断标志没有清空,因而还会触发中断。所以要想禁止所有中断,必须对逐个模块的中断进行Disable操作,由于每个模块中断源有很多,对逐个中断Disable的话比较复杂,较为简单的方法是通过XXX_ClearITPendingBit()清除中断标志或者直接通过XXX_DeInit()来清除寄存器的状态。这样在__enable_irq()开启总中断后,MCU就不会响应之前触发的中断了。

STM32 NVIC_SetPriority()中断优先级

转载自http://bbs.eeworld.com.cn/thread-331983-1-1.html

NVIC_SetPriority(SysTick_IRQn, 0x04)

NVIC_SetPriority(SysTick_IRQn, n);
n=0x00~0x03 设置Systick为抢占优先级0
n=0x04~0x07 设置Systick为抢占优先级1
n=0x08~0x0B 设置Systick为抢占优先级2
n=0x0C~0x0F 设置Systick为抢占优先级3
NVIC_SetPriority函数指定中断优先级的寄存器位(STM32只用4位来表示优先级)的数据,中断优先级组设置为了2,即高2位用于指定抢占式优先级,低2位用于指定响应优先级,0x00~0x03高2位为0,
所以抢占优先级为0;0x04~0x07高2位为1,所以抢占优先级为1,以此类推。
此帖出自stm32/stm8论坛

网上搜索了很多网页,都是这样的说明。其实我是想知道优先级0和优先级1比,谁的优先级更高。

摘自
https://blog.csdn.net/yx_l128125/article/details/9703843
前提条件1:组别优先顺序(第0组优先级最强,第4组优先级最弱):NVIC_PriorityGroup_0>NVIC_PriorityGroup_1>NVIC_PriorityGroup_2>NVIC_PriorityGroup_3>NVIC_PriorityGroup_4