精华内容
下载资源
问答
  • 中断向量 中断源的识别标志,可用来形成相应的中断服务程序的入口地址或存放中断服务程序的首地址。运行过程 在中断响应过程中,CPU通过从接口电路获取的中断类型号(中断向量号)计算对应中断向量在表中的位置,...

    中断向量
    中断源的识别标志,可用来形成相应的中断服务程序的入口地址或存放中断服务程序的首地址。

    运行过程
    在中断响应过程中,CPU通过从接口电路获取的中断类型号(中断向量号)计算对应中断向量在表中的位置,并从中断向量表中获取中断向量,将程序流程转向中断服务程序的入口地址。

    这里写图片描述
    图一 中断函数声明
    这里写图片描述
    图二 配置中断服务函数
    这里写图片描述
    图三 设置中断服务函数的底层库函数

    举例
    上图是利用山外K60库配置PORTC和DMA0的中断服务函数实例
    图二中PORTC_IRQHandler是需要设置的中断服务程序(用户自己设置),PORTC_VECT0Rn是中断向量表中的中断向量(K60底层已设置)。set_vector_handler函数的意义是将PORTC_IRQHandler的地址(PORTC_IRQHandler在图一中是定义的函数名,在图二中代表该函数在内存中的首地址)“赋值”给中断向量PORTC_VECT0Rn。
    简单来说,set_vector_handler(PORTC_VECT0Rn, PORTC_IRQHandler);的作用是把PORTC_IRQHandler添加到中断向量表中。
    K60在获取中断类型号(码)后,经计算(中断类型码*4)得到该中断类型服务子程序入口地址在中断向量表的位置(即中断向量PORTC_VECT0Rn),然后从中取出这个地址(PORTC_IRQHandler),转到相应的子程序(void PORTC_IRQHandle())。

    简单来说,中断向量指向地址,该地址下存放的是用户需要在中断时执行的函数。
    先获取中断类型号,再在中断向量表中找中断向量,指向一个地址,执行其中的中断服务程序。

    下图为山外K60平台部分中断号类型声明和中断向量表编号声明
    这里写图片描述

    如有错误,欢迎指正!

    展开全文
  • 在IAR环境下用户程序的地址及中断向量设置,在IAR环境下用户程序的地址及中断向量设置
  • DSP嵌入式系统写Flash配置文件代码  DSP嵌入式系统写Flash中断向量代码  DSP嵌入式系统写Flash工具代码  欢迎转载,信息来源维库电子市场网(www.dzsc.com)  来源:ks99
  • STM32(Cortex-M3)中有两个优先级的概念:抢占式优先级和响应优先级,也把响应优先级称作“亚优先级”或“副优先级”,每个中断源都需要被指定这两种优先级。
  • 内核IRQ中断向量

    千次阅读 2019-08-01 19:45:11
    首先看一下vector_irq的定义,此每处理器数组变量,保存每个处理器上中断向量所对应的中断号,其以中断向量值为索引。系统中定义了256个中断向量。相关代码如下: typedef int vector_irq_t[NR_VECTORS]; DEFINE_...

    首先看一下vector_irq的定义,此每处理器数组变量,保存每个处理器上中断向量所对应的中断号,其以中断向量值为索引。系统中定义了256个中断向量。相关代码如下:

    typedef int vector_irq_t[NR_VECTORS];
    
    DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
        [0 ... NR_VECTORS - 1] = VECTOR_UNDEFINED,
    };
    
    
    #define NR_VECTORS  256
    

    另一个是used_vector的定义,其为一个位图变量,用来标记系统中已经使用的中断向量。

    DECLARE_BITMAP(used_vectors, NR_VECTORS);
    

    中断向量初始化

    中断初始化入口函数init_IRQ。为支持传统的PIC类型的终端控制器,如8259,内核预留了IRQ0_VECTOR 到 IRQ15_VECTOR 共16个中断向量,分别对应IRQ号0到15。在初始化时,也不是全部预留这16个中断向量,而是根据检测到的传统PIC中断控制器所支持中断数量在预留,有可能小于16个。x86_init.irqs.intr_init()指针对应的为native_init_IRQ函数,接下来介绍。

    void __init init_IRQ(void)
    {
    
        for (i = 0; i < nr_legacy_irqs(); i++)
            per_cpu(vector_irq, 0)[IRQ0_VECTOR + i] = i;
    
        x86_init.irqs.intr_init();
    }
    

    函数apic_intr_init负责分配系统自身所需的中断向量。x86架构的IDT中断描述表可用的外部中断向量由0x20(FIRST_EXTERNAL_VECTOR)开始,其中0x80(IA32_SYSCALL_VECTOR)为系统调用所用的中断向量;0x30-0x3f共16个中断向量保留给ISA使用。interrupt函数参见文件arch/x86/kernel/entry_64.S中的定义,表示中断处理程序的入口地址,for_each_clear_bit_from循环将所有未使用的中断向量的处理程序入口设定为interrupt的相应偏移。最后对于传统的中断控制器,irq2用作两片控制器的级联。

    void __init native_init_IRQ(void)
    {
        apic_intr_init();
    
        i = FIRST_EXTERNAL_VECTOR;
        for_each_clear_bit_from(i, used_vectors, NR_VECTORS) {
            set_intr_gate(i, interrupt[i - FIRST_EXTERNAL_VECTOR]);
        }
    
        if (!acpi_ioapic && !of_ioapic)
            setup_irq(2, &irq2);
    }
    

    系统中断向量分配

    函数apic_intr_init。首先分配SMP相关的中断向量,参见函数smp_intr_init,随后是分配其他的向量。这些中断向量值由大到小分配,首先是:SPURIOUS_APIC_VECTOR(0xff),目前最小的是:LOCAL_TIMER_VECTOR(0xef)。内核中定义了变量first_system_vector表示当前系统中断向量的最小值。

    static void __init apic_intr_init(void)
    {
        smp_intr_init();
    
    #ifdef CONFIG_X86_THERMAL_VECTOR
        alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
    }
    
    static void __init smp_intr_init(void)
    {
    #ifdef CONFIG_SMP
    #if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
        alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
    }
    

    alloc_intr_gate宏由alloc_system_vector和set_intr_gate两个函数组成。前者为注册的系统中断向量设置used_vectors中的使用标志,并且更新系统最小向量值:first_system_vector。后者set_intr_gate函数设置处理器的IDT表。

    static inline void alloc_system_vector(int vector)
    {
        if (!test_bit(vector, used_vectors)) {
            set_bit(vector, used_vectors);
            if (first_system_vector > vector)
                first_system_vector = vector;
        } else {
            BUG();
        }
    }
    
    #define alloc_intr_gate(n, addr)                \
        do {                            \
            alloc_system_vector(n);             \
            set_intr_gate(n, addr);             \
        } while (0)
    

    外部中断向量分配

    由如下函数irq_alloc_hwirqs可见,首先调用函数__irq_alloc_descs分配中断号,内核中已经使用的中断号标记在全局位图变量allocated_irqs中,函数的第一个参数表示期望的中断号,-1表示由系统来选择中断号。系统将在allocated_irqs位图中选择一个不为零的位返回,作为新的中断号。

    函数arch_setup_hwirq负责为中断号查找合适的中断向量。注意在执行过程中出现错误的话,函数将执行回退处理,包括由函数irq_free_descs复位之前分配中断号时设置的allocated_irqs中的位。arch_teardown_hwirq函数是对应arch_setup_hwirq函数的清理函数。

    unsigned int irq_alloc_hwirqs(int cnt, int node)
    {
        int i, irq = __irq_alloc_descs(-1, 0, cnt, node, NULL);
    
        if (irq < 0)
            return 0;
    
        for (i = irq; cnt > 0; i++, cnt--) {
            if (arch_setup_hwirq(i, node))
                goto err;
    
            irq_clear_status_flags(i, _IRQ_NOREQUEST);
        }
        return irq;
    
    err:
        for (i--; i >= irq; i--) {
            irq_set_status_flags(i, _IRQ_NOREQUEST | _IRQ_NOPROBE);
            arch_teardown_hwirq(i);
        }
        irq_free_descs(irq, cnt);
        return 0;
    }
    

    arch_setup_hwirq函数的主体是由__assign_irq_vector函数完成,其定义如下。由于终端级别是由中断向量后4位决定的,而本地的APIC不能够很好的处理多个同级别的中断,所以内核以2的4次方,即16为区间,进行中断向量的分配。

    使用静态变量current_vector和current_offset分别记录当前的区间起始值和区间内偏移。第一次分配中断向量时,current_vector为33,偏移值为1,所以第一个可供分配的中断向量为34。

    static int __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
    {
        static int current_vector = FIRST_EXTERNAL_VECTOR + VECTOR_OFFSET_START;
        static int current_offset = VECTOR_OFFSET_START % 16;
    

    以下的中断向量查找由两个循环组成。第一个循环遍历中断可用的处理器列表,由APIC控制器的可用处理器列表和在线处理器列表中第一个同时置位的处理器开始,第二个循环(内部循环)遍历所有可用的中断向量vector,如果没有合适的选择,即vector的值又回到了最初的current_vector,进行第二次循环,遍历第二个可用的处理器。

    获取第二个可用处理器的算法为:1)当前分配的处理器域domain(处理器列表),与老的域值old_domain进行或操作;2)将上一步的结果和APIC处理器列表进行与操作;3)在第二步所得结果和在线处理器列表中获取第一个同时置位的处理器。此即下一个循环要遍历的处理器。

    1287     cpumask_clear(cfg->old_domain);
    1288     cpu = cpumask_first_and(mask, cpu_online_mask);
    1289     while (cpu < nr_cpu_ids) {
    1290         int new_cpu, vector, offset;
    1291
    1294         apic->vector_allocation_domain(cpu, tmp_mask, mask);
    
    1335         if (unlikely(current_vector == vector)) {
    1340             cpumask_or(cfg->old_domain, cfg->old_domain, tmp_mask);
    1345             cpumask_andnot(tmp_mask, mask, cfg->old_domain);
    1348             cpu = cpumask_first_and(tmp_mask, cpu_online_mask);
    1350             continue;
    1351         }
    

    内部的循环由标签和goto语句组成。每次遍历16长度的区间中的第一个偏移向量值,一直遍历完所有的区间。之后,当vector向量值大于最大可用向量值first_system_vector时,重新由第一个区间的第二个偏移值开始遍历。

    如果遍历的向量值没有被使用,即used_vectors位图没有置位。并且,tmp_mask中的所有有效处理器上vector_irq映射还没有被占用,表明此中断向量可用。

    1324         vector = current_vector;
    1325         offset = current_offset;
    1326 next:
    1329         vector += 16;
    1330         if (vector >= first_system_vector) {
    1331             offset = (offset + 1) % 16;
    1332             vector = FIRST_EXTERNAL_VECTOR + offset;
    1333         }
    1334
    1335         if (unlikely(current_vector == vector)) {
    1340             cpumask_or(cfg->old_domain, cfg->old_domain, tmp_mask);
    1345             cpumask_andnot(tmp_mask, mask, cfg->old_domain);
    1348             cpu = cpumask_first_and(tmp_mask, cpu_online_mask);
    1350             continue;
    1351         }
    1352
    1353         if (test_bit(vector, used_vectors))
    1355             goto next;
    1357
    1358         for_each_cpu_and(new_cpu, tmp_mask, cpu_online_mask) {
    1359             if (per_cpu(vector_irq, new_cpu)[vector] > VECTOR_UNDEFINED)
    1360                 goto next;
    1361         }
    

    成功找到可用的中断向量之后,更新静态的current_vector和current_offset的值,并更新tmp_mask中所有处理器的vector_irq中断向量和中断号映射值,写入分配的irq中断号,表明此中断向量已被占用。使用cfg中的domain成员记录有效的处理器列表。

    除去第一次申请中断向量外,系统也可能动态的调整中断向量,及为其服务的处理器列表,old_domain用来保存调整前的处理器列表,move_in_progress表示是否正处于调整期间,调整结束之后old_domain为空,move_in_progress也值为0。

    1362         /* Found one! */
    1363         current_vector = vector;
    1364         current_offset = offset;
    1365         if (cfg->vector) {
    1371             cpumask_copy(cfg->old_domain, cfg->domain);
    1374             cfg->move_in_progress = cpumask_intersects(cfg->old_domain, cpu_online_mask);
    1377         }
    
    1380         for_each_cpu_and(new_cpu, tmp_mask, cpu_online_mask)
    1381             per_cpu(vector_irq, new_cpu)[vector] = irq;
    1382         cfg->vector = vector;
    1383         cpumask_copy(cfg->domain, tmp_mask);
    1387
    1388         err = 0;
    1389         break;
    

    另外,在中断调整时,如果服务的处理器列表调整前后一致,直接跳出循环(cpumask_equal(tmp_mask, cfg->domain))。如果新的处理器列表是调整前处理器列表的子集,移除多余的处理器,并更新domain为调整之后的处理器列表。

    1294         apic->vector_allocation_domain(cpu, tmp_mask, mask);
    1295
    1296         if (cpumask_subset(tmp_mask, cfg->domain)) {
    1297             err = 0;
    
    1303             if (cpumask_equal(tmp_mask, cfg->domain))
    1304                 break;
    1305             /*
    1306              * New cpumask using the vector is a proper subset of the current in use mask. So cleanup the vector
    1308              * allocation for the members that are not used anymore.
    1309              */
    1310             cpumask_andnot(cfg->old_domain, cfg->domain, tmp_mask);
    1313
    1314             cfg->move_in_progress = cpumask_intersects(cfg->old_domain, cpu_online_mask);
    1317             cpumask_and(cfg->domain, cfg->domain, tmp_mask);
    1320
    1321             break;
    1322         }
    

    以上的介绍打乱了代码的顺序,以行号为准。

    内核版本:3.10.0

    展开全文
  • 2、配置 1、设置中断优先级分组 主要设置SCB->AIRCR[10:8],中断优先级分组见下图。 初始化函数说明如下: /** * @brief Configures the priority grouping: pre-emption priority and subpriority. *

    1、中断和事件区别

    外部激励信号来看,中断和事件没有区别。从处理来看,中断会向CPU发出请求,需要CPU响应中断程序。事件则是对其他模块发出的脉冲信号,具体其他设备如何响应,就由这个模块决定。

    2、配置

    1、设置中断优先级分组

    主要设置SCB->AIRCR[10:8],中断优先级分组见下图。
    在这里插入图片描述

    • 初始化函数说明如下:
    /**
      * @brief  Configures the priority grouping: pre-emption priority and subpriority.
      *         配置优先级分组:抢占优先级和子优先级
      * @param  NVIC_PriorityGroup: specifies the priority grouping bits length. 指定优先级分组位的长度
      *   This parameter can be one of the following values:
      *     @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority
      *                                4 bits for subpriority
      *     @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority
      *                                3 bits for subpriority
      *     @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority
      *                                2 bits for subpriority
      *     @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority
      *                                1 bits for subpriority
      *     @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority
      *                                0 bits for subpriority
      * @retval None
      */
    void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
    {
      /* Check the parameters */
      assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
      
      /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */
      SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
    }
    

    2、配置中断参数

    主要配置中断优先级寄存器(NVIC_IPRx)和中断开启寄存器((NVIC_ISERx),以及中断关闭寄存器(NVIC_ICERx)。

    • 配置函数说明如下:
    /**
      * @brief  Initializes the NVIC peripheral according to the specified
      *         parameters in the NVIC_InitStruct.
      *         根据NVIC_InitStruct中的指定参数初始化NVIC外设。
      * @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 --------------------------------*/
        /* 计算相应的IRQ优先级 --------------------------------*/
        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);
      }
    }
    
    • NVIC_InitTypeDef结构说明如下:
    typedef struct
    {
      // 指定要启用或禁用的IRQ通道。此参数可以是@ref IRQn_Type的值(有关完整的STM32设备IRQ通道列表,请参阅stm32f10x.h文件)
      uint8_t NVIC_IRQChannel;               
    
      // 指定NVIC_IRQChannel中指定的IRQ通道的抢占优先级。 如表@ref NVIC_Priority_Table中所述,此参数可以是0到15之间的值。
      uint8_t NVIC_IRQChannelPreemptionPriority;  
    
      // 为NVIC_IRQChannel中指定的IRQ通道指定子优先级。 如表@ref NVIC_Priority_Table中所述,此参数可以是0到15之间的值。
      uint8_t NVIC_IRQChannelSubPriority;
        
      // 指定是启用还是禁用NVIC_IRQChannel中定义的IRQ通道。此参数可以设置为ENABLE或DISABLE
      FunctionalState NVIC_IRQChannelCmd;         
        
    } NVIC_InitTypeDef;
    

    3、中断优先级配置表

    在这里插入图片描述

    展开全文
  • 原文地址 在做stm32 iap升级固件的时候通常需要多份中断向量表。比如bootloader的中断向量表在0x00000000位置,应用程序的中断向...VTOR是arm内核的一个寄存器,叫做中断向量偏移量寄存器。当系统上电启动的时候CPU...

    原文地址

    在做stm32 iap升级固件的时候通常需要多份中断向量表。比如bootloader的中断向量表在0x00000000位置,应用程序的中断向量表则会放在flash的另一个地方或者是放在RAM中运行。

    要维护向量表位置就需要用VTOR这个东西,那么就要先从VTOR来聊聊, 先弄清这个东西又是干嘛的。

    VTOR是arm内核的一个寄存器,叫做中断向量偏移量寄存器。当系统上电启动的时候CPU会从先找到中断向量表的位置,然后从表中找到复位中断Reset_Handler,而main函数的执行实际上就是在复位中断函数中的。如下汇编代码就是复位中断服务函数,该函数在启动文件中定义。在Reset_Handler 中会执行__main(),而main函数又是被__main()调用了。

    Reset_Handler    PROC
                     EXPORT  Reset_Handler                 [WEAK]
            IMPORT  __main
            IMPORT  SystemInit  
                     LDR     R0, =SystemInit
                     BLX     R0
                     LDR     R0, =__main
                     BX      R0
                     ENDP

    前面复习一下ARM处理器启动到执行main的一个大概流程。再回归正题继续探讨这个VTOR。当来一个中断时,cpu就会从0x0000000+VTOR位置找到中断向量表,然后再查表跳转到对应的中断服务函数去执行。所以你代码里面存在多份中断向量表是可以的,只需要动态改变VTOR的值就可以了。

    STM32在线升级中断向量重定向深度剖析

    APP的中断向量放在flash中:

    如下图所示,在运行bootloader的时候用的是他自己的bootloader,当从bootloader跳转到app以后就需要用app的向量表了。所以进入APP的首要任务就是设置VTOR值为0x0x8001000,再产生中断的时候让cpu去app的向量表里找中断服务函数入口。

    STM32在线升级中断向量重定向深度剖析

    所以从在app中重定义向量表是不是很简单。但是有个前提,就是要有VTOR寄存器。实际上,并不是所有stm32都带有VTOR的。准确的说是因为ARM-CORTEX-M0内核的芯片没有,所以stm32F0系列所采用M0内核的芯片就没有VTOR。但是还有需要注意的就是L0系列使用的M0+内核和M0内核又是不同的,是有VTOR的。

    这就意味着stm32F0系列没有办法使用这种简单的修改VTOR的方式重新定位APP的中断向量表。那肯定还有其他思路,就是稍微麻烦一点。

    中断向量放在RAM中:

    那就是把中断向量表放在RAM中去,并且针对F0没有VTOR的还必须把中断向量表拷贝到RAM的起始地址。

    为什么这样做,因为前面我们提到过CPU默认会认为0x00000000处放的就是向量表。那么我们换种思路可以把RAM的地址映射到0x00000000处。这个通过配置SYSCFG寄存器的MEM_MODE就可以把RAM地址映射到0x00000000处。

    STM32在线升级中断向量重定向深度剖析

    这时候再进入到APP以后首要任务就是把APP的中断向量表拷贝到RAM的起始地址,并且修改MEM_MODE位。

    在代码里面比较简单的做法就是在ram起始地址处定义一个数组,上电以后把向量表拷贝到这个数组中。如下代码是在MDK中定义的方法,在IAR或者GCC定义的方式会有区别。

    __IO uint32_t vector_t[48] __attribute__((at(0x20000000)));

    但是要编译通过还需要在mdk配置里面把ram的起始地址设置为0x200000c0,前面的0xc0的空间腾出来存放定义的这个数组。

    有VTOR的系列向量表放在RAM中

    stm32F0系列内核决定了即便把向量表放在RAM中也只能放在RAM的起始位置而不能任意放。但是有VTOR的型号就可以随便放。这样分配存放向量表的数组也可以不用定位在0x20000000位置了。可以如下方式定义:

    __align(256) uint32_t vector_t[48];

    可以看到虽然没有了必须放在ram起始地址的限制,但是还是要遵守一定的规则。就是对齐有要求的。比如L0系列有48个中断向量,一共占用内存为48*4=192bytes。扩大为2的整次方为256:28=256。所以就要求向量存储的地址必须是256对齐的。存放在0x0或者0x20000100都可以满足要求。

    另外这种方式虽然更灵活了一些,但是却造成了一定RAM空间的浪费。我在这样定义编译以后查看MAP文件如下,红色的区域空出来的一段内存空间就会被浪费掉:

    STM32在线升级中断向量重定向深度剖析

    关于0X00000000地址

    前面说过默认cpu会从0x00000000地址来取向量表,那么stm32的flash都是从0x8000000地址开始的,这时候不设置VTOR偏移为什么也可以正常运行。实际上当从用户flash启动的时候,从0x8000000或者0x00000000访问的都是同一片区域。所以cpu从0x0取向量表相当于取的就是0x8000000地址处的数据。

    更进一步理解,stm32通过配置boot脚(或者SYSCFG中MEM_MODE位)有三种启动模式选择,这三种模式的本质就是看把那个区域重映射为0x00000000地址。这样CPU取第一条指令就是从哪里取:

    1. 从用户flash区启动,用户flash起始地址被映射到0x00000000上
    2. 从系统flash区启动,系统flash起始地址被映射到0x00000000上,上电就执行内置的bootloader
    3. 从RAM区启动,RAM起始地址被映射到0x00000000上,这时候你再回过去看我刚才说的F0无VTOR寄存器实现IAP就是这样的思路。向量表放在了RAM区域的起始地址。


    转载请注明转自电子创客营: STM32在线升级中断向量重定向深度剖析! 了解我们 点击这里

    微信扫一扫关注我们的公众号:eemaker

    STM32在线升级中断向量重定向深度剖析


    喜欢 (5) or 分享 (0)
    展开全文
  • 但是开始有个疑问:就是_start入口后,第一个指令就执行了b reset,进入了reset标签,正常启动了,对于改指令后的红色部分,并不能有效执行,怎么才能把中断向量正常初始化呢?(中断函数在其他地方也没有执行、或...
  • stm32中断向量控制器

    千次阅读 2018-08-21 16:15:31
    NVIC,中文名嵌套中断向量控制器,是Cortex-M3系列控制器内部独有集成单元,与CPU结合紧密,降低中断延迟时间并且能更加高效处理后续中断。举个例子,比如火车站买票,那些火车站的规章制度就是NVIC,规定学生和军人...
  • ARM 中断向量介绍

    千次阅读 2017-07-21 11:08:51
    最后,通过设置中断控制寄存器,设计外部中断EINT3的初始化程序,并给出主程序流程图。实践证明程序运行稳定可靠。 引言 计算机体系结构中,异常或者中断是处理系统中突发事件的一种机制,几乎所有的处理器都...
  • //中断向量优先级配置 ST的注释:那一组代表了什么样的主次优先级排位,比如:第0组,主优先级0位,次优先级4位表示16种级别,那就是第一优先级无效。 在STM32F20xxx Cortex-M3 编程手册中找到了定义: 2....
  • 说到中断号和中断向量,也许你并不陌生,这两个概念也可以将中断原理解释个大概了。但是当你深究下去的时候你会碰到另一个东西——IRQ,之后自然而然的对从硬件级开始到中断向量表的整个中断过程产生好奇,然后继续...
  • 这里和系统时钟一样,完全可以直接用 cubeMX来进行配置,没必要自己手动配置。 SysTick的主要功能是给RTOS提供时钟节拍做时间基准。HAL库自带的延时函数就是通过它来延时的,但其实这并不值得推荐,一般都是用...
  • 1、外部中断 0、 1;分别由引脚/INT0、/INT1的电平信号引起。 2、定时/计数器 0、1;分别由T0、 T1的溢出引起。 3、串行口发送、接收;发送完一个字节或接收到一个字节引起。 上述共5个中断源。 一、中断号 外部中断...
  • Bootloader中断向量重定位问题 1.Bootloader程序在内核Cortex-M0+内核中运行时需要进行地址跳转执行应用程序主程序,此时就涉及到了中断向量重定位问题,以下截图为单片机启动文件中的栈和堆空间大小分配以及中断向...
  • 通常32位ARM嵌入式系统的中断向...本文给出一种配置ARM中断向量表新方法。该方法比通常方法仅增加一条指令执行时间,简便高效,功能完备,向量表在运行时动态生成,C程序可以使用固定向量表的启动代码,并可隐藏起来。
  • 在MCU/ARM/DSP中,都有1个启动过程,这里主要设计复位及中断的入口问题。所以它们基本都有启动文件的支持,使程序上电后自动进入正确的程序位置及地址。复位及中断的入口具有多个间隔固定的程序空间,它们可以是单独的...
  • Linux ARM 中断向量重定位分析

    千次阅读 2019-01-01 22:11:12
    作为Linux的开篇,延续我一贯的风格,从启动以及中断向量开始。此篇文章的内容是以Linux版本是2.6.39,硬件平台是ATMEL9G25。 大神路过,看一眼,请指正其中错误之处。好了,开始正题。 在arch/arm/kernel/entry...
  • RH850有两种定义中断方法: 1.直接向量法:Direct Vector Method 对于Direct Vector Method,Exception Handler Address = base address + offset address, base address是指 RBASE or EBASE register 但是Direct ...
  • CC2530 按键中断--中断向量

    千次阅读 2013-05-11 14:38:59
    /************************************************* *项目名称:Zigbee——学习 ...*功能描述:key1中断方式点亮led灯 *开发平台:网蜂Zigbee基础版 *硬件连接: * LED1 P1_0 低电平亮 * KEY1 P0_4 下拉有效 *
  • 44B的中断介绍_eint4567配置实例_关于中断嵌套和向量中断[借鉴].pdf
  • MCF52259 PIT中断

    千次阅读 2014-04-18 19:07:46
    中断向量表如下所示: __declspec(vectortable) vectorTableEntryType _vect[256] = { /* Interrupt vector table */ (vectorTableEntryType)__SP_AFTER_RESET, /* 0 (0x000) Initial supervisor SP */ _startup, ...
  • 2、USART中断配置---内嵌中断向量控制器 3、一种串口发送格式化数据方法 几个概念: 内嵌向量中断控制器:Nested Vectored Interrupt Controller (NVIC) 向量中断即中断源的识别标志,可用来存放中断服务程序...
  • EXTI10_15共用一个中断向量地址,但是中断线EXTI_Line10~EXTI_Line15是分开的。 在初始化时,使用 或操作进行初始化时,如下部分代码,对中断线进行初始化后,中断程序没有动作。 EXTI_InitStructure.EXTI_Line=...
  • 什么是“中断”? CPU执行程序时,由于发生了某种随机的事件(外部或内部),引起CPU暂时中断正在运行的程序,转去执行一段特殊的...NVIC :嵌套向量中断控制器,用于总体管理异常 Cortex-M4内核支持256个中断,其中包...
  • NVIC 的全称是 Nested vectored interrupt controller,即嵌套向量中断控制器。 对于 M3 和 M4 内核的 MCU,每个中断的优先级都是用寄存器中的 8 位来设置的。 8 位的话就可以 设置 2^8 = 256 级中断,实际中用不了...
  • [STM32]外部中断配置

    2021-05-27 16:19:15
    但外部中断5 ~ 9共用一个中断向量,外部中断10 ~ 15共用一个中断向量 及同时只能使用7个外部中断,外部中断5 ~ 9同时只能配置一个中断线,外部中断10 ~ 15也同时只能配置一个中断线 外部中断的配置 设置系统中断...
  • NVIC(Nested Vectored Interrupt Controller):嵌套向量中断控制器 库函数程序(以USART1为例) NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置优先级分组为2 //Usart1 NVIC 配置 NVIC_...
  • 配置流程: 1:系统时钟初始化,包括系统时钟和要开放的IO口或者功能的时钟配置。...3:NVIC 中断向量配置 ,中断向量基地址和优先级的配置。 4:TIM3初始化:包括自动重装值,分频值,计数模式,使能T...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 18,954
精华内容 7,581
关键字:

中断向量配置