{"id":874,"date":"2022-08-30T15:08:37","date_gmt":"2022-08-30T15:08:37","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2013\/11\/09\/assembly-code-for-creating-interrupts-vector-on-lpc2148-arm-processor-collection-of-common-programming-errors\/"},"modified":"2022-08-30T15:08:37","modified_gmt":"2022-08-30T15:08:37","slug":"assembly-code-for-creating-interrupts-vector-on-lpc2148-arm-processor-collection-of-common-programming-errors","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2022\/08\/30\/assembly-code-for-creating-interrupts-vector-on-lpc2148-arm-processor-collection-of-common-programming-errors\/","title":{"rendered":"Assembly code for creating interrupts vector on LPC2148 ARM processor-Collection of common programming errors"},"content":{"rendered":"<p>I&#8217;m going to remove the conditional code, since it just complicates things:<\/p>\n<pre><code>\/\/ Runtime Interrupt Vectors\n\/\/ -------------------------\nVectors:\n        b     _start                    \/\/ reset - _start\n        ldr   pc,_undf                  \/\/ undefined - _undf\n        ldr   pc,_swi                   \/\/ SWI - _swi\n        ldr   pc,_pabt                  \/\/ program abort - _pabt\n        ldr   pc,_dabt                  \/\/ data abort - _dabt\n        nop                             \/\/ reserved\n        ldr   pc,[pc,#-0xFF0]           \/\/ IRQ - read the VIC\n        ldr   pc,_fiq                   \/\/ FIQ - _fiq\n\n_undf:  .word __undf                    \/\/ undefined\n_swi:   .word __swi                     \/\/ SWI\n_pabt:  .word __pabt                    \/\/ program abort\n_dabt:  .word __dabt                    \/\/ data abort\n_irq:   .word __irq                     \/\/ IRQ\n_fiq:   .word __fiq                     \/\/ FIQ\n\n__undf: b     .                         \/\/ undefined\n__swi:  b     .                         \/\/ SWI\n__pabt: b     .                         \/\/ program abort\n__dabt: b     .                         \/\/ data abort\n__irq:  b     .                         \/\/ IRQ\n__fiq:  b     .                         \/\/ FIQ\n\n        .size _boot, . - _boot\n        .endfunc\n<\/code><\/pre>\n<p>Lets look first at the reset\/start vector:<\/p>\n<pre><code>b   _start\n<\/code><\/pre>\n<p>That instruction is an unconditional branch (a jump) to the the code labeled &#8220;_start&#8221; which I don&#8217;t see in your snippet. Basically it&#8217;ll be the assembly that initializes the stack and processor registers, maybe some memory areas then probably jumps to a C routine that performs the bulk of the initialization.<\/p>\n<p>Next is the &#8220;undefined&#8221; vector that the ARM will go to when an invalid instruction is executed (if my memory is right):<\/p>\n<pre><code>ldr pc, _undf\n<\/code><\/pre>\n<p>That instruction loads the <code>pc<\/code> register (the &#8216;program counter&#8217; or instruction pointer) with the address at the &#8220;_undf&#8221; symbol. If we look at the <code>_undf<\/code> variable, it contains the address represented by symbol <code>__undf<\/code>. So the <code>ldr pc, _undf<\/code> instruction loads <code>pc<\/code> with <code>__undf<\/code>&#8216;s address &#8211; jumping to <code>__undf:<\/code>.<\/p>\n<p>And at <code>__undf<\/code> we see:<\/p>\n<pre><code>__undf: b     .  \n<\/code><\/pre>\n<p>That&#8217;s just a branch to the same address &#8211; an infinite loop (the <code>.<\/code> symbol means &#8216;here&#8217; or &#8216;this location&#8217;).<\/p>\n<p>So for most of these vectors (which follow the same technique as the undefined vector), they&#8217;ll just jump to little infinite loops. You could replace the infinite loops at those labels with code that&#8217;s appropriate for the vector in question, though many projects don&#8217;t because those vectors firing would represent some sort of serious error.<\/p>\n<p>Finally, the vector slot that&#8217;s most interesting is the IRQ vector:<\/p>\n<pre><code>ldr   pc,[pc,#-0xFF0]           \/\/ IRQ - read the VIC\n<\/code><\/pre>\n<p>This looks like the handler for an NXP device.<\/p>\n<p>It loads the <code>pc<\/code> register with the value read from a memory location that&#8217;s relative to the <code>pc<\/code> register. Since on the ARM architecture the IRQ vector is <em>always<\/em> at address 0x00000018 (I&#8217;m going to ignore implementations that can map the vectors elsewhere or ARMs like the Cortex-M3 that use a different vector model) and because of the instruction pipeline&#8217;s effect on using the <code>PC<\/code> register value for addressing, the memory location that will be read by this instruction will be <code>0xFFFFF030<\/code>, which is the address of the memory-mapped <code>VICVectAddr<\/code> register in the &#8216;Vectored Interrupt Controller` (VIC):<\/p>\n<pre><code> 'apparent'      Pipeline      offset in      effective\n  PC value        effect       the opcode      address\n-------------   ------------   -----------    ----------\n  0x00000018  +  0x00000008  -  0x0000ff0  == 0xfffff030\n<\/code><\/pre>\n<p>This device register will contain the address of the interrupt handler for the interrupt that just occurred (of course the VIC needs to be properly initialized so it knows that address).<\/p>\n<p>So when the <code>ldr pc,[pc,#-0xFF0]<\/code> instruction executes, it&#8217;ll load the <code>pc<\/code> register with the address of the interrupt handler routine for the appropriate device (basically, jumping to the right interrupt handler).<\/p>\n<p id=\"rop\"><small>Originally posted 2013-11-09 22:51:02. <\/small><\/p>","protected":false},"excerpt":{"rendered":"<p>I&#8217;m going to remove the conditional code, since it just complicates things: \/\/ Runtime Interrupt Vectors \/\/ &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- Vectors: b _start \/\/ reset &#8211; _start ldr pc,_undf \/\/ undefined &#8211; _undf ldr pc,_swi \/\/ SWI &#8211; _swi ldr pc,_pabt \/\/ program abort &#8211; _pabt ldr pc,_dabt \/\/ data abort &#8211; _dabt nop \/\/ reserved ldr [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-874","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/874","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=874"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/874\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=874"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=874"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=874"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}