chip.h FAQ

Q: I wonder about the purpose of the two chip.h files in each arm chip.

  $ find arch/arm -name chip.h | grep stm32
  arch/arm/include/stm32/chip.h
  arch/arm/src/stm32/chip.h

A: The arch/arm/src/stm32/chip.h file was a bad idea that happened a long time ago.
Right now, I believe that its only required when CONFIG_ARMV7M_CMNVECTOR is selected in the configuration.
In that case, arch/arm/src/stm32/chip.h is included by arch/arm/src/armv7-m/up_vectors.c in order provide the number of interrupt vectors.
In stm32, arch/arm/src/stm32/chip.h provides the number of vectors indirectly by including the correct, chip-specific vectors.h file.
This function is a little more obvious in arch/arm/srch/lpc43xx/chip.h.

This arch/arm/src/xyz/chip.h is also a good way to export awkward internal header files in a cleaner way. But that use is optional and not required outside of the chip- and board-related directories.

For the arch/include/stm32/chip.h file, only set of definitions is required there: The NVIC priorities:

If CONFIG_ARMV7M_USEBASEPRI is selected, then interrupts will be disabled by setting the BASEPRI register to {{ NVIC_SYSH_DISABLE_PRIORITY}} so that most interrupts will not have execution priority.
SVCall must have execution priority in all cases.

In the normal cases, interrupts are not nest-able and all interrupts run at an execution priority between NVIC_SYSH_PRIORITY_MIN and NVIC_SYSH_PRIORITY_MAX (with NVIC_SYSH_PRIORITY_MAX reserved for SVCall).

If, in addition, CONFIG_ARCH_HIPRI_INTERRUPT is defined, then special high priority interrupts are supported.
These are not "nested" in the normal sense of the word.
These high priority interrupts can interrupt normal interrupt processing but execute outside of OS (although they can "get back into the game" via a PendSV interrupt).

In the normal course of things, interrupts must occasionally be disabled using the up_irq_save() inline function to prevent contention in use of resources that may be shared between interrupt level and non-interrupt level logic. Now the question arises, if we are using the BASEPRI to disable interrupts and have high priority interrupts enabled (CONFIG_ARCH_HIPRI_INTERRUPT=y), do we disable all interrupts except SVCall (we cannot disable SVCall interrupts)? Or do we only disable the "normal" interrupts?

If we are using the BASEPRI register to disable interrupts, then the answer is that we must disable ONLY the normal interrupts. That is because we cannot disable SVCALL interrupts and we cannot permit SVCAll interrupts running at a higher priority than the high priority interrupts. Otherwise, they will introduce jitter in the high priority interrupt response time.

Hence, if you need to disable the high priority interrupt, you will have to disable the interrupt either at the peripheral that generates the interrupt or at the interrupt controller (e.g., NVIC). Disabling global interrupts via the BASEPRI register cannot effect high priority interrupts.

These definitions only have to be here because NVIC implementations may differ in the number of priority levels.

Now, by convention, the arch/xyz/include/chip/abc/chip.h file is also used to provide all of the definitions that discriminate the features of the different members of the chip family.
It is not technically necessary that those chip feature definitions exist in this header file, but it is a good convention to follow so that it is easier for people who have to work across the differ architectures.

There is another really big difference between the two chip header files: They also different in scope:

  #include <arch/chip/chip.h>

So the arch/arm/include/xyz/chip.h header file is a place where you would want to put chip-related stuff that can be made visible to application code.
Chip capabilities is a good example of the kind of knowledge that applications might care about.