I'm using a PGA970 with a ARM Cortex M0 and I'm struggling with the basic function of its SysTick interrupt. My current state is this:
void main(void) { Interrupt_Config(); __set_PRIMASK(0); //Enables Interrupts SYST_Config(0x0000004F,0x00000007); //configures Reload value + enables counting while(1) {} //stay in main and wait for Interrupt }
with this definition:
void Interrupt_Config(void) { /* Clear interrupt pending register */ NVIC_UNPEND0 = 0xFFFFFFFF; /* Set priority of NVIC interrupt */ NVIC_PRI0 = 0x80400000; NVIC_PRI1 = 0xC0C0C0C0; /* * Enable NVIC interrupts * NVIC interrupt for external interrupt 1 i.e. TADC is disabled */ NVIC_ENABLE0 = 0xFFFFFFFD; }
According to Ti priority of SysTick is set to -1 with the highest priority being -3 (used by fault handlers). Custom interrupts start with the priority of 1.
SysTick M0 System Timer SysTick Registers:
These are my SysTick registers. The CSR register is enabled by setting the value of 7. When the Current Value Register hits 0 it gets reset to the Reload Value which is defined in the RVR. When this reload happens the Countflag-Bit in the CSR is set to 1. Everything of this is working as described in my case.
After the Countflag-Bit is set, an interrupt should be triggered executing the Syst_Handler as shown below. Since I'm using it as a basic counter for now I can confirm that it never gets called.
int SYSTcounter=0; interrupt void SYST_Handler(void) { SYSTcounter++; }
Now to the weird part. The NVIC_INT_CTRL register was renamed by Ti and represents the ISCR of ARM. After executing the Code and waiting for the Countflag it has a Value of 0x67108867. The SysTick exception has a value of 15 --> 1111 which can be seen in VECACTIVE in the picture below. BUT the VECPENDING remains empty same for ISRPENDING. ISCR values and explanation of Bits
As far as my understanding goes something most probably some stupid setting I forgot prevents my Systick from being executed although it realises that it should be executed. My interrupts in general are working as an unexpected power loss triggers the FaultHandler on the next startup as desired.
Aditionnaly this is my vector table on which you can see SYST_Handler goes by exception number 15. So far I didn't manage to get any Interrupt going, except for the IntDefaultHandler which states that it gets excecuted whenever the processor recieves an unexpected interrupt. I did that by cutting the power supply off and immediatly reconnecting it. All of them should be enabled and working since interrupts in general should be enabled for IntDefaultHandler to work.
#pragma DATA_SECTION(g_pfnVectors, ".intvecs") void (* const g_pfnVectors[])(void) = { (void (*)(void))((unsigned long)&__STACK_TOP), // The initial stack pointer ResetISR, // The reset handler NmiSR, // The NMI handler FaultISR, // The hard fault handler IntDefaultHandler, // The MPU fault handler IntDefaultHandler, // The bus fault handler IntDefaultHandler, // The usage fault handler 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved IntDefaultHandler, // SVCall handler IntDefaultHandler, // Debug monitor handler 0, // Reserved IntDefaultHandler, // The PendSV handler #if (SYST_TESTING == 1) SYST_Handler, // The M0 System timer handler #else IntDefaultHandler, // The M0 System timer handler #endif ADC_Handler, // ADC handler IntDefaultHandler, #if(OWI_TESTING == 1) // OWI_Activation_Handler, // OWI_Activation_Handler, OWI Activation handler #else IntDefaultHandler, #endif #if (COMBUF_TESTING == 1) COMBUF_Handler, // COMBUF RX handler #else IntDefaultHandler, // #endif IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // IntDefaultHandler, // };
Anybody got any Ideas?
Since v6m allows "up to 32" external interrupts, and sysTick is not "external", it follows that the "enable" isn't going to fit in the same 32bit NVIC_ENABLE0 register with the other enable bits.
NVIC_ENABLE0
Indeed, section B.3.2.10 of the ARM says that the "system Handler priority" for sysTick and PendSV are off in SCR->SHPR3 (I don't know what TI calls it, since they seem to have ignored CMSIS Core...)
The ARM CMSIS core_cm0.h file has a definition for NVIC_SetPriority() that special-cases the system interrupts:
__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority){ if ((int32_t)(IRQn) < 0) { SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } else { NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); }}
__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
if ((int32_t)(IRQn) < 0)
SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
(((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
}
else
NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
I also tried my luck with stack overflow, but the best advice that was given to me, was to dump the whole TI-code and rewrite it myself...If you achieve anything better please let me know.
As it seems the PGA970 also lacks the core_cm0.h file your mentioning. The only function using any sort of "PRIO" (searched it with win Explorer) are the arm_m0.h which manages the adresses of the different registers and the pga970_isr.c which I posted in my original post. But I realised that there are 60 adresses for NVIC_PRI (0-59) while only NVIC_PRI 0 and NVIC_PRI1 are written onto. Maybe I would need to set a value to NVIC_PRI15 (number for SysTick). But I cant find any Information on what to write into such registers.
> But I cant find any Information on what to write into such registers.
A lot of vendors choose not to document the ARM "Core" functions. Instead they just refer you to the ARM documentation.
See here, and related: https://developer.arm.com/documentation/dui0497/a/cortex-m0-peripherals/system-control-block/system-handler-priority-registers
(and also (pdf warning) https://documentation-service.arm.com/static/5f8ff05ef86e16515cdbf826 )
You're using TI's CCStudio and CCS? I tried making a sample PGA970 program, and I couldn't even find arm_m0.h, nor the NVIC_PRI0 symbol you are using :-(
NVIC_PRI0 symbol you are using :-(
This is when a standard like CMSIS comes in handy; in theory the functions and register names for the ARM core and core peripherals would all be the same, regardless of who put the vendor-dependent stuff in, and regardless of which compiler or IDE you are using. (At least for CMSIS-Core, which defines such things for the ARM core. Parts like CMSIS-Driver that attempt to abstract higher-level peripherals like UARTs and Ethernet are ... more ambiguous in their utility (because of the vast differences in hardware implementations.)) (Although even CMSIS Core doesn't seem to be perfect. The SHPR3 register that I think is relevant (and documented in the Archiecture Refrence Manual) seems to be called SCB->SHP[1] in the core_cm0.h file.)
BTW, are you 100% sure that the M0 on the PGA970 actually HAS a SysTick timer?
It is considered an "optional" part of the CM0 cpu...
Documentation seems pretty ... sparse, and I'm having a lot of trouble finding a version of CCS that actually has the .h files that the software users guide says should get inserted into a project (which could be because I'm not using CCS correctly, I guess.)
You can try doing this:
/* Manually import some defs from arm cm0_core.h */#include <stdint.h>#define __IM volatile#define __IOM volatiletypedef struct{ __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ uint32_t RESERVED0; __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ uint32_t RESERVED1; __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */} SCB_Type;/* Memory mapping of Cortex-M0 Hardware */#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */void Interrupt_Config(void){ SCB->SHP[1] = 0xC0C00000; // enable SysTick and PendSC interrupts?
/* Manually import some defs from arm cm0_core.h */
#include <stdint.h>
#define __IM volatile
#define __IOM volatile
typedef struct
__IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
__IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
uint32_t RESERVED0;
__IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
__IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
__IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
uint32_t RESERVED1;
__IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
__IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
} SCB_Type;
/* Memory mapping of Cortex-M0 Hardware */
#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
void Interrupt_Config(void)
SCB->SHP[1] = 0xC0C00000; // enable SysTick and PendSC interrupts?
// etc
Hi Bill, sorry for the late respone i got sick.As for the Firmware I am using the "PGA970_FW_Release_1_5_Generic" (which does include the SysTick features) and their most recent version "PGA970_FW_Release_1_6_Generic" (which does not include SysTick). In order to get the SysTimer to work I am currently working with the 1.5 in a basic programm.But I am not able to find where (at TexasInstruments) I got that firmwares. I could upload/sent it to you if you wish.I am using CCS and got all Software directly from TI where also the arm_m0.h file is included. In my file it was located in source>chip>inc.You are right, I am not a 100% certain that there actually is a working SysTimer worked in, espacially because its mentioning got deleted in a later FW release... I will try manually importing the files and see if that does the trick.