;************************************************************************
;* *
;* assembler definitions for enabling nested interrupts *
;* *
;************************************************************************
;************************************************************************
;* 1 Disclaimer *
;************************************************************************
;* __DISCLAIMER_START__ *
;************************************************************************
;* (c) 2014-2016, Cypress Semiconductor Corporation
;* or a subsidiary of Cypress Semiconductor Corporation. All rights
;* reserved.
;*
;* This software, including source code, documentation and related
;* materials ( "Software" ), is owned by Cypress Semiconductor
;* Corporation or one of its subsidiaries ( "Cypress" ) and is protected by
;* and subject to worldwide patent protection (United States and foreign),
;* United States copyright laws and international treaty provisions.
;* Therefore, you may use this Software only as provided in the license
;* agreement accompanying the software package from which you
;* obtained this Software ( "EULA" ).
;*
;* If no EULA applies, Cypress hereby grants you a personal, nonexclusive,
;* non-transferable license to copy, modify, and compile the
;* Software source code solely for use in connection with Cypress' s
;* integrated circuit products. Any reproduction, modification, translation,
;* compilation, or representation of this Software except as specified
;* above is prohibited without the express written permission of Cypress.
;*
;* Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO
;* WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING,
;* BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED
;* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
;* PARTICULAR PURPOSE. Cypress reserves the right to make
;* changes to the Software without notice. Cypress does not assume any
;* liability arising out of the application or use of the Software or any
;* product or circuit described in the Software. Cypress does not
;* authorize its products for use in any products where a malfunction or
;* failure of the Cypress product may reasonably be expected to result in
;* significant property damage, injury or death ( "High Risk Product" ). By
;* including Cypress' s product in a High Risk Product, the manufacturer
;* of such system or application assumes all risk of such use and in doing
;* so agrees to indemnify Cypress against all liability.
;************************************************************************
; __DISCLAIMER_END__ *
;************************************************************************
;************************************************************************
;* 2 Contents *
;************************************************************************
;* 1 Disclaimer *
;* 2 Contents *
;* 3 History *
;* 4 Local definitions *
;* 5 Assembler macro code *
;************************************************************************
;* 3 History *
;************************************************************************
;* Version Date Author Description *
;* V0.01 2015-09-01 HS Initial version for Traveo *
;************************************************************************
;* 4 Local definitions *
;************************************************************************
;* define register address
ADDRESS_OF_IRC0_IRQR0 .equ 0xb0400b00
ADDRESS_OF_IRQST_nIRQ .equ 0xb1100078
ADDRESS_OF_IRC0_IRQHC .equ 0xb0400c48
;************************************************************************
;* 5 Assembler macro code *
;************************************************************************
;* This macro can be used to define a nested IRQ handler.
;* Currently GHS comliler does not support IRQ nesting,
;* so it is necessary to code in assembly language to define nested IRQ handler.
;*
;* Parameters:
;* irq_handler_name: IRQ handler name.This macro generates a hanlder named irq_handler_name.
;* isr_name : Interrup service routine name which called by the irq_handler_name.
;* irq_num : IRQ number
;*
;* How to use:
;* Define hanlders using the steps explained below.
;*
;* - At first, make new assembler file.
;* - Next include this file from new file.
;* - Then Define handlers using this macro.
;* - Implement Interrupt service routine "isr_name".
;* "isr_name" can be coded in C or assembly language.
;* - Assign irq_handler_name to INTERRUPTS_IRQ_ISR_??? which is defined in interrupts.h.
;*
;* example:
;* - In new file
;* .include "nested_interrupt.asm"
;*
;* .text ;* Declare code section. (Change section if you need.)
;* .nothumb ;* use ARM mode.
;*
;* define_nested_irq_handler irq_handler_0, irq_isr_0, 0
;*
;* END
;*
;* - In any file
;* // implement ISR
;* void irq_isr_0(void)
;* {
;* // code to handle the IRQ
;* // clear IRQ flag at source (peripheral or software interrupt)
;* }
;*
;* - In interrupts.h
;* // assign INTERRUPTS_IRQ_ISR_0
;* #define INTERRUPTS_IRQ_ISR_0 irq_handler_0 ///< IRQ#0
;*
.macro define_nested_irq_handler irq_handler_name, isr_name, irq_num
.macrolocal IRQST_check_loop
.export irq_handler_name
.import isr_name
irq_handler_name:
SUB lr, lr, #4 ;* Save LR_irq and SPS_irq on system stack
SRSFD sp!, #0x1f ;*
CPS #0x1f ;* Switch to system mode
PUSH {r0-r3, r12} ;* Store remaining AAPCS register on system stack
FSTMDBD sp!, {d0-d7}
FMRX r1, fpscr
PUSH r1
AND r1, sp, #4 ;* Ensure stack is 8-byte aligned
SUB sp, sp, r1 ;*
PUSH {r1, lr} ;* Save LR_sys and stack adjusted value
CPSIE i ;* Enable IRQ
;* Dummy write to IRC0_IRQR0 (for enable IRQ)
MOVW r1, #(ADDRESS_OF_IRC0_IRQR0 & 0xFFFF) ;* Load register address (lower 16bit)
MOVT r1, #(ADDRESS_OF_IRC0_IRQR0 >> 16) ;* Load register address (upper 16bit)
MOV r0, #0 ;* Set IRQR to "0" (no effect)
STR r0, [r1] ;*
;* Call interrupt service routine
LDR r1, =isr_name
BLX r1
;* Check IRQST
MOVW r1, #(ADDRESS_OF_IRQST_nIRQ & 0xFFFF) ;* Load register address (lower 16bit)
MOVT r1, #(ADDRESS_OF_IRQST_nIRQ >> 16) ;* Load register address (upper 16bit)
IRQST_check_loop:
LDRB r0, [r1] ;* Read register value
CMP r0, #0
BEQ IRQST_check_loop ;* Loop while nIRQ == 0
;* Clear hold bit
MOVW r0, #(irq_num & 0x1FF) ;* Set to IRQ number (valid range: 0 to 511)
MOVW r1, #(ADDRESS_OF_IRC0_IRQHC & 0xFFFF) ;* Load register address (lower 16bit)
MOVT r1, #(ADDRESS_OF_IRC0_IRQHC >> 16) ;* Load register address (upper 16bit)
STR r0, [r1] ;* Clear hold bit
CPSID i ;* Disable IRQ
POP {r1, lr} ;* Restore LR_sys and unajust stack
ADD sp, sp, r1 ;*
POP r1
FMXR fpscr, r1
FLDMIAD sp!, {d0-d7} ;* Restore AAPCS register
POP {r0-r3, r12}
RFEFD sp! ;* Return from system stack mode
.endm