Merge pull request #11122 from ibr-cm/hartung/atmega-pin-change-interrupt-pseudomodules
cpu/atmega_common: pseudomodule-based pin change interrupt implementation
This commit is contained in:
commit
e612d3d71b
@ -46,6 +46,11 @@ This should take care of everything!
|
|||||||
We use the open `avrdude` tool to write the new code into the ATmega2560's
|
We use the open `avrdude` tool to write the new code into the ATmega2560's
|
||||||
flash
|
flash
|
||||||
|
|
||||||
|
## Pin Change Interrupts
|
||||||
|
|
||||||
|
More pins can be used for hardware interrupts using the Pin Change
|
||||||
|
Interrupt feature. See @ref boards_common_atmega for details.
|
||||||
|
|
||||||
## State
|
## State
|
||||||
While there is basic support in RIOT, there are still some parts missing:
|
While there is basic support in RIOT, there are still some parts missing:
|
||||||
* Timer implementation needs love (ideally simulate a 32bit timer by adding
|
* Timer implementation needs love (ideally simulate a 32bit timer by adding
|
||||||
|
|||||||
16
boards/arduino-mega2560/include/atmega_pcint.h
Normal file
16
boards/arduino-mega2560/include/atmega_pcint.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef ATMEGA_PCINT_H
|
||||||
|
#define ATMEGA_PCINT_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ATMEGA_PCINT_MAP_PCINT0 GPIO_PIN(PORT_B, 0), GPIO_PIN(PORT_B, 1), GPIO_PIN(PORT_B, 2), GPIO_PIN(PORT_B, 3), GPIO_PIN(PORT_B, 4), GPIO_PIN(PORT_B, 5), GPIO_PIN(PORT_B, 6), GPIO_PIN(PORT_B, 7)
|
||||||
|
#define ATMEGA_PCINT_MAP_PCINT1 GPIO_PIN(PORT_E, 0), GPIO_PIN(PORT_J, 0), GPIO_PIN(PORT_J, 1), GPIO_UNDEF, GPIO_UNDEF, GPIO_UNDEF, GPIO_UNDEF, GPIO_UNDEF
|
||||||
|
#define ATMEGA_PCINT_MAP_PCINT2 GPIO_PIN(PORT_K, 0), GPIO_PIN(PORT_K, 1), GPIO_PIN(PORT_K, 2), GPIO_PIN(PORT_K, 3), GPIO_PIN(PORT_K, 4), GPIO_PIN(PORT_K, 5), GPIO_PIN(PORT_K, 6), GPIO_PIN(PORT_K, 7)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ATMEGA_PCINT_H */
|
||||||
@ -37,6 +37,11 @@ This should take care of everything!
|
|||||||
We use the open `avrdude` tool to write the new code into the ATmega328p's
|
We use the open `avrdude` tool to write the new code into the ATmega328p's
|
||||||
flash
|
flash
|
||||||
|
|
||||||
|
## Pin Change Interrupts
|
||||||
|
|
||||||
|
More pins can be used for hardware interrupts using the Pin Change
|
||||||
|
Interrupt feature. See @ref boards_common_atmega for details.
|
||||||
|
|
||||||
##Caution
|
##Caution
|
||||||
Don't expect having a working network stack due to very limited resources.
|
Don't expect having a working network stack due to very limited resources.
|
||||||
*/
|
*/
|
||||||
|
|||||||
17
boards/common/atmega/doc.txt
Normal file
17
boards/common/atmega/doc.txt
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
@defgroup boards_common_atmega ATmega common
|
||||||
|
@ingroup boards
|
||||||
|
@brief Shared files and configuration for ATmega-based boards
|
||||||
|
|
||||||
|
### Pin Change Interrupts
|
||||||
|
|
||||||
|
Pin Change Interrupts (PCINTs) can be enabled using pseudo modules. To provide
|
||||||
|
a low-memory overhead implementation, the PCINTs are grouped into **banks**.
|
||||||
|
Each banks corresponds to one PCINT on the ATmega (PCINT0, ..., PCINT3).
|
||||||
|
|
||||||
|
To enable only a specific bank, simply add `USEMODULE += atmega_pcintN` to your
|
||||||
|
Makefile. To enable all interrupts you can use `USEMODULE += atmega_pcint`.
|
||||||
|
|
||||||
|
In case you want to add a new CPU, simply provide an `atmega_pcint.h` with your
|
||||||
|
CPU and adapt your Makefile.dep and Makefile.featues files.
|
||||||
|
*/
|
||||||
@ -173,4 +173,9 @@ the clocks for all peripherals are enabled and set to the smallest divider (high
|
|||||||
power consumption. When the device should be put into deep sleep it is recommended to use the internal RC oscillator
|
power consumption. When the device should be put into deep sleep it is recommended to use the internal RC oscillator
|
||||||
as system clock source.
|
as system clock source.
|
||||||
|
|
||||||
|
## Pin Change Interrupts
|
||||||
|
|
||||||
|
More pins can be used for hardware interrupts using the Pin Change
|
||||||
|
Interrupt feature. See @ref boards_common_atmega for details.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -34,4 +34,10 @@ It will be used automatically with `make term`:
|
|||||||
```
|
```
|
||||||
make BOARD=mega-xplained -C examples/hello-world term
|
make BOARD=mega-xplained -C examples/hello-world term
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Pin Change Interrupts
|
||||||
|
|
||||||
|
More pins can be used for hardware interrupts using the Pin Change
|
||||||
|
Interrupt feature. See @ref boards_common_atmega for details.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -2,4 +2,10 @@
|
|||||||
@defgroup boards_waspmote-pro Waspmote PRO v1.2
|
@defgroup boards_waspmote-pro Waspmote PRO v1.2
|
||||||
@ingroup boards
|
@ingroup boards
|
||||||
@brief Support for the Waspmote PRO v1.2 board.
|
@brief Support for the Waspmote PRO v1.2 board.
|
||||||
|
|
||||||
|
## Pin Change Interrupts
|
||||||
|
|
||||||
|
More pins can be used for hardware interrupts using the Pin Change
|
||||||
|
Interrupt feature. See @ref boards_common_atmega for details.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -1 +1,3 @@
|
|||||||
-include $(RIOTCPU)/atmega_common/Makefile.features
|
FEATURES_PROVIDED += atmega_pcint1 atmega_pcint2
|
||||||
|
|
||||||
|
include $(RIOTCPU)/atmega_common/Makefile.features
|
||||||
|
|||||||
@ -4,5 +4,10 @@ USEMODULE += atmega_common
|
|||||||
RAM_LEN = 8K
|
RAM_LEN = 8K
|
||||||
ROM_LEN = 128K
|
ROM_LEN = 128K
|
||||||
|
|
||||||
|
# expand atmega_pcint for additional PCINTs of atmega1281
|
||||||
|
ifneq (,$(filter atmega_pcint,$(USEMODULE)))
|
||||||
|
USEMODULE += atmega_pcint1 atmega_pcint2
|
||||||
|
endif
|
||||||
|
|
||||||
# CPU depends on the atmega common module, so include it
|
# CPU depends on the atmega common module, so include it
|
||||||
include $(RIOTCPU)/atmega_common/Makefile.include
|
include $(RIOTCPU)/atmega_common/Makefile.include
|
||||||
|
|||||||
16
cpu/atmega1281/include/atmega_pcint.h
Normal file
16
cpu/atmega1281/include/atmega_pcint.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef ATMEGA_PCINT_H
|
||||||
|
#define ATMEGA_PCINT_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ATMEGA_PCINT_MAP_PCINT0 GPIO_PIN(PORT_B, 0), GPIO_PIN(PORT_B, 1), GPIO_PIN(PORT_B, 2), GPIO_PIN(PORT_B, 3), GPIO_PIN(PORT_B, 4), GPIO_PIN(PORT_B, 5), GPIO_PIN(PORT_B, 6), GPIO_PIN(PORT_B, 7)
|
||||||
|
#define ATMEGA_PCINT_MAP_PCINT1 GPIO_PIN(PORT_E, 0), GPIO_PIN(PORT_J, 0), GPIO_PIN(PORT_J, 1), GPIO_PIN(PORT_J, 2), GPIO_PIN(PORT_J, 3), GPIO_PIN(PORT_J, 4), GPIO_PIN(PORT_J, 5), GPIO_PIN(PORT_J, 6)
|
||||||
|
#define ATMEGA_PCINT_MAP_PCINT2 GPIO_PIN(PORT_K, 0), GPIO_PIN(PORT_K, 1), GPIO_PIN(PORT_K, 2), GPIO_PIN(PORT_K, 3), GPIO_PIN(PORT_K, 4), GPIO_PIN(PORT_K, 5), GPIO_PIN(PORT_K, 6), GPIO_PIN(PORT_K, 7)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ATMEGA_PCINT_H */
|
||||||
6
cpu/atmega1284p/Makefile.dep
Normal file
6
cpu/atmega1284p/Makefile.dep
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# additional PCINTs for atmega1284p
|
||||||
|
ifneq (,$(filter atmega_pcint,$(USEMODULE)))
|
||||||
|
USEMODULE += atmega_pcint1 atmega_pcint2 atmega_pcint3
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(RIOTCPU)/atmega_common/Makefile.dep
|
||||||
@ -1 +1,4 @@
|
|||||||
-include $(RIOTCPU)/atmega_common/Makefile.features
|
# additional PCINTs for atmega1284p
|
||||||
|
FEATURES_PROVIDED += atmega_pcint1 atmega_pcint2 atmega_pcint3
|
||||||
|
|
||||||
|
include $(RIOTCPU)/atmega_common/Makefile.features
|
||||||
|
|||||||
@ -4,5 +4,10 @@ USEMODULE += atmega_common
|
|||||||
RAM_LEN = 16K
|
RAM_LEN = 16K
|
||||||
ROM_LEN = 128K
|
ROM_LEN = 128K
|
||||||
|
|
||||||
|
# expand atmega_pcint for atmega1284p
|
||||||
|
ifneq (,$(filter atmega_pcint,$(USEMODULE)))
|
||||||
|
USEMODULE += atmega_pcint1 atmega_pcint2 atmega_pcint3
|
||||||
|
endif
|
||||||
|
|
||||||
# CPU depends on the atmega common module, so include it
|
# CPU depends on the atmega common module, so include it
|
||||||
include $(RIOTCPU)/atmega_common/Makefile.include
|
include $(RIOTCPU)/atmega_common/Makefile.include
|
||||||
|
|||||||
17
cpu/atmega1284p/include/atmega_pcint.h
Normal file
17
cpu/atmega1284p/include/atmega_pcint.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef ATMEGA_PCINT_H
|
||||||
|
#define ATMEGA_PCINT_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ATMEGA_PCINT_MAP_PCINT0 GPIO_PIN(PORT_A, 0), GPIO_PIN(PORT_A, 1), GPIO_PIN(PORT_A, 2), GPIO_PIN(PORT_A, 3), GPIO_PIN(PORT_A, 4), GPIO_PIN(PORT_A, 5), GPIO_PIN(PORT_A, 6), GPIO_PIN(PORT_A, 7)
|
||||||
|
#define ATMEGA_PCINT_MAP_PCINT1 GPIO_PIN(PORT_B, 0), GPIO_PIN(PORT_B, 1), GPIO_PIN(PORT_B, 2), GPIO_PIN(PORT_B, 3), GPIO_PIN(PORT_B, 4), GPIO_PIN(PORT_B, 5), GPIO_PIN(PORT_B, 6), GPIO_PIN(PORT_B, 7)
|
||||||
|
#define ATMEGA_PCINT_MAP_PCINT2 GPIO_PIN(PORT_C, 0), GPIO_PIN(PORT_C, 1), GPIO_PIN(PORT_C, 2), GPIO_PIN(PORT_C, 3), GPIO_PIN(PORT_C, 4), GPIO_PIN(PORT_C, 5), GPIO_PIN(PORT_C, 6), GPIO_PIN(PORT_C, 7)
|
||||||
|
#define ATMEGA_PCINT_MAP_PCINT3 GPIO_PIN(PORT_D, 0), GPIO_PIN(PORT_D, 1), GPIO_PIN(PORT_D, 2), GPIO_PIN(PORT_D, 3), GPIO_PIN(PORT_D, 4), GPIO_PIN(PORT_D, 5), GPIO_PIN(PORT_D, 6), GPIO_PIN(PORT_D, 7)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ATMEGA_PCINT_H */
|
||||||
6
cpu/atmega2560/Makefile.dep
Normal file
6
cpu/atmega2560/Makefile.dep
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# additional PCINTs for atmega2560
|
||||||
|
ifneq (,$(filter atmega_pcint,$(USEMODULE)))
|
||||||
|
USEMODULE += atmega_pcint1 atmega_pcint2
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(RIOTCPU)/atmega_common/Makefile.dep
|
||||||
@ -1 +1,3 @@
|
|||||||
-include $(RIOTCPU)/atmega_common/Makefile.features
|
FEATURES_PROVIDED += atmega_pcint1 atmega_pcint2
|
||||||
|
|
||||||
|
include $(RIOTCPU)/atmega_common/Makefile.features
|
||||||
|
|||||||
@ -4,5 +4,10 @@ USEMODULE += atmega_common
|
|||||||
RAM_LEN = 8K
|
RAM_LEN = 8K
|
||||||
ROM_LEN = 256K
|
ROM_LEN = 256K
|
||||||
|
|
||||||
|
# expand atmega_pcint with additional PCINTs for atmega2560
|
||||||
|
ifneq (,$(filter atmega_pcint,$(USEMODULE)))
|
||||||
|
USEMODULE += atmega_pcint1 atmega_pcint2
|
||||||
|
endif
|
||||||
|
|
||||||
# CPU depends on the atmega common module, so include it
|
# CPU depends on the atmega common module, so include it
|
||||||
include $(RIOTCPU)/atmega_common/Makefile.include
|
include $(RIOTCPU)/atmega_common/Makefile.include
|
||||||
|
|||||||
16
cpu/atmega2560/include/atmega_pcint.h
Normal file
16
cpu/atmega2560/include/atmega_pcint.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef ATMEGA_PCINT_H
|
||||||
|
#define ATMEGA_PCINT_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ATMEGA_PCINT_MAP_PCINT0 GPIO_PIN(PORT_B, 0), GPIO_PIN(PORT_B, 1), GPIO_PIN(PORT_B, 2), GPIO_PIN(PORT_B, 3), GPIO_PIN(PORT_B, 4), GPIO_PIN(PORT_B, 5), GPIO_PIN(PORT_B, 6), GPIO_PIN(PORT_B, 7)
|
||||||
|
#define ATMEGA_PCINT_MAP_PCINT1 GPIO_PIN(PORT_E, 0), GPIO_PIN(PORT_J, 0), GPIO_PIN(PORT_J, 1), GPIO_PIN(PORT_J, 2), GPIO_PIN(PORT_J, 3), GPIO_PIN(PORT_J, 4), GPIO_PIN(PORT_J, 5), GPIO_PIN(PORT_J, 6)
|
||||||
|
#define ATMEGA_PCINT_MAP_PCINT2 GPIO_PIN(PORT_K, 0), GPIO_PIN(PORT_K, 1), GPIO_PIN(PORT_K, 2), GPIO_PIN(PORT_K, 3), GPIO_PIN(PORT_K, 4), GPIO_PIN(PORT_K, 5), GPIO_PIN(PORT_K, 6), GPIO_PIN(PORT_K, 7)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ATMEGA_PCINT_H */
|
||||||
6
cpu/atmega256rfr2/Makefile.dep
Normal file
6
cpu/atmega256rfr2/Makefile.dep
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# additional PCINTs for atmega256rfr2
|
||||||
|
ifneq (,$(filter atmega_pcint,$(USEMODULE)))
|
||||||
|
USEMODULE += atmega_pcint1
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(RIOTCPU)/atmega_common/Makefile.dep
|
||||||
@ -1,7 +1,9 @@
|
|||||||
include $(RIOTCPU)/atmega_common/Makefile.features
|
include $(RIOTCPU)/atmega_common/Makefile.features
|
||||||
|
|
||||||
# common feature are defined in atmega_common/Makefile.features
|
# common feature are defined in atmega_common/Makefile.features
|
||||||
# Only add Additional features
|
# Only add Additional features
|
||||||
|
|
||||||
|
# additional PCINT for atmega256rfr2
|
||||||
|
FEATURES_PROVIDED += atmega_pcint1
|
||||||
|
|
||||||
# Various other features (if any)
|
# Various other features (if any)
|
||||||
FEATURES_PROVIDED += periph_cpuid
|
FEATURES_PROVIDED += periph_cpuid
|
||||||
|
|||||||
@ -7,5 +7,10 @@ USEMODULE += periph
|
|||||||
RAM_LEN = 32K
|
RAM_LEN = 32K
|
||||||
ROM_LEN = 256K
|
ROM_LEN = 256K
|
||||||
|
|
||||||
|
# expand atmega_pcint for atmega256rfr2
|
||||||
|
ifneq (,$(filter atmega_pcint,$(USEMODULE)))
|
||||||
|
USEMODULE += atmega_pcint1
|
||||||
|
endif
|
||||||
|
|
||||||
# CPU depends on the atmega common module, so include it
|
# CPU depends on the atmega common module, so include it
|
||||||
include $(RIOTCPU)/atmega_common/Makefile.include
|
include $(RIOTCPU)/atmega_common/Makefile.include
|
||||||
|
|||||||
15
cpu/atmega256rfr2/include/atmega_pcint.h
Normal file
15
cpu/atmega256rfr2/include/atmega_pcint.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef ATMEGA_PCINT_H
|
||||||
|
#define ATMEGA_PCINT_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ATMEGA_PCINT_MAP_PCINT0 GPIO_PIN(PORT_B, 0), GPIO_PIN(PORT_B, 1), GPIO_PIN(PORT_B, 2), GPIO_PIN(PORT_B, 3), GPIO_PIN(PORT_B, 4), GPIO_PIN(PORT_B, 5), GPIO_PIN(PORT_B, 6), GPIO_PIN(PORT_B, 7)
|
||||||
|
#define ATMEGA_PCINT_MAP_PCINT1 GPIO_PIN(PORT_E, 0), GPIO_UNDEF, GPIO_UNDEF, GPIO_UNDEF, GPIO_UNDEF, GPIO_UNDEF, GPIO_UNDEF, GPIO_UNDEF
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ATMEGA_PCINT_H */
|
||||||
@ -1 +1,3 @@
|
|||||||
-include $(RIOTCPU)/atmega_common/Makefile.features
|
FEATURES_PROVIDED += atmega_pcint1 atmega_pcint2
|
||||||
|
|
||||||
|
include $(RIOTCPU)/atmega_common/Makefile.features
|
||||||
|
|||||||
@ -4,5 +4,10 @@ USEMODULE += atmega_common
|
|||||||
RAM_LEN = 2K
|
RAM_LEN = 2K
|
||||||
ROM_LEN = 32K
|
ROM_LEN = 32K
|
||||||
|
|
||||||
|
# additional PCINTs for atmega328p
|
||||||
|
ifneq (,$(filter atmega_pcint,$(USEMODULE)))
|
||||||
|
USEMODULE += atmega_pcint1 atmega_pcint2
|
||||||
|
endif
|
||||||
|
|
||||||
# CPU depends on the atmega common module, so include it
|
# CPU depends on the atmega common module, so include it
|
||||||
include $(RIOTCPU)/atmega_common/Makefile.include
|
include $(RIOTCPU)/atmega_common/Makefile.include
|
||||||
|
|||||||
16
cpu/atmega328p/include/atmega_pcint.h
Normal file
16
cpu/atmega328p/include/atmega_pcint.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef ATMEGA_PCINT_H
|
||||||
|
#define ATMEGA_PCINT_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ATMEGA_PCINT_MAP_PCINT0 GPIO_PIN(PORT_B, 0), GPIO_PIN(PORT_B, 1), GPIO_PIN(PORT_B, 2), GPIO_PIN(PORT_B, 3), GPIO_PIN(PORT_B, 4), GPIO_PIN(PORT_B, 5), GPIO_PIN(PORT_B, 6), GPIO_PIN(PORT_B, 7)
|
||||||
|
#define ATMEGA_PCINT_MAP_PCINT1 GPIO_PIN(PORT_C, 0), GPIO_PIN(PORT_C, 1), GPIO_PIN(PORT_C, 2), GPIO_PIN(PORT_C, 3), GPIO_PIN(PORT_C, 4), GPIO_PIN(PORT_C, 5), GPIO_PIN(PORT_C, 6), GPIO_UNDEF
|
||||||
|
#define ATMEGA_PCINT_MAP_PCINT2 GPIO_PIN(PORT_D, 0), GPIO_PIN(PORT_D, 1), GPIO_PIN(PORT_D, 2), GPIO_PIN(PORT_D, 3), GPIO_PIN(PORT_D, 4), GPIO_PIN(PORT_D, 5), GPIO_PIN(PORT_D, 6), GPIO_PIN(PORT_D, 7)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ATMEGA_PCINT_H */
|
||||||
2
cpu/atmega32u4/Makefile.dep
Normal file
2
cpu/atmega32u4/Makefile.dep
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# common Makefile.dep expand the atmega_pcint pseudo module
|
||||||
|
include $(RIOTCPU)/atmega_common/Makefile.dep
|
||||||
@ -1 +1,2 @@
|
|||||||
-include $(RIOTCPU)/atmega_common/Makefile.features
|
# atmega_common provides atmega_pcint0
|
||||||
|
include $(RIOTCPU)/atmega_common/Makefile.features
|
||||||
|
|||||||
14
cpu/atmega32u4/include/atmega_pcint.h
Normal file
14
cpu/atmega32u4/include/atmega_pcint.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef ATMEGA_PCINT_H
|
||||||
|
#define ATMEGA_PCINT_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ATMEGA_PCINT_MAP_PCINT0 GPIO_PIN(PORT_B, 0), GPIO_PIN(PORT_B, 1), GPIO_PIN(PORT_B, 2), GPIO_PIN(PORT_B, 3), GPIO_PIN(PORT_B, 4), GPIO_PIN(PORT_B, 5), GPIO_PIN(PORT_B, 6), GPIO_PIN(PORT_B, 7)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ATMEGA_PCINT_H */
|
||||||
24
cpu/atmega_common/Makefile.dep
Normal file
24
cpu/atmega_common/Makefile.dep
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# expand atmega_pcint module
|
||||||
|
ifneq (,$(filter atmega_pcint,$(USEMODULE)))
|
||||||
|
USEMODULE += atmega_pcint0
|
||||||
|
endif
|
||||||
|
|
||||||
|
# feature for atmega_pcint0 module
|
||||||
|
ifneq (,$(filter atmega_pcint0,$(USEMODULE)))
|
||||||
|
FEATURES_REQUIRED += atmega_pcint0
|
||||||
|
endif
|
||||||
|
|
||||||
|
# feature for atmega_pcint1 module
|
||||||
|
ifneq (,$(filter atmega_pcint1,$(USEMODULE)))
|
||||||
|
FEATURES_REQUIRED += atmega_pcint1
|
||||||
|
endif
|
||||||
|
|
||||||
|
# feature for atmega_pcint2 module
|
||||||
|
ifneq (,$(filter atmega_pcint2,$(USEMODULE)))
|
||||||
|
FEATURES_REQUIRED += atmega_pcint2
|
||||||
|
endif
|
||||||
|
|
||||||
|
# feature for atmega_pcint3 module
|
||||||
|
ifneq (,$(filter atmega_pcint3,$(USEMODULE)))
|
||||||
|
FEATURES_REQUIRED += atmega_pcint3
|
||||||
|
endif
|
||||||
@ -1,2 +1,4 @@
|
|||||||
FEATURES_PROVIDED += periph_eeprom
|
FEATURES_PROVIDED += periph_eeprom
|
||||||
FEATURES_PROVIDED += periph_pm
|
FEATURES_PROVIDED += periph_pm
|
||||||
|
|
||||||
|
FEATURES_PROVIDED += atmega_pcint0
|
||||||
|
|||||||
@ -6,4 +6,34 @@ export INCLUDES += -I$(RIOTCPU)/atmega_common/include \
|
|||||||
# avr libc needs some RIOT-specific support code
|
# avr libc needs some RIOT-specific support code
|
||||||
USEMODULE += avr_libc_extra
|
USEMODULE += avr_libc_extra
|
||||||
|
|
||||||
|
PSEUDOMODULES += atmega_pcint
|
||||||
|
PSEUDOMODULES += atmega_pcint%
|
||||||
|
|
||||||
|
# expand atmega_pcint module
|
||||||
|
# atmega16u4 only features atmega_pcint0, therefore additional pseudomodules
|
||||||
|
# are activated in each CPU's Makefile.include
|
||||||
|
ifneq (,$(filter atmega_pcint,$(USEMODULE)))
|
||||||
|
USEMODULE += atmega_pcint0
|
||||||
|
endif
|
||||||
|
|
||||||
|
# feature for atmega_pcint0 module
|
||||||
|
ifneq (,$(filter atmega_pcint0,$(USEMODULE)))
|
||||||
|
FEATURES_REQUIRED += atmega_pcint0
|
||||||
|
endif
|
||||||
|
|
||||||
|
# feature for atmega_pcint1 module
|
||||||
|
ifneq (,$(filter atmega_pcint1,$(USEMODULE)))
|
||||||
|
FEATURES_REQUIRED += atmega_pcint1
|
||||||
|
endif
|
||||||
|
|
||||||
|
# feature for atmega_pcint2 module
|
||||||
|
ifneq (,$(filter atmega_pcint2,$(USEMODULE)))
|
||||||
|
FEATURES_REQUIRED += atmega_pcint2
|
||||||
|
endif
|
||||||
|
|
||||||
|
# feature for atmega_pcint3 module
|
||||||
|
ifneq (,$(filter atmega_pcint3,$(USEMODULE)))
|
||||||
|
FEATURES_REQUIRED += atmega_pcint3
|
||||||
|
endif
|
||||||
|
|
||||||
include $(RIOTMAKE)/arch/atmega.inc.mk
|
include $(RIOTMAKE)/arch/atmega.inc.mk
|
||||||
|
|||||||
@ -19,6 +19,9 @@
|
|||||||
* @author René Herthel <rene-herthel@outlook.de>
|
* @author René Herthel <rene-herthel@outlook.de>
|
||||||
* @author Francisco Acosta <francisco.acosta@inria.fr>
|
* @author Francisco Acosta <francisco.acosta@inria.fr>
|
||||||
* @author Laurent Navet <laurent.navet@gmail.com>
|
* @author Laurent Navet <laurent.navet@gmail.com>
|
||||||
|
* @author Robert Hartung <hartung@ibr.cs.tu-bs.de>
|
||||||
|
* @author Torben Petersen <petersen@ibr.cs.tu-bs.de>
|
||||||
|
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
|
||||||
*
|
*
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
@ -28,10 +31,14 @@
|
|||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "board.h"
|
||||||
#include "periph/gpio.h"
|
#include "periph/gpio.h"
|
||||||
#include "periph_conf.h"
|
#include "periph_conf.h"
|
||||||
#include "periph_cpu.h"
|
#include "periph_cpu.h"
|
||||||
|
|
||||||
|
#define ENABLE_DEBUG (0)
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
#define GPIO_BASE_PORT_A (0x20)
|
#define GPIO_BASE_PORT_A (0x20)
|
||||||
#define GPIO_OFFSET_PORT_H (0xCB)
|
#define GPIO_OFFSET_PORT_H (0xCB)
|
||||||
#define GPIO_OFFSET_PIN_PORT (0x02)
|
#define GPIO_OFFSET_PIN_PORT (0x02)
|
||||||
@ -42,6 +49,7 @@
|
|||||||
* @brief Define GPIO interruptions for an specific atmega CPU, by default
|
* @brief Define GPIO interruptions for an specific atmega CPU, by default
|
||||||
* 2 (for small atmega CPUs)
|
* 2 (for small atmega CPUs)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(INT7_vect)
|
#if defined(INT7_vect)
|
||||||
#define GPIO_EXT_INT_NUMOF (8U)
|
#define GPIO_EXT_INT_NUMOF (8U)
|
||||||
#elif defined(INT6_vect)
|
#elif defined(INT6_vect)
|
||||||
@ -59,6 +67,104 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static gpio_isr_ctx_t config[GPIO_EXT_INT_NUMOF];
|
static gpio_isr_ctx_t config[GPIO_EXT_INT_NUMOF];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief detects ammount of possible PCINTs
|
||||||
|
*/
|
||||||
|
#if defined(MODULE_ATMEGA_PCINT0) || defined(MODULE_ATMEGA_PCINT1) || \
|
||||||
|
defined(MODULE_ATMEGA_PCINT2) || defined(MODULE_ATMEGA_PCINT3)
|
||||||
|
#include "atmega_pcint.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief check which pcints should be enabled!
|
||||||
|
*/
|
||||||
|
#ifdef MODULE_ATMEGA_PCINT0
|
||||||
|
#ifndef ATMEGA_PCINT_MAP_PCINT0
|
||||||
|
#error \
|
||||||
|
Either mapping for pin change interrupt bank 0 is missing or not supported by the MCU
|
||||||
|
#else
|
||||||
|
#define PCINT0_IDX (0)
|
||||||
|
#define _COUNTER0 (1)
|
||||||
|
#endif /* ATMEGA_PCINT_MAP_PCINT0 */
|
||||||
|
#else
|
||||||
|
#define _COUNTER0 (0)
|
||||||
|
#endif /* MODULE_ATMEGA_PCINT0 */
|
||||||
|
|
||||||
|
#ifdef MODULE_ATMEGA_PCINT1
|
||||||
|
#ifndef ATMEGA_PCINT_MAP_PCINT1
|
||||||
|
#error \
|
||||||
|
Either mapping for pin change interrupt bank 1 is missing or not supported by the MCU
|
||||||
|
#else
|
||||||
|
#define PCINT1_IDX _COUNTER0
|
||||||
|
#define _COUNTER1 (_COUNTER0 + 1)
|
||||||
|
#endif /* ATMEGA_PCINT_MAP_PCINT1 */
|
||||||
|
#else
|
||||||
|
#define _COUNTER1 _COUNTER0
|
||||||
|
#endif /* MODULE_ATMEGA_PCINT1 */
|
||||||
|
|
||||||
|
#ifdef MODULE_ATMEGA_PCINT2
|
||||||
|
#ifndef ATMEGA_PCINT_MAP_PCINT2
|
||||||
|
#error \
|
||||||
|
Either mapping for pin change interrupt bank 2 is missing or not supported by the MCU
|
||||||
|
#else
|
||||||
|
#define PCINT2_IDX _COUNTER1
|
||||||
|
#define _COUNTER2 (_COUNTER1 + 1)
|
||||||
|
#endif /* ATMEGA_PCINT_MAP_PCINT2 */
|
||||||
|
#else
|
||||||
|
#define _COUNTER2 _COUNTER1
|
||||||
|
#endif /* MODULE_ATMEGA_PCINT2 */
|
||||||
|
|
||||||
|
#ifdef MODULE_ATMEGA_PCINT3
|
||||||
|
#ifndef ATMEGA_PCINT_MAP_PCINT3
|
||||||
|
#error \
|
||||||
|
Either mapping for pin change interrupt bank 3 is missing or not supported by the MCU
|
||||||
|
#else
|
||||||
|
#define PCINT3_IDX _COUNTER2
|
||||||
|
#define _COUNTER3 (_COUNTER2 + 1)
|
||||||
|
#endif /* ATMEGA_PCINT_MAP_PCINT3 */
|
||||||
|
#else
|
||||||
|
#define _COUNTER3 _COUNTER2
|
||||||
|
#endif /* MODULE_ATMEGA_PCINT3 */
|
||||||
|
|
||||||
|
#define PCINT_NUM_BANKS (_COUNTER3)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief stores the last pcint state of each port
|
||||||
|
*/
|
||||||
|
static uint8_t pcint_state[PCINT_NUM_BANKS];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief stores all cb and args for all defined pcint.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
gpio_flank_t flank; /**< type of interrupt the flank should be triggered on */
|
||||||
|
gpio_cb_t cb; /**< interrupt callback */
|
||||||
|
void *arg; /**< optional argument */
|
||||||
|
} gpio_isr_ctx_pcint_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
static const gpio_t pcint_mapping[] = {
|
||||||
|
#ifdef PCINT0_IDX
|
||||||
|
ATMEGA_PCINT_MAP_PCINT0,
|
||||||
|
#endif /* PCINT0_IDX */
|
||||||
|
#ifdef PCINT1_IDX
|
||||||
|
ATMEGA_PCINT_MAP_PCINT1,
|
||||||
|
#endif /* PCINT1_IDX */
|
||||||
|
#ifdef PCINT2_IDX
|
||||||
|
ATMEGA_PCINT_MAP_PCINT2,
|
||||||
|
#endif /* PCINT2_IDX */
|
||||||
|
#ifdef PCINT3_IDX
|
||||||
|
ATMEGA_PCINT_MAP_PCINT3,
|
||||||
|
#endif /* PCINT3_IDX */
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
static gpio_isr_ctx_pcint_t pcint_config[8 * PCINT_NUM_BANKS];
|
||||||
|
#endif /* MODULE_ATMEGA_PCINTn */
|
||||||
|
|
||||||
#endif /* MODULE_PERIPH_GPIO_IRQ */
|
#endif /* MODULE_PERIPH_GPIO_IRQ */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -115,6 +221,7 @@ static inline uint16_t _pin_addr(gpio_t pin)
|
|||||||
int gpio_init(gpio_t pin, gpio_mode_t mode)
|
int gpio_init(gpio_t pin, gpio_mode_t mode)
|
||||||
{
|
{
|
||||||
uint8_t pin_mask = (1 << _pin_num(pin));
|
uint8_t pin_mask = (1 << _pin_num(pin));
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case GPIO_OUT:
|
case GPIO_OUT:
|
||||||
_SFR_MEM8(_ddr_addr(pin)) |= pin_mask;
|
_SFR_MEM8(_ddr_addr(pin)) |= pin_mask;
|
||||||
@ -195,8 +302,82 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* not a valid interrupt pin */
|
/* not a valid interrupt pin. Set as pcint instead if pcints are enabled */
|
||||||
if (int_num < 0) {
|
if (int_num < 0) {
|
||||||
|
/* If pin change interrupts are enabled, enable mask and interrupt */
|
||||||
|
#ifdef PCINT_NUM_BANKS
|
||||||
|
int8_t offset = -1;
|
||||||
|
uint8_t pin_num = _pin_num(pin);
|
||||||
|
|
||||||
|
for (unsigned i = 0;
|
||||||
|
i < sizeof(pcint_mapping) / sizeof(pcint_mapping[0]); i++) {
|
||||||
|
if (pin != GPIO_UNDEF && pin == pcint_mapping[i]) {
|
||||||
|
offset = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if pcint was not found: return -1 */
|
||||||
|
if (offset < 0) {
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t bank = offset / 8;
|
||||||
|
uint8_t bank_idx = offset % 8;
|
||||||
|
DEBUG("PCINT enabled for bank %u offset %u\n",
|
||||||
|
(unsigned)bank, (unsigned)offset);
|
||||||
|
|
||||||
|
/* save configuration for pin change interrupt */
|
||||||
|
pcint_config[offset].flank = flank;
|
||||||
|
pcint_config[offset].arg = arg;
|
||||||
|
pcint_config[offset].cb = cb;
|
||||||
|
|
||||||
|
/* init gpio */
|
||||||
|
gpio_init(pin, mode);
|
||||||
|
/* configure pcint */
|
||||||
|
cli();
|
||||||
|
switch (bank) {
|
||||||
|
#ifdef PCINT0_IDX
|
||||||
|
case PCINT0_IDX:
|
||||||
|
PCMSK0 |= (1 << bank_idx);
|
||||||
|
PCICR |= (1 << PCIE0);
|
||||||
|
break;
|
||||||
|
#endif /* PCINT0_IDX */
|
||||||
|
#ifdef PCINT1_IDX
|
||||||
|
case PCINT1_IDX:
|
||||||
|
PCMSK1 |= (1 << bank_idx);
|
||||||
|
PCICR |= (1 << PCIE1);
|
||||||
|
break;
|
||||||
|
#endif /* PCINT1_IDX */
|
||||||
|
#ifdef PCINT2_IDX
|
||||||
|
case PCINT2_IDX:
|
||||||
|
PCMSK2 |= (1 << bank_idx);
|
||||||
|
PCICR |= (1 << PCIE2);
|
||||||
|
break;
|
||||||
|
#endif /* PCINT2_IDX */
|
||||||
|
#ifdef PCINT3_IDX
|
||||||
|
case PCINT3_IDX:
|
||||||
|
PCMSK3 |= (1 << pin_num);
|
||||||
|
PCICR |= (1 << PCIE3);
|
||||||
|
break;
|
||||||
|
#endif /* PCINT3_IDX */
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* As ports are mixed in a bank (e.g. PCINT0), we can only save a single bit here! */
|
||||||
|
uint8_t port_value = (_SFR_MEM8(_pin_addr( pin )));
|
||||||
|
uint8_t pin_mask = (1 << pin_num);
|
||||||
|
uint8_t pin_value = ((port_value & pin_mask) != 0);
|
||||||
|
if (pin_value) {
|
||||||
|
pcint_state[bank] |= pin_mask;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pcint_state[bank] &= ~pin_mask;
|
||||||
|
}
|
||||||
|
sei();
|
||||||
|
return 0;
|
||||||
|
#endif /* GPIO_PC_INT_NUMOF */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,6 +435,72 @@ static inline void irq_handler(uint8_t int_num)
|
|||||||
__exit_isr();
|
__exit_isr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PCINT_NUM_BANKS
|
||||||
|
/* inline function that is used by the PCINT ISR */
|
||||||
|
static inline void pcint_handler(uint8_t bank, uint8_t enabled_pcints)
|
||||||
|
{
|
||||||
|
__enter_isr();
|
||||||
|
/* Find right item */
|
||||||
|
uint8_t idx = 0;
|
||||||
|
|
||||||
|
while (enabled_pcints > 0) {
|
||||||
|
/* check if this pin is enabled & has changed */
|
||||||
|
if (enabled_pcints & 0x1) {
|
||||||
|
/* get pin from mapping (assumes 8 entries per bank!) */
|
||||||
|
gpio_t pin = pcint_mapping[bank * 8 + idx];
|
||||||
|
/* re-construct mask from pin */
|
||||||
|
uint8_t pin_mask = (1 << (_pin_num(pin)));
|
||||||
|
uint8_t idx_mask = (1 << idx);
|
||||||
|
uint8_t port_value = (_SFR_MEM8(_pin_addr( pin )));
|
||||||
|
uint8_t pin_value = ((port_value & pin_mask) != 0);
|
||||||
|
uint8_t old_state = ((pcint_state[bank] & idx_mask) != 0);
|
||||||
|
gpio_isr_ctx_pcint_t *conf = &pcint_config[bank * 8 + idx];
|
||||||
|
if (old_state != pin_value) {
|
||||||
|
pcint_state[bank] ^= idx_mask;
|
||||||
|
if ((conf->flank == GPIO_BOTH ||
|
||||||
|
(pin_value && conf->flank == GPIO_RISING) ||
|
||||||
|
(!pin_value && conf->flank == GPIO_FALLING))) {
|
||||||
|
/* execute callback routine */
|
||||||
|
conf->cb(conf->arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enabled_pcints = enabled_pcints >> 1;
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
__exit_isr();
|
||||||
|
}
|
||||||
|
#if defined(PCINT0_IDX)
|
||||||
|
ISR(PCINT0_vect, ISR_BLOCK)
|
||||||
|
{
|
||||||
|
pcint_handler(PCINT0_IDX, PCMSK0);
|
||||||
|
}
|
||||||
|
#endif /* PCINT0_IDX */
|
||||||
|
|
||||||
|
#if defined(PCINT1_IDX)
|
||||||
|
ISR(PCINT1_vect, ISR_BLOCK)
|
||||||
|
{
|
||||||
|
pcint_handler(PCINT1_IDX, PCMSK1);
|
||||||
|
}
|
||||||
|
#endif /* PCINT1_IDX */
|
||||||
|
|
||||||
|
#if defined(PCINT2_IDX)
|
||||||
|
ISR(PCINT2_vect, ISR_BLOCK)
|
||||||
|
{
|
||||||
|
pcint_handler(PCINT2_IDX, PCMSK2);
|
||||||
|
}
|
||||||
|
#endif /* PCINT2_IDX */
|
||||||
|
|
||||||
|
#if defined(PCINT3_IDX)
|
||||||
|
ISR(PCINT3_vect, ISR_BLOCK)
|
||||||
|
{
|
||||||
|
pcint_handler(PCINT3_IDX, PCMSK3);
|
||||||
|
}
|
||||||
|
#endif /* PCINT3_IDX */
|
||||||
|
|
||||||
|
#endif /* GPIO_PC_INT_NUMOF */
|
||||||
|
|
||||||
ISR(INT0_vect, ISR_BLOCK)
|
ISR(INT0_vect, ISR_BLOCK)
|
||||||
{
|
{
|
||||||
irq_handler(0); /**< predefined interrupt pin */
|
irq_handler(0); /**< predefined interrupt pin */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user