#pragma once @ vim:ft=arm #include "vic.h" /* This file provides the entry and exit sequences for the syscall handler * specific to the Vectored Interrupt Manager (VIM) and the System Software * Interrupt (SSI), as implemented on the TI Hercules family (TMS570/RM4). */ #define SSI_CHANNEL_BITMASK (1 << (RT_VIM_SSI_CHANNEL % 32)) #define SSI_CHANNEL_REG_OFFSET ((RT_VIM_SSI_CHANNEL / 32) * 4) #define SSI_REQENASET (RT_VIM_REQENASET + SSI_CHANNEL_REG_OFFSET) #define SSI_REQENACLR (RT_VIM_REQENACLR + SSI_CHANNEL_REG_OFFSET) #define SSIVEC 0xFFFFFFF4 /* Use the address of the system control registers as a base address because it * can be loaded in a single instruction in both arm and thumb, and it allows * (+/-) 8-bit immediate offsets to access both the VIM and SSI registers. */ #define SYS_BASE 0xFFFFFF00 .macro vic_svc_start mov r12, SYS_BASE mov lr, SSI_CHANNEL_BITMASK str lr, [r12, SSI_REQENACLR - SYS_BASE] /* A read-back from the VIM and an isb are ordinarily needed when masking * an interrupt channel to ensure that it has taken effect and to take any * latched interrupts before proceeding. In this case we are masking the * SSI interrupt and it is only triggered by a write. Because the SSI * registers and VIM must have either device or strongly-ordered semantics, * any SSI triggered after this point and before vic_svc_finish will be * masked. */ .endm .macro vic_svc_finish // Unmask the software interrupt in the VIM. mov r0, SYS_BASE mov r1, SSI_CHANNEL_BITMASK str r1, [r0, SSI_REQENASET - SYS_BASE] .endm /* The Hercules VIM doesn't automatically mask the active interrupt, so we need * to mask and unmask it manually just like the svc handler. */ .macro vic_syscall_irq_start mov r0, SYS_BASE mov r1, SSI_CHANNEL_BITMASK str r1, [r0, SSI_REQENACLR - SYS_BASE] /* Clear the software interrupt so it can be triggered again. Any * additional trigger will be masked until the current syscall IRQ handler * returns. */ ldr r0, [r0, SSIVEC - SYS_BASE] .endm .macro vic_syscall_irq_finish vic_svc_finish .endm