mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-17 04:52:59 +01:00
Merge #19752
19752: cpu/atmega_common: checking features instead of CPU models r=benpicco a=hugueslarrive ### Contribution description Splitted from: - #19740 ### Testing procedure Tested on atmega8 with: - #19755 This one probably need to be tested on others cpu. ### Tests on 1284p: #### tests/periph/adc ``` tests/periph/adc$ BOARD=atmega1284p make -j64 clean all | grep '^ ' && BOARD=atmega1284p AVRDUDE_PROGRAMMER='usbasp -F' make flash 2>&1 | grep -- 'of flash' && BOARD=atmega1284p PORT=/dev/ttyACM0 make term text data bss dec hex filename 10712 304 1021 12037 2f05 /home/hugues/github/cpu_atmega_common/RIOT/tests/periph/adc/bin/atmega1284p/tests_adc.elf avrdude: 11016 bytes of flash written avrdude: 11016 bytes of flash verified /home/hugues/github/cpu_atmega_common/RIOT/dist/tools/pyterm/pyterm -p "/dev/ttyACM0" -b "9600" Twisted not available, please install it if you want to use pyterm's JSON capabilities 2023-06-22 18:44:54,846 # Connect to serial port /dev/ttyACM0 Welcome to pyterm! Type '/exit' to exit. 2023-06-22 18:44:55,848 # 2023-06-22 18:44:55,848 # main(): This is RIOT! (Version: 2020.07-devel-15351-gc5f75c-cpu/atmega_common) 2023-06-22 18:44:55,848 # 2023-06-22 18:44:55,849 # RIOT ADC peripheral driver test 2023-06-22 18:44:55,849 # 2023-06-22 18:44:55,850 # This test will sample all available ADC lines once every 100ms with 2023-06-22 18:44:55,850 # a 10-bit resolution and print the sampled results to STDIO 2023-06-22 18:44:55,850 # 2023-06-22 18:44:55,850 # 2023-06-22 18:44:55,851 # Successfully initialized ADC_LINE(0) 2023-06-22 18:44:55,851 # Successfully initialized ADC_LINE(1) 2023-06-22 18:44:55,851 # Successfully initialized ADC_LINE(2) 2023-06-22 18:44:55,852 # Successfully initialized ADC_LINE(3) 2023-06-22 18:44:55,852 # Successfully initialized ADC_LINE(4) 2023-06-22 18:44:55,852 # Successfully initialized ADC_LINE(5) 2023-06-22 18:44:55,853 # Successfully initialized ADC_LINE(6) 2023-06-22 18:44:55,853 # Successfully initialized ADC_LINE(7) 2023-06-22 18:44:55,853 # ADC_LINE(0): 796 2023-06-22 18:44:55,854 # ADC_LINE(1): 599 2023-06-22 18:44:55,854 # ADC_LINE(2): 522 2023-06-22 18:44:55,854 # ADC_LINE(3): 485 2023-06-22 18:44:55,854 # ADC_LINE(4): 466 2023-06-22 18:44:55,854 # ADC_LINE(5): 466 2023-06-22 18:44:55,854 # ADC_LINE(6): 478 2023-06-22 18:44:55,855 # ADC_LINE(7): 501 2023-06-22 18:44:55,855 # Exiting Pyterm make: *** [/home/hugues/github/cpu_atmega_common/RIOT/tests/periph/adc/../../../Makefile.include:879: term] Interrompre ``` #### tests/periph/gpio ``` tests/periph/gpio$ BOARD=atmega1284p make -j64 clean all | grep '^ ' && BOARD=atmega1284p AVRDUDE_PROGRAMMER='usbasp -F' make flash 2>&1 | grep -- 'of flash' && BOARD=atmega1284p PORT=/dev/ttyACM0 make term text data bss dec hex filename 17828 2112 1095 21035 522b /home/hugues/github/cpu_atmega_common/RIOT/tests/periph/gpio/bin/atmega1284p/tests_gpio.elf avrdude: 19940 bytes of flash written avrdude: 19940 bytes of flash verified /home/hugues/github/cpu_atmega_common/RIOT/dist/tools/pyterm/pyterm -p "/dev/ttyACM0" -b "9600" Twisted not available, please install it if you want to use pyterm's JSON capabilities 2023-06-22 18:46:50,726 # Connect to serial port /dev/ttyACM0 Welcome to pyterm! Type '/exit' to exit. 2023-06-22 18:46:51,734 # This is RIOT! (Version: 2020.07-devel-15351-gc5f75c-cpu/atmega_common) 2023-06-22 18:46:51,734 # GPIO peripheral driver test 2023-06-22 18:46:51,734 # 2023-06-22 18:46:51,735 # In this test, pins are specified by integer port and pin numbers. 2023-06-22 18:46:51,735 # So if your platform has a pin PA01, it will be port=0 and pin=1, 2023-06-22 18:46:51,736 # PC14 would be port=2 and pin=14 etc. 2023-06-22 18:46:51,736 # 2023-06-22 18:46:51,736 # NOTE: make sure the values you use exist on your platform! The 2023-06-22 18:46:51,738 # behavior for not existing ports/pins is not defined! init_out 1 5 2023-06-22 18:47:50,380 # init_out 1 5 toggle 1 5 2023-06-22 18:48:09,425 # toggle 1 5 > toggle 1 5 2023-06-22 18:48:12,477 # toggle 1 5 > 2023-06-22 18:48:15,013 # Exiting Pyterm ``` #### tests/periph/i2c ``` tests/periph/i2c$ BOARD=atmega1284p make -j64 clean all | grep '^ ' && BOARD=atmega1284p AVRDUDE_PROGRAMMER='usbasp -F' make flash 2>&1 | grep -- 'of flash' && BOARD=atmega1284p PORT=/dev/ttyACM0 make term text data bss dec hex filename 18634 1288 1215 21137 5291 /home/hugues/github/cpu_atmega_common/RIOT/tests/periph/i2c/bin/atmega1284p/tests_i2c.elf avrdude: 19922 bytes of flash written avrdude: 19922 bytes of flash verified /home/hugues/github/cpu_atmega_common/RIOT/dist/tools/pyterm/pyterm -p "/dev/ttyACM0" -b "9600" Twisted not available, please install it if you want to use pyterm's JSON capabilities 2023-06-22 18:50:37,434 # Connect to serial port /dev/ttyACM0 Welcome to pyterm! Type '/exit' to exit. 2023-06-22 18:50:38,437 # 2023-06-22 18:50:38,438 # main(): This is RIOT! (Version: 2020.07-devel-15351-gc5f75c-cpu/atmega_common) 2023-06-22 18:50:38,438 # Start: Test for the low-level I2C driver > i2c_scan 0 2023-06-22 18:51:37,661 # i2c_scan 0 2023-06-22 18:51:37,687 # Scanning I2C device 0... 2023-06-22 18:51:37,765 # addr not ack'ed = "-", addr ack'ed = "X", addr reserved = "R", error = "E" 2023-06-22 18:51:37,804 # 0 1 2 3 4 5 6 7 8 9 a b c d e f 2023-06-22 18:51:37,842 # 0x00 R R R R R R R R R R R R R R - - 2023-06-22 18:51:37,881 # 0x10 - - - - - - - - - - - - - - - - 2023-06-22 18:51:37,919 # 0x20 - - - - - - - - - - - - - - - - 2023-06-22 18:51:37,958 # 0x30 - - - - - - - - - - - - - - - - 2023-06-22 18:51:37,996 # 0x40 - - - - - - - - - - - - - - - - 2023-06-22 18:51:38,035 # 0x50 - - - - - - - - - - - - - - - - 2023-06-22 18:51:38,073 # 0x60 - - - - - - - - - - - - - - - - 2023-06-22 18:51:38,112 # 0x70 - - - - - - - - R R R R R R R R > 2023-06-22 18:52:54,462 # Exiting Pyterm ``` #### tests/periph/pwm ``` tests/periph/pwm$ BOARD=atmega1284p make -j64 clean all | grep '^ ' && BOARD=atmega1284p AVRDUDE_PROGRAMMER='usbasp -F' make flash 2>&1 | grep -- 'of flash' && BOARD=atmega1284p PORT=/dev/ttyACM0 make term text data bss dec hex filename 15382 896 1093 17371 43db /home/hugues/github/cpu_atmega_common/RIOT/tests/periph/pwm/bin/atmega1284p/tests_pwm.elf avrdude: 16278 bytes of flash written avrdude: 16278 bytes of flash verified /home/hugues/github/cpu_atmega_common/RIOT/dist/tools/pyterm/pyterm -p "/dev/ttyACM0" -b "9600" Twisted not available, please install it if you want to use pyterm's JSON capabilities 2023-06-22 18:54:32,308 # Connect to serial port /dev/ttyACM0 Welcome to pyterm! Type '/exit' to exit. 2023-06-22 18:54:33,310 # 2023-06-22 18:54:33,312 # main(): This is RIOT! (Version: 2020.07-devel-15351-gc5f75c-cpu/atmega_common) 2023-06-22 18:54:33,312 # PWM peripheral driver test 2023-06-22 18:54:33,313 # > osci 2023-06-22 18:54:39,105 # osci 2023-06-22 18:54:39,106 # 2023-06-22 18:54:39,121 # RIOT PWM test 2023-06-22 18:54:39,177 # Connect an LED or scope to PWM pins to see something. 2023-06-22 18:54:39,178 # 2023-06-22 18:54:39,216 # Available PWM device between 0 and 1 2023-06-22 18:54:39,244 # Initialized PWM_0 @ 488Hz. 2023-06-22 18:54:39,273 # Initialized PWM_1 @ 976Hz. 2023-06-22 18:54:39,274 # 2023-06-22 18:54:39,313 # Letting the PWM pins oscillate now... 2023-06-22 18:54:45,655 # Exiting Pyterm ``` #### tests/periph/spi ``` tests/periph/spi$ BOARD=atmega1284p make -j64 clean all | grep '^ ' && BOARD=atmega1284p AVRDUDE_PROGRAMMER='usbasp -F' make flash 2>&1 | grep -- 'of flash' && BOARD=atmega1284p PORT=/dev/ttyACM0 make term text data bss dec hex filename 19240 1402 2317 22959 59af /home/hugues/github/cpu_atmega_common/RIOT/tests/periph/spi/bin/atmega1284p/tests_spi.elf avrdude: 20642 bytes of flash written avrdude: 20642 bytes of flash verified /home/hugues/github/cpu_atmega_common/RIOT/dist/tools/pyterm/pyterm -p "/dev/ttyACM0" -b "9600" Twisted not available, please install it if you want to use pyterm's JSON capabilities 2023-06-22 18:58:12,394 # Connect to serial port /dev/ttyACM0 Welcome to pyterm! Type '/exit' to exit. 2023-06-22 18:58:13,396 # 2023-06-22 18:58:13,398 # main(): This is RIOT! (Version: 2020.07-devel-15351-gc5f75c-cpu/atmega_common) 2023-06-22 18:58:13,398 # Manual SPI peripheral driver test (see README.md) 2023-06-22 18:58:13,399 # There are 1 SPI devices configured for your platform. init 0 0 4 2023-06-22 18:58:32,086 # init 0 0 4 2023-06-22 18:58:32,161 # Trying to initialize SPI_DEV(0): mode: 0, clk: 4, cs_port: 0, cs_pin: 0 2023-06-22 18:58:32,270 # (if below the program crashes with a failed assertion, then it means the configuration is not supported) 2023-06-22 18:58:32,280 # Success. bench 2023-06-22 18:58:41,590 # bench 2023-06-22 18:58:41,644 # ### Running some benchmarks, all values in [us] ### 2023-06-22 18:58:41,682 # ### Test Transfer time user time 2023-06-22 18:58:41,683 # 2023-06-22 18:58:41,755 # 1 - write 1000 times 1 byte: 28456 28640 2023-06-22 18:58:41,827 # 2 - write 1000 times 2 byte: 28184 28352 2023-06-22 18:58:42,454 # 3 - write 1000 times 100 byte: 579528 579704 2023-06-22 18:58:42,563 # 4 - write 1000 times 1 byte to register: 54080 54256 2023-06-22 18:58:42,674 # 5 - write 1000 times 2 byte to register: 56720 56888 2023-06-22 18:58:43,340 # 6 - write 1000 times 100 byte to register: 608152 608320 2023-06-22 18:58:43,412 # 7 - read 1000 times 2 byte: 28304 28480 2023-06-22 18:58:44,025 # 8 - read 1000 times 100 byte: 567408 567576 2023-06-22 18:58:44,138 # 9 - read 1000 times 2 byte from register: 56840 57016 2023-06-22 18:58:44,793 # 10 - read 1000 times 100 byte from register: 596024 596200 2023-06-22 18:58:44,868 # 11 - transfer 1000 times 2 byte: 28336 28512 2023-06-22 18:58:45,510 # 12 - transfer 1000 times 100 byte: 592128 592304 2023-06-22 18:58:45,625 # 13 - transfer 1000 times 2 byte to register: 56960 57136 2023-06-22 18:58:46,306 # 14 - transfer 1000 times 100 byte to register:620744 620920 2023-06-22 18:58:46,373 # 15 - acquire/release 1000 times: 20960 21136 2023-06-22 18:58:46,879 # -- - SUM: 3922824 3925440 2023-06-22 18:58:46,880 # 2023-06-22 18:58:46,907 # ### All runs complete ### > 2023-06-22 18:58:54,706 # Exiting Pyterm ``` I always wonder how fast it really goes: - #16727 - #18374 #### tests/periph/timer ``` tests/periph/timer$ BOARD=atmega1284p make -j64 clean all | grep '^ ' && BOARD=atmega1284p AVRDUDE_PROGRAMMER='usbasp -F' make flash 2>&1 | grep -- 'of flash' && BOARD=atmega1284p PORT=/dev/ttyACM0 make term text data bss dec hex filename 8968 274 1032 10274 2822 /home/hugues/github/cpu_atmega_common/RIOT/tests/periph/timer/bin/atmega1284p/tests_timer.elf avrdude: 9242 bytes of flash written avrdude: 9242 bytes of flash verified /home/hugues/github/cpu_atmega_common/RIOT/dist/tools/pyterm/pyterm -p "/dev/ttyACM0" -b "9600" Twisted not available, please install it if you want to use pyterm's JSON capabilities 2023-06-22 19:00:15,136 # Connect to serial port /dev/ttyACM0 Welcome to pyterm! Type '/exit' to exit. 2023-06-22 19:00:16,138 # 2023-06-22 19:00:16,139 # Help: Press s to start test, r to print it is ready s 2023-06-22 19:00:31,118 # START 2023-06-22 19:00:31,200 # main(): This is RIOT! (Version: 2020.07-devel-15351-gc5f75c-cpu/atmega_common) 2023-06-22 19:00:31,201 # 2023-06-22 19:00:31,230 # Test for peripheral TIMERs 2023-06-22 19:00:31,231 # 2023-06-22 19:00:31,251 # Available timers: 2 2023-06-22 19:00:31,252 # 2023-06-22 19:00:31,270 # Testing TIMER_0: 2023-06-22 19:00:31,306 # TIMER_0: initialization successful 2023-06-22 19:00:31,324 # TIMER_0: stopped 2023-06-22 19:00:31,356 # TIMER_0: set channel 0 to 5000 2023-06-22 19:00:31,390 # TIMER_0: set channel 1 to 10000 2023-06-22 19:00:31,408 # TIMER_0: starting 2023-06-22 19:00:31,482 # TIMER_0: channel 0 fired at SW count 1247 - init: 1247 2023-06-22 19:00:31,547 # TIMER_0: channel 1 fired at SW count 2488 - diff: 1241 2023-06-22 19:00:31,551 # 2023-06-22 19:00:31,568 # Testing TIMER_1: 2023-06-22 19:00:31,605 # TIMER_1: initialization successful 2023-06-22 19:00:31,622 # TIMER_1: stopped 2023-06-22 19:00:31,655 # TIMER_1: set channel 0 to 5000 2023-06-22 19:00:31,688 # TIMER_1: set channel 1 to 10000 2023-06-22 19:00:31,707 # TIMER_1: starting 2023-06-22 19:00:31,780 # TIMER_1: channel 0 fired at SW count 1247 - init: 1247 2023-06-22 19:00:31,846 # TIMER_1: channel 1 fired at SW count 2488 - diff: 1241 2023-06-22 19:00:31,849 # 2023-06-22 19:00:31,864 # TEST SUCCEEDED 2023-06-22 19:00:31,939 # { "threads": [{ "name": "idle", "stack_size": 128, "stack_used": 86 }]} 2023-06-22 19:00:32,015 # { "threads": [{ "name": "main", "stack_size": 640, "stack_used": 120 }]} 2023-06-22 19:00:34,259 # Exiting Pyterm ``` #### tests/periph/uart ``` tests/periph/uart$ BOARD=atmega1284p make -j64 clean all | grep '^ ' && BOARD=atmega1284p AVRDUDE_PROGRAMMER='usbasp -F' make flash 2>&1 | grep -- 'of flash' && BOARD=atmega1284p PORT=/dev/ttyACM0 make term text data bss dec hex filename 15918 1044 2000 18962 4a12 /home/hugues/github/cpu_atmega_common/RIOT/tests/periph/uart/bin/atmega1284p/tests_uart.elf avrdude: 16962 bytes of flash written avrdude: 16962 bytes of flash verified /home/hugues/github/cpu_atmega_common/RIOT/dist/tools/pyterm/pyterm -p "/dev/ttyACM0" -b "9600" Twisted not available, please install it if you want to use pyterm's JSON capabilities 2023-06-22 19:01:25,894 # Connect to serial port /dev/ttyACM0 Welcome to pyterm! Type '/exit' to exit. 2023-06-22 19:01:26,896 # 2023-06-22 19:01:26,898 # main(): This is RIOT! (Version: 2020.07-devel-15351-gc5f75c-cpu/atmega_common) 2023-06-22 19:01:26,898 # 2023-06-22 19:01:26,899 # Manual UART driver test application 2023-06-22 19:01:26,899 # =================================== 2023-06-22 19:01:26,900 # This application is intended for testing additional UART 2023-06-22 19:01:26,900 # interfaces, that might be defined for a board. The 'primary' UART 2023-06-22 19:01:26,901 # interface is tested implicitly, as it is running the shell... 2023-06-22 19:01:26,901 # 2023-06-22 19:01:26,902 # When receiving data on one of the additional UART interfaces, this 2023-06-22 19:01:26,902 # data will be outputted via STDIO. So the easiest way to test an 2023-06-22 19:01:26,903 # UART interface, is to simply connect the RX with the TX pin. Then 2023-06-22 19:01:26,904 # you can send data on that interface and you should see the data 2023-06-22 19:01:26,904 # being printed to STDOUT 2023-06-22 19:01:26,904 # 2023-06-22 19:01:26,904 # NOTE: all strings need to be '\n' terminated! 2023-06-22 19:01:26,904 # 2023-06-22 19:01:26,909 # UARD_DEV(0): test uart_poweron() and uart_poweroff() -> [OK] 2023-06-22 19:01:26,910 # 2023-06-22 19:01:26,921 # UART INFO: 2023-06-22 19:01:26,958 # Available devices: 2 2023-06-22 19:01:27,004 # UART used for STDIO (the shell): UART_DEV(0) 2023-06-22 19:01:27,006 # init 1 9600 2023-06-22 19:01:50,464 # init 1 9600 send 1 ping 2023-06-22 19:04:12,912 # send 1 ping 2023-06-22 19:04:12,934 # UART_DEV(1) TX: ping > 2023-06-22 19:04:12,973 # Success: UART_DEV(1) RX: [ping]\n 2023-06-22 19:04:23,894 # Exiting Pyterm ```` ### Issues/PRs references Depends on PR: - #19751 Co-authored-by: Hugues Larrive <hlarrive@pm.me>
This commit is contained in:
commit
9d596734a1
@ -3,6 +3,7 @@
|
||||
* 2017 RWTH Aachen, Josua Arndt
|
||||
* 2018 Matthew Blue
|
||||
* 2021 Gerson Fernando Budke
|
||||
* 2023 Hugues Larrive
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -22,6 +23,7 @@
|
||||
* @author Matthew Blue <matthew.blue.neuro@gmail.com>
|
||||
* @author Francisco Acosta <francisco.acosta@inria.fr>
|
||||
* @author Gerson Fernando Budke <nandojve@gmail.com>
|
||||
* @author Hugues Larrive <hugues.larrive@pm.me>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@ -58,7 +60,7 @@ void avr8_reset_cause(void)
|
||||
DEBUG("Watchdog reset!\n");
|
||||
}
|
||||
}
|
||||
#if !defined (CPU_ATMEGA328P)
|
||||
#if defined(JTRF)
|
||||
if (mcusr_mirror & (1 << JTRF)) {
|
||||
DEBUG("JTAG reset!\n");
|
||||
}
|
||||
@ -67,7 +69,9 @@ void avr8_reset_cause(void)
|
||||
|
||||
void __attribute__((weak)) avr8_clk_init(void)
|
||||
{
|
||||
#if defined(CLKPR)
|
||||
atmega_set_prescaler(CPU_ATMEGA_CLK_SCALE_INIT);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This is a vector which is aliased to __vector_default,
|
||||
@ -85,9 +89,12 @@ ISR(BADISR_vect)
|
||||
{
|
||||
avr8_reset_cause();
|
||||
|
||||
#if defined (CPU_ATMEGA256RFR2)
|
||||
printf("IRQ_STATUS %#02x\nIRQ_STATUS1 %#02x\n",
|
||||
(unsigned int)IRQ_STATUS, (unsigned int)IRQ_STATUS1);
|
||||
#if defined(TRX_CTRL_0) /* megaRF */
|
||||
printf("IRQ_STATUS %#02x\n", (unsigned int)IRQ_STATUS);
|
||||
|
||||
#if defined(IRQ_STATUS1)
|
||||
printf("IRQ_STATUS1 %#02x\n", (unsigned int)IRQ_STATUS1);
|
||||
#endif
|
||||
|
||||
printf("SCIRQS %#02x\nBATMON %#02x\n", (unsigned int)SCIRQS, (unsigned int)BATMON);
|
||||
|
||||
@ -101,7 +108,7 @@ ISR(BADISR_vect)
|
||||
core_panic(PANIC_GENERAL_ERROR, "BADISR");
|
||||
}
|
||||
|
||||
#if defined(CPU_ATMEGA128RFA1) || defined (CPU_ATMEGA256RFR2)
|
||||
#if defined(BAT_LOW_vect)
|
||||
ISR(BAT_LOW_vect, ISR_BLOCK)
|
||||
{
|
||||
avr8_enter_isr();
|
||||
|
@ -2,6 +2,7 @@
|
||||
* Copyright (C) 2016 Freie Universität Berlin
|
||||
* 2016 INRIA
|
||||
* 2017 Thomas Perrot <thomas.perrot@tupi.fr>
|
||||
* 2023 Hugues Larrive
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -18,6 +19,7 @@
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
* @author Francisco Acosta <francisco.acosta@inria.fr>
|
||||
* @author Thomas Perrot <thomas.perrot@tupi.fr>
|
||||
* @author Hugues Larrive <hugues.larrive@pm.me>
|
||||
*
|
||||
*/
|
||||
|
||||
@ -42,6 +44,7 @@ extern "C" {
|
||||
/**
|
||||
* @brief Timer register map
|
||||
*/
|
||||
#ifdef TCCR1C
|
||||
typedef struct {
|
||||
REG8 CRA; /**< control A */
|
||||
REG8 CRB; /**< control B */
|
||||
@ -51,31 +54,57 @@ typedef struct {
|
||||
REG16 ICR; /**< input capture */
|
||||
REG16 OCR[3]; /**< output compare */
|
||||
} mega_timer_t;
|
||||
#else /* atmega8 */
|
||||
typedef struct {
|
||||
REG16 ICR; /**< input capture */
|
||||
REG16 OCR[2]; /**< output compare */
|
||||
REG16 CNT; /**< counter */
|
||||
REG8 CRB; /**< control B */
|
||||
REG8 CRA; /**< control A */
|
||||
} mega_timer_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief 8-bit timer register map
|
||||
*/
|
||||
typedef struct {
|
||||
#if ((defined(TCCR0A) && defined(TCCR0B)) || (defined(TCCR2A) && defined(TCCR2B)))
|
||||
REG8 CRA; /**< control A */
|
||||
REG8 CRB; /**< control B */
|
||||
REG8 CNT; /**< counter */
|
||||
REG8 OCR[2]; /**< output compare */
|
||||
#elif defined(TCCR2)
|
||||
REG8 OCR; /**< output compare */
|
||||
REG8 CNT; /**< counter */
|
||||
REG8 CR; /**< control */
|
||||
#endif
|
||||
} mini_timer_t;
|
||||
|
||||
/**
|
||||
* @brief UART register map
|
||||
*/
|
||||
typedef struct {
|
||||
#if defined(UCSR0A) || defined(UCSR1A)
|
||||
REG8 CSRA; /**< control and status register A */
|
||||
REG8 CSRB; /**< control and status register B */
|
||||
REG8 CSRC; /**< control and status register C */
|
||||
#ifdef CPU_ATMEGA32U4
|
||||
#ifdef UCSR1D /* 32u4 */
|
||||
REG8 CSRD; /**< control and status register D */
|
||||
#else
|
||||
REG8 reserved; /**< reserved */
|
||||
#endif
|
||||
REG16 BRR; /**< baud rate register */
|
||||
REG8 DR; /**< data register */
|
||||
#elif defined(UCSRA) /* atmega8 */
|
||||
REG8 BRRL; /**< baud rate register low byte */
|
||||
REG8 CSRB; /**< control and status register B */
|
||||
REG8 CSRA; /**< control and status register A */
|
||||
REG8 DR; /**< data register */
|
||||
REG8 padding[19]; /**< 3 SPI + 3 PORTD + 3 PORTC + 3 PORTB
|
||||
* + 3 reserved + 4 EEPROM = 19 */
|
||||
REG8 CSRC; /**< control and status register C shared
|
||||
* with baud rate register high byte */
|
||||
#endif
|
||||
} mega_uart_t;
|
||||
|
||||
/**
|
||||
@ -87,14 +116,20 @@ typedef struct {
|
||||
#define MINI_TIMER0_DIV TIMER_DIV1_8_64_128_1024
|
||||
#endif
|
||||
|
||||
#if defined(TCCR1A)
|
||||
#if defined(TCCR1C)
|
||||
#define MEGA_TIMER1_BASE (uint16_t *)(&TCCR1A)
|
||||
#define MEGA_TIMER1 ((mega_timer_t *)MEGA_TIMER1_BASE)
|
||||
#elif defined(TCCR1A) /* atmega8 */
|
||||
#define MEGA_TIMER1_BASE (uint16_t *)(&ICR1L)
|
||||
#define MEGA_TIMER1 ((mega_timer_t *)MEGA_TIMER1_BASE)
|
||||
#endif
|
||||
|
||||
#if defined(TCCR2A)
|
||||
#define MINI_TIMER2 ((mini_timer_t *)(uint16_t *)(&TCCR2A))
|
||||
#define MINI_TIMER2_DIV TIMER_DIV1_8_32_64_128_256_1024
|
||||
#elif defined(TCCR2) /* atmega8 */
|
||||
#define MINI_TIMER2 ((mini_timer_t *)(uint16_t *)(&OCR2))
|
||||
#define MINI_TIMER2_DIV TIMER_DIV1_8_32_64_128_256_1024
|
||||
#endif
|
||||
|
||||
#if defined(TCCR3A)
|
||||
@ -117,6 +152,11 @@ typedef struct {
|
||||
* @brief Peripheral register definitions and instances
|
||||
* @{
|
||||
*/
|
||||
#if defined(UCSRA)
|
||||
#define MEGA_UART_BASE ((uint16_t *)(&UBRRL))
|
||||
#define MEGA_UART ((mega_uart_t *)MEGA_UART_BASE)
|
||||
#endif
|
||||
|
||||
#if defined(UCSR0A)
|
||||
#define MEGA_UART0_BASE ((uint16_t *)(&UCSR0A))
|
||||
#define MEGA_UART0 ((mega_uart_t *)MEGA_UART0_BASE)
|
||||
|
@ -63,11 +63,15 @@ enum {
|
||||
static inline void atmega_set_prescaler(uint8_t clk_scale)
|
||||
{
|
||||
/* Enable clock change */
|
||||
#ifdef CLKPR
|
||||
/* Must be assignment to set all other bits to zero, see datasheet */
|
||||
CLKPR = (1 << CLKPCE);
|
||||
|
||||
/* Write clock within 4 cycles */
|
||||
CLKPR = clk_scale;
|
||||
#else
|
||||
(void) clk_scale;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -2,6 +2,7 @@
|
||||
* Copyright (C) 2015 HAW Hamburg
|
||||
* 2016 Freie Universität Berlin
|
||||
* 2016 INRIA
|
||||
* 2023 Hugues Larrive
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -18,6 +19,7 @@
|
||||
* @author René Herthel <rene-herthel@outlook.de>
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
* @author Francisco Acosta <francisco.acosta@inria.fr>
|
||||
* @author Hugues Larrive <hugues.larrive@pm.me>
|
||||
*/
|
||||
|
||||
#ifndef PERIPH_CPU_COMMON_H
|
||||
@ -61,7 +63,27 @@ typedef uint8_t gpio_t;
|
||||
*
|
||||
* Must be identical to the address of `PINA` provided by avr/io.h
|
||||
*/
|
||||
#define ATMEGA_GPIO_BASE_A (0x20)
|
||||
#if (defined(OCF1A) && defined(OCF1B) && (OCF1A > OCF1B)) \
|
||||
|| (defined(PUD) && (PUD != 4)) || (defined(INT0) && (INT0 == 6))
|
||||
/* match with 65 devices against 61 for (PORTB == _SFR_IO8(0x18)) which
|
||||
* did not work here anyway */
|
||||
#define GPIO_PORT_DESCENDENT
|
||||
#endif
|
||||
|
||||
#ifdef GPIO_PORT_DESCENDENT
|
||||
#ifdef _AVR_ATTINY1634_H_INCLUDED
|
||||
/* the only one that requires particular treatment! */
|
||||
#define ATMEGA_GPIO_BASE_A (0x2F)
|
||||
#else
|
||||
/* all other port descendent, including :
|
||||
- _AVR_IO8534_ (only have port A but with 0x1B address) ;
|
||||
- _AVR_IOAT94K_H_ (only have ports D and E) ;
|
||||
- _AVR_IOTN28_H_ (only have ports A and D). */
|
||||
#define ATMEGA_GPIO_BASE_A (0x39)
|
||||
#endif /* _AVR_ATTINY1634_H_INCLUDED */
|
||||
#else /* !GPIO_PORT_DESCENDENT */
|
||||
#define ATMEGA_GPIO_BASE_A (0x20)
|
||||
#endif /* GPIO_PORT_DESCENDENT */
|
||||
/**
|
||||
* @brief Base of the GPIO port G register as memory address
|
||||
*
|
||||
@ -137,7 +159,11 @@ typedef struct {
|
||||
static inline atmega_gpio_port_t *atmega_gpio_port(uint8_t port_num)
|
||||
{
|
||||
static const uintptr_t base_addr = (uintptr_t)ATMEGA_GPIO_BASE_A;
|
||||
#ifdef GPIO_PORT_DESCENDENT
|
||||
uintptr_t res = base_addr - port_num * sizeof(atmega_gpio_port_t);
|
||||
#else
|
||||
uintptr_t res = base_addr + port_num * sizeof(atmega_gpio_port_t);
|
||||
#endif
|
||||
/* GPIO ports up to (including) G are mapped in the I/O address space,
|
||||
* port H and higher (if present) are mapped in a different contiguous
|
||||
* region afterwards (e.g. 0x100 for ATmega2560). */
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Laurent Navet <laurent.navet@gmail.com>
|
||||
* 2017 HAW Hamburg, Dimitri Nahm
|
||||
* 2023 Hugues Larrive
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
@ -17,6 +18,7 @@
|
||||
* @author Laurent Navet <laurent.navet@gmail.com>
|
||||
* @author Dimitri Nahm <dimitri.nahm@haw-hamburg.de>
|
||||
* @author Sebastian Meiling <s@mlng.net>
|
||||
* @author Hugues Larrive <hugues.larrive@pm.me>
|
||||
* @}
|
||||
*/
|
||||
|
||||
@ -52,35 +54,53 @@ int adc_init(adc_t line)
|
||||
|
||||
_prep();
|
||||
|
||||
#if defined(DIDR0)
|
||||
/* Disable corresponding Digital input */
|
||||
if (line < 8) {
|
||||
DIDR0 |= (1 << line);
|
||||
}
|
||||
#if defined(CPU_ATMEGA2560)
|
||||
#if defined(DIDR2)
|
||||
else {
|
||||
DIDR2 |= (1 << (line - 8));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Set ADC-pin as input */
|
||||
#if defined(CPU_ATMEGA328P)
|
||||
#if !defined(PORTA) && defined(PC0)
|
||||
/* 328p and 8 do not have PORTA, on 32u4 pins are named differently
|
||||
* and it only have PORTC6 and PORTC7 */
|
||||
DDRC &= ~(1 << line);
|
||||
PORTC &= ~(1 << line);
|
||||
#elif defined(CPU_ATMEGA1284P)
|
||||
#elif defined(PORTA) && !defined(DIDR2) /* 1284p do not have DIDR2 */
|
||||
DDRA &= ~(1 << line);
|
||||
PORTA &= ~(1 << line);
|
||||
#elif defined(CPU_ATMEGA2560) || defined(CPU_ATMEGA1281)
|
||||
#elif defined(PORTF) /* 2560 and 1281 */
|
||||
if (line < 8) {
|
||||
DDRF &= ~(1 << line);
|
||||
PORTF &= ~(1 << line);
|
||||
}
|
||||
#if defined(CPU_ATMEGA2560)
|
||||
#if defined(PORTK) /* 2560 */
|
||||
else {
|
||||
DDRK &= ~(1 << (line-8));
|
||||
PORTK &= ~(1 << (line-8));
|
||||
DDRK &= ~(1 << (line - 8));
|
||||
PORTK &= ~(1 << (line - 8));
|
||||
}
|
||||
#endif /* CPU_ATMEGA2560 */
|
||||
#endif /* CPU_ATMEGA328P */
|
||||
#elif defined(PORTF0) && !defined(PORTF2) && !defined(PORTF3)
|
||||
/* 32u4 do not have PORTF2 and PORTF3 */
|
||||
else if (line == 8) {
|
||||
DDRD &= ~(1 << PORTD4);
|
||||
PORTD &= ~(1 << PORTD4);
|
||||
}
|
||||
else if (line < 11) {
|
||||
DDRD &= ~(1 << (line - 3));
|
||||
PORTD &= ~(1 << (line - 3));
|
||||
}
|
||||
else {
|
||||
DDRB &= ~(1 << (line - 7));
|
||||
PORTB &= ~(1 << (line - 7));
|
||||
}
|
||||
#endif /* PORTK */
|
||||
#endif /* PORTF */
|
||||
|
||||
/* set clock prescaler to get the maximal possible ADC clock value */
|
||||
for (uint32_t clk_div = 1; clk_div < 8; ++clk_div) {
|
||||
@ -110,10 +130,12 @@ int32_t adc_sample(adc_t line, adc_res_t res)
|
||||
_prep();
|
||||
|
||||
/* set conversion channel */
|
||||
#if defined(CPU_ATMEGA328P) || defined(CPU_ATMEGA1281) || defined(CPU_ATMEGA1284P) || defined(CPU_ATMEGA32U4)
|
||||
#if defined(ADMUX)
|
||||
#if !defined(MUX5)
|
||||
/* atmega8 ; 328p ; 1281 ; 1284p ; 32u4 */
|
||||
ADMUX &= 0xf0;
|
||||
ADMUX |= line;
|
||||
#elif defined(CPU_ATMEGA2560) || defined(CPU_ATMEGA128RFA1) || defined(CPU_ATMEGA256RFR2)
|
||||
#else /* 2560 ; 128rfa1 ; 256rfr2 */
|
||||
if (line < 8) {
|
||||
ADCSRB &= ~(1 << MUX5);
|
||||
ADMUX &= 0xf0;
|
||||
@ -124,6 +146,7 @@ int32_t adc_sample(adc_t line, adc_res_t res)
|
||||
ADMUX &= 0xf0;
|
||||
ADMUX |= (line-8);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Start a new conversion. By default, this conversion will
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2015 HAW Hamburg
|
||||
* 2016 INRIA
|
||||
|
||||
* 2023 Hugues Larrive
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -22,6 +22,7 @@
|
||||
* @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>
|
||||
* @author Hugues Larrive <hugues.larrive@pm.me>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@ -309,20 +310,30 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
|
||||
cli();
|
||||
|
||||
/* enable interrupt number int_num */
|
||||
#if defined(EIFR) && defined(EIMSK)
|
||||
EIFR |= (1 << int_num);
|
||||
EIMSK |= (1 << int_num);
|
||||
#elif defined(GIFR) && defined(GICR)
|
||||
GIFR |= (1 << (INTF0 + int_num));
|
||||
GICR |= (1 << (INT0 + int_num));
|
||||
#endif
|
||||
|
||||
/* apply flank to interrupt number int_num */
|
||||
#if defined(EICRB)
|
||||
#if defined(EICRB)
|
||||
if (int_num >= 4) {
|
||||
EICRB &= ~(0x3 << ((int_num % 4) * 2));
|
||||
EICRB |= (flank << ((int_num % 4) * 2));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
#if defined(EICRA)
|
||||
EICRA &= ~(0x3 << (int_num * 2));
|
||||
EICRA |= (flank << (int_num * 2));
|
||||
#elif defined(MCUCR)
|
||||
MCUCR &= ~(0x3 << (int_num * 2));
|
||||
MCUCR |= (flank << (int_num * 2));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* set callback */
|
||||
@ -337,13 +348,22 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
|
||||
|
||||
void gpio_irq_enable(gpio_t pin)
|
||||
{
|
||||
#if defined(EIFR) && defined(EIMSK)
|
||||
EIFR |= (1 << _int_num(pin));
|
||||
EIMSK |= (1 << _int_num(pin));
|
||||
#elif defined(GIFR) && defined(GICR)
|
||||
GIFR |= (1 << (INTF0 + _int_num(pin)));
|
||||
GICR |= (1 << (INT0 + _int_num(pin)));
|
||||
#endif
|
||||
}
|
||||
|
||||
void gpio_irq_disable(gpio_t pin)
|
||||
{
|
||||
#if defined(EIMSK)
|
||||
EIMSK &= ~(1 << _int_num(pin));
|
||||
#elif defined(GICR)
|
||||
GICR &= ~(1 << (INT0 + _int_num(pin)));
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void irq_handler(uint8_t int_num)
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Hamburg University of Applied Sciences, Dimitri Nahm
|
||||
* 2023 Hugues Larrive
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -18,6 +19,7 @@
|
||||
*
|
||||
* @author Dimitri Nahm <dimitri.nahm@haw-hamburg.de>
|
||||
* @author Laurent Navet <laurent.navet@gmail.com>
|
||||
* @author Hugues Larrive <hugues.larrive@pm.me>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@ -238,7 +240,9 @@ static void i2c_poweron(i2c_t dev)
|
||||
{
|
||||
assert(dev < I2C_NUMOF);
|
||||
(void) dev;
|
||||
#ifdef PRTWI
|
||||
power_twi_enable();
|
||||
#endif
|
||||
}
|
||||
|
||||
static int _start(uint8_t address, uint8_t rw_flag)
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Víctor Ariño
|
||||
* 2023 Hugues Larrive
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -15,6 +16,7 @@
|
||||
* @brief Low-level PWM driver implementation
|
||||
*
|
||||
* @author Víctor Ariño <victor@lebrush.org>
|
||||
* @author Hugues Larrive <hugues.larrive@pm.me>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@ -35,8 +37,12 @@
|
||||
#define COMA1 7
|
||||
|
||||
static struct {
|
||||
#if (defined(TCCR0A) && defined(TCCR0B)) || (defined(TCCR2A) && defined(TCCR2B))
|
||||
uint8_t CRA;
|
||||
uint8_t CRB;
|
||||
#elif defined(TCCR2)
|
||||
uint8_t CR;
|
||||
#endif
|
||||
uint8_t res;
|
||||
} state[PWM_NUMOF];
|
||||
|
||||
@ -60,6 +66,7 @@ static inline uint8_t get_prescaler(pwm_t dev, uint32_t *scale)
|
||||
return pre;
|
||||
}
|
||||
|
||||
#if (defined(TCCR0A) && defined(TCCR0B)) || (defined(TCCR2A) && defined(TCCR2B))
|
||||
static inline void compute_cra_and_crb(pwm_t dev, uint8_t pre)
|
||||
{
|
||||
uint8_t cra = (1 << WGM1) | (1 << WGM0);
|
||||
@ -79,16 +86,25 @@ static inline void compute_cra_and_crb(pwm_t dev, uint8_t pre)
|
||||
state[dev].CRA = cra;
|
||||
state[dev].CRB = crb;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void apply_config(pwm_t dev)
|
||||
{
|
||||
#if (defined(TCCR0A) && defined(TCCR0B)) || (defined(TCCR2A) && defined(TCCR2B))
|
||||
pwm_conf[dev].dev->CRA = state[dev].CRA;
|
||||
pwm_conf[dev].dev->CRB = state[dev].CRB;
|
||||
#elif defined(TCCR2)
|
||||
pwm_conf[dev].dev->CR = state[dev].CR;
|
||||
#endif
|
||||
|
||||
if (pwm_conf[dev].pin_ch[0] == GPIO_UNDEF) {
|
||||
/* If channel 0 is not used, variable resolutions can be used for
|
||||
* channel 1 */
|
||||
#if (defined(OCR0A) && defined(OCR0B)) || (defined(OCR2A) && defined(OCR2B))
|
||||
pwm_conf[dev].dev->OCR[0] = state[dev].res;
|
||||
#elif defined(OCR2)
|
||||
pwm_conf[dev].dev->OCR = state[dev].res;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,11 +117,17 @@ uint32_t pwm_init(pwm_t dev, pwm_mode_t mode, uint32_t freq, uint16_t res)
|
||||
assert(!(res != 256 && pwm_conf[dev].pin_ch[0] != GPIO_UNDEF));
|
||||
|
||||
/* disable PWM */
|
||||
#if (defined(TCCR0A) && defined(TCCR0B)) || (defined(TCCR2A) && defined(TCCR2B))
|
||||
pwm_conf[dev].dev->CRA = 0x00;
|
||||
pwm_conf[dev].dev->CRB = 0x00;
|
||||
pwm_conf[dev].dev->OCR[0] = 0;
|
||||
pwm_conf[dev].dev->OCR[1] = 0;
|
||||
#elif defined(TCCR2)
|
||||
pwm_conf[dev].dev->CR = 0x00;
|
||||
pwm_conf[dev].dev->OCR = 0;
|
||||
#endif
|
||||
|
||||
#if defined(PRT2) || defined(PRTIM2) || defined(PRT0) || defined(PRTIM0)
|
||||
/* disable power reduction */
|
||||
if (dev) {
|
||||
power_timer2_enable();
|
||||
@ -113,6 +135,7 @@ uint32_t pwm_init(pwm_t dev, pwm_mode_t mode, uint32_t freq, uint16_t res)
|
||||
else {
|
||||
power_timer0_enable();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* find out prescaler */
|
||||
uint32_t scale = (CLOCK_CORECLOCK / (freq * (uint32_t)res));
|
||||
@ -121,7 +144,12 @@ uint32_t pwm_init(pwm_t dev, pwm_mode_t mode, uint32_t freq, uint16_t res)
|
||||
|
||||
/* Compute configuration and store it in the state. (The state is needed
|
||||
* for later calls to pwm_poweron().)*/
|
||||
#if (defined(TCCR0A) && defined(TCCR0B)) || (defined(TCCR2A) && defined(TCCR2B))
|
||||
compute_cra_and_crb(dev, pre);
|
||||
#elif defined(TCCR2)
|
||||
uint8_t cr = (1 << WGM21) | (1 << WGM20) | (1 << COM21) | pre;
|
||||
state[dev].CR = cr;
|
||||
#endif
|
||||
state[dev].res = res - 1;
|
||||
|
||||
/* Apply configuration stored in state */
|
||||
@ -155,18 +183,30 @@ uint8_t pwm_channels(pwm_t dev)
|
||||
|
||||
void pwm_set(pwm_t dev, uint8_t ch, uint16_t value)
|
||||
{
|
||||
#ifdef OCR2
|
||||
(void)ch;
|
||||
#endif
|
||||
assert(dev < PWM_NUMOF && ch <= 1 && pwm_conf[dev].pin_ch[ch] != GPIO_UNDEF);
|
||||
if (value > state[dev].res) {
|
||||
#if (defined(OCR0A) && defined(OCR0B)) || (defined(OCR2A) && defined(OCR2B))
|
||||
pwm_conf[dev].dev->OCR[ch] = state[dev].res;
|
||||
#elif defined(OCR2)
|
||||
pwm_conf[dev].dev->OCR = state[dev].res;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#if (defined(OCR0A) && defined(OCR0B)) || (defined(OCR2A) && defined(OCR2B))
|
||||
pwm_conf[dev].dev->OCR[ch] = value;
|
||||
#elif defined(OCR2)
|
||||
pwm_conf[dev].dev->OCR = value;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void pwm_poweron(pwm_t dev)
|
||||
{
|
||||
assert(dev < PWM_NUMOF);
|
||||
#if defined(PRT2) || defined(PRTIM2) || defined(PRT0) || defined(PRTIM0)
|
||||
/* disable power reduction */
|
||||
if (dev) {
|
||||
power_timer2_enable();
|
||||
@ -174,6 +214,7 @@ void pwm_poweron(pwm_t dev)
|
||||
else {
|
||||
power_timer0_enable();
|
||||
}
|
||||
#endif
|
||||
|
||||
apply_config(dev);
|
||||
}
|
||||
@ -181,6 +222,7 @@ void pwm_poweron(pwm_t dev)
|
||||
void pwm_poweroff(pwm_t dev)
|
||||
{
|
||||
assert(dev < PWM_NUMOF);
|
||||
#if (defined(TCCR0A) && defined(TCCR0B)) || (defined(TCCR2A) && defined(TCCR2B))
|
||||
pwm_conf[dev].dev->CRA = 0x00;
|
||||
pwm_conf[dev].dev->CRB = 0x00;
|
||||
/* disable timers to lower power consumption */
|
||||
@ -190,6 +232,9 @@ void pwm_poweroff(pwm_t dev)
|
||||
else {
|
||||
power_timer0_disable();
|
||||
}
|
||||
#elif defined(TCCR2)
|
||||
pwm_conf[dev].dev->CR = 0x00;
|
||||
#endif
|
||||
|
||||
if (pwm_conf[dev].pin_ch[0] != GPIO_UNDEF) {
|
||||
gpio_clear(pwm_conf[dev].pin_ch[0]);
|
||||
|
@ -3,6 +3,7 @@
|
||||
* 2016 Freie Universität Berlin
|
||||
* 2017 Hamburg University of Applied Sciences
|
||||
* 2017 Thomas Perrot <thomas.perrot@tupi.fr>
|
||||
* 2023 Hugues Larrive
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -21,6 +22,7 @@
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
* @author Dimitri Nahm <dimitri.nahm@haw-hamburg.de>
|
||||
* @author Thomas Perrot <thomas.perrot@tupi.fr>
|
||||
* @author Hugues Larrive <hugues.larrive@pm.me>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@ -43,8 +45,10 @@ static mutex_t lock = MUTEX_INIT;
|
||||
void spi_init(spi_t bus)
|
||||
{
|
||||
assert(bus == 0);
|
||||
#ifdef PRSPI
|
||||
/* power off the SPI peripheral */
|
||||
power_spi_disable();
|
||||
#endif
|
||||
/* trigger the pin configuration */
|
||||
spi_init_pins(bus);
|
||||
}
|
||||
@ -53,13 +57,13 @@ void spi_init_pins(spi_t bus)
|
||||
{
|
||||
(void)bus;
|
||||
/* set SPI pins as output */
|
||||
#if defined (CPU_ATMEGA2560) || defined (CPU_ATMEGA1281)
|
||||
#if defined(CPU_ATMEGA2560) || defined(CPU_ATMEGA1281)
|
||||
DDRB |= ((1 << DDB2) | (1 << DDB1) | (1 << DDB0));
|
||||
#endif
|
||||
#if defined (CPU_ATMEGA328P)
|
||||
#if defined(CPU_ATMEGA328P) || defined(CPU_ATMEGA8)
|
||||
DDRB |= ((1 << DDB2) | (1 << DDB3) | (1 << DDB5));
|
||||
#endif
|
||||
#if defined (CPU_ATMEGA1284P)
|
||||
#if defined(CPU_ATMEGA1284P)
|
||||
DDRB |= ((1 << DDB4) | (1 << DDB5) | (1 << DDB7));
|
||||
#endif
|
||||
#if defined(CPU_ATMEGA128RFA1) || defined(CPU_ATMEGA256RFR2)
|
||||
@ -86,7 +90,9 @@ void spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk)
|
||||
|
||||
/* lock the bus and power on the SPI peripheral */
|
||||
mutex_lock(&lock);
|
||||
#ifdef PRSPI
|
||||
power_spi_enable();
|
||||
#endif
|
||||
|
||||
/* configure as master, with given mode and clock */
|
||||
SPSR = (clk >> S2X_SHIFT);
|
||||
@ -102,7 +108,9 @@ void spi_release(spi_t bus)
|
||||
(void)bus;
|
||||
/* power off and release the bus */
|
||||
SPCR &= ~(1 << SPE);
|
||||
#ifdef PRSPI
|
||||
power_spi_disable();
|
||||
#endif
|
||||
mutex_unlock(&lock);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin, Hinnerk van Bruinehsen
|
||||
* 2023 Hugues Larrive
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -16,6 +17,7 @@
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
* @author Hinnerk van Bruinehsen <h.v.bruinehsen@fu-berlin.de>
|
||||
* @author Hugues Larrive <hugues.larrive@pm.me>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@ -134,7 +136,9 @@ int timer_init(tim_t tim, uint32_t freq, timer_cb_t cb, void *arg)
|
||||
/* stop and reset timer */
|
||||
ctx[tim].dev->CRA = 0;
|
||||
ctx[tim].dev->CRB = 0;
|
||||
#ifdef TCCR1C
|
||||
ctx[tim].dev->CRC = 0;
|
||||
#endif
|
||||
ctx[tim].dev->CNT = 0;
|
||||
|
||||
/* save interrupt context and timer mode */
|
||||
@ -158,10 +162,17 @@ int timer_set_absolute(tim_t tim, int channel, unsigned int value)
|
||||
unsigned state = irq_disable();
|
||||
|
||||
ctx[tim].dev->OCR[channel] = (uint16_t)value;
|
||||
#if defined(OCF1A) && defined(OCF1B) && (OCF1A < OCF1B)
|
||||
/* clear spurious IRQs, if any */
|
||||
*ctx[tim].flag = (1 << (channel + OCF1A));
|
||||
*ctx[tim].flag = (1 << (OCF1A + channel));
|
||||
/* unmask IRQ */
|
||||
*ctx[tim].mask |= (1 << (channel + OCIE1A));
|
||||
*ctx[tim].mask |= (1 << (OCIE1A + channel));
|
||||
#elif defined(OCF1A) && defined(OCF1B) && (OCF1A > OCF1B)
|
||||
/* clear spurious IRQs, if any */
|
||||
*ctx[tim].flag = (1 << (OCF1A - channel));
|
||||
/* unmask IRQ */
|
||||
*ctx[tim].mask |= (1 << (OCIE1A - channel));
|
||||
#endif
|
||||
set_oneshot(tim, channel);
|
||||
|
||||
irq_restore(state);
|
||||
@ -179,17 +190,28 @@ int timer_set(tim_t tim, int channel, unsigned int timeout)
|
||||
unsigned absolute = ctx[tim].dev->CNT + timeout;
|
||||
|
||||
ctx[tim].dev->OCR[channel] = absolute;
|
||||
#if defined(OCF1A) && defined(OCF1B) && (OCF1A < OCF1B)
|
||||
/* clear spurious IRQs, if any */
|
||||
*ctx[tim].flag = (1 << (channel + OCF1A));
|
||||
*ctx[tim].flag = (1 << (OCF1A + channel));
|
||||
/* unmask IRQ */
|
||||
*ctx[tim].mask |= (1 << (channel + OCIE1A));
|
||||
*ctx[tim].mask |= (1 << (OCIE1A + channel));
|
||||
#elif defined(OCF1A) && defined(OCF1B) && (OCF1A > OCF1B)
|
||||
/* clear spurious IRQs, if any */
|
||||
*ctx[tim].flag = (1 << (OCF1A - channel));
|
||||
/* unmask IRQ */
|
||||
*ctx[tim].mask |= (1 << (OCIE1A - channel));
|
||||
#endif
|
||||
set_oneshot(tim, channel);
|
||||
|
||||
if ((absolute - ctx[tim].dev->CNT) > timeout) {
|
||||
/* Timer already expired. Trigger the interrupt now and loop until it
|
||||
* is triggered.
|
||||
*/
|
||||
#if defined(OCF1A) && defined(OCF1B) && (OCF1A < OCF1B)
|
||||
while (!(*ctx[tim].flag & (1 << (OCF1A + channel)))) {
|
||||
#elif defined(OCF1A) && defined(OCF1B) && (OCF1A > OCF1B)
|
||||
while (!(*ctx[tim].flag & (1 << (OCF1A - channel)))) {
|
||||
#endif
|
||||
ctx[tim].dev->OCR[channel] = ctx[tim].dev->CNT;
|
||||
}
|
||||
}
|
||||
@ -215,10 +237,17 @@ int timer_set_periodic(tim_t tim, int channel, unsigned int value, uint8_t flags
|
||||
|
||||
ctx[tim].dev->OCR[channel] = (uint16_t)value;
|
||||
|
||||
#if defined(OCF1A) && defined(OCF1B) && (OCF1A < OCF1B)
|
||||
/* clear spurious IRQs, if any */
|
||||
*ctx[tim].flag = (1 << (channel + OCF1A));
|
||||
*ctx[tim].flag = (1 << (OCF1A + channel));
|
||||
/* unmask IRQ */
|
||||
*ctx[tim].mask |= (1 << (channel + OCIE1A));
|
||||
*ctx[tim].mask |= (1 << (OCIE1A + channel));
|
||||
#elif defined(OCF1A) && defined(OCF1B) && (OCF1A > OCF1B)
|
||||
/* clear spurious IRQs, if any */
|
||||
*ctx[tim].flag = (1 << (OCF1A - channel));
|
||||
/* unmask IRQ */
|
||||
*ctx[tim].mask |= (1 << (OCIE1A - channel));
|
||||
#endif
|
||||
|
||||
clear_oneshot(tim, channel);
|
||||
|
||||
@ -253,7 +282,11 @@ int timer_clear(tim_t tim, int channel)
|
||||
return -1;
|
||||
}
|
||||
|
||||
*ctx[tim].mask &= ~(1 << (channel + OCIE1A));
|
||||
#if defined(OCIE1A) && defined(OCIE1B) && (OCIE1A < OCIE1B)
|
||||
*ctx[tim].mask &= ~(1 << (OCIE1A + channel));
|
||||
#elif defined(OCIE1A) && defined(OCIE1B) && (OCIE1A > OCIE1B)
|
||||
*ctx[tim].mask &= ~(1 << (OCIE1A - channel));
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -293,7 +326,7 @@ static inline void _isr(tim_t tim, int chan)
|
||||
avr8_enter_isr();
|
||||
|
||||
if (is_oneshot(tim, chan)) {
|
||||
*ctx[tim].mask &= ~(1 << (chan + OCIE1A));
|
||||
timer_clear(tim, chan);
|
||||
}
|
||||
ctx[tim].cb(ctx[tim].arg, chan);
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin, Hinnerk van Bruinehsen
|
||||
* 2017 Thomas Perrot <thomas.perrot@tupi.fr>
|
||||
* 2023 Hugues Larrive
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -18,6 +19,7 @@
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
* @author Hinnerk van Bruinehsen <h.v.bruinehsen@fu-berlin.de>
|
||||
* @author Thomas Perrot <thomas.perrot@tupi.fr>
|
||||
* @author Hugues Larrive <hugues.larrive@pm.me>
|
||||
*
|
||||
*
|
||||
* Support static BAUD rate calculation using STDIO_UART_BAUDRATE.
|
||||
@ -83,12 +85,20 @@ static uart_isr_ctx_t isr_ctx[UART_NUMOF];
|
||||
|
||||
static void _update_brr(uart_t uart, uint16_t brr, bool double_speed)
|
||||
{
|
||||
#if defined(UCSR0A) || defined(UCSR1A)
|
||||
dev[uart]->BRR = brr;
|
||||
#elif defined(UCSRA) /* atmega8 */
|
||||
/* on atmega8 BRRH is shared with CSRC */
|
||||
dev[uart]->CSRC = (brr >> 8);
|
||||
dev[uart]->BRRL = (uint8_t)(brr & 0x00ff);
|
||||
#endif
|
||||
if (double_speed) {
|
||||
#ifdef CPU_ATMEGA32U4
|
||||
dev[uart]->CSRA |= (1 << U2X1);
|
||||
#else
|
||||
#if defined(U2X) /* atmega8 */
|
||||
dev[uart]->CSRA |= (1 << U2X);
|
||||
#elif defined(U2X0)
|
||||
dev[uart]->CSRA |= (1 << U2X0);
|
||||
#elif defined(U2X1) /* atmega32u4 */
|
||||
dev[uart]->CSRA |= (1 << U2X1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -129,34 +139,40 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
||||
isr_ctx[uart].arg = arg;
|
||||
|
||||
/* disable and reset UART */
|
||||
#ifdef CPU_ATMEGA32U4
|
||||
#ifdef UCSR1D /* 32u4 */
|
||||
dev[uart]->CSRD = 0;
|
||||
#endif
|
||||
dev[uart]->CSRB = 0;
|
||||
dev[uart]->CSRA = 0;
|
||||
|
||||
/* configure UART to 8N1 mode */
|
||||
#ifdef CPU_ATMEGA32U4
|
||||
dev[uart]->CSRC = (1 << UCSZ10) | (1 << UCSZ11);
|
||||
#else
|
||||
#if defined(UCSZ0) && defined(UCSZ1) /* atmega8 */
|
||||
dev[uart]->CSRC = (1 << UCSZ0) | (1 << UCSZ1);
|
||||
#elif defined(UCSZ00) && defined(UCSZ01)
|
||||
dev[uart]->CSRC = (1 << UCSZ00) | (1 << UCSZ01);
|
||||
#elif defined(UCSZ10) && defined(UCSZ11) /* 32u4 */
|
||||
dev[uart]->CSRC = (1 << UCSZ10) | (1 << UCSZ11);
|
||||
#endif
|
||||
/* set clock divider */
|
||||
_set_brr(uart, baudrate);
|
||||
|
||||
/* enable RX and TX and their respective interrupt */
|
||||
if (rx_cb) {
|
||||
#ifdef CPU_ATMEGA32U4
|
||||
dev[uart]->CSRB = ((1 << RXCIE1) | (1 << TXCIE1) | (1 << RXEN1) | (1 << TXEN1));
|
||||
#else
|
||||
#if defined(RXCIE) /* atmega8 */
|
||||
dev[uart]->CSRB = ((1 << RXCIE) | (1 << TXCIE) | (1 << RXEN) | (1 << TXEN));
|
||||
#elif defined(RXCIE0)
|
||||
dev[uart]->CSRB = ((1 << RXCIE0) | (1 << TXCIE0) | (1 << RXEN0) | (1 << TXEN0));
|
||||
#elif defined(RXCIE1) /* 32u4 */
|
||||
dev[uart]->CSRB = ((1 << RXCIE1) | (1 << TXCIE1) | (1 << RXEN1) | (1 << TXEN1));
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#ifdef CPU_ATMEGA32U4
|
||||
dev[uart]->CSRB = ((1 << TXEN1) | (1 << TXCIE1));
|
||||
#else
|
||||
#if defined(TXEN) /* atmega8 */
|
||||
dev[uart]->CSRB = ((1 << TXEN) | (1 << TXCIE));
|
||||
#elif defined(TXEN0)
|
||||
dev[uart]->CSRB = ((1 << TXEN0) | (1 << TXCIE0));
|
||||
#elif defined(TXEN1) /* 32u4 */
|
||||
dev[uart]->CSRB = ((1 << TXEN1) | (1 << TXCIE1));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -166,10 +182,12 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
||||
void uart_write(uart_t uart, const uint8_t *data, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
#ifdef CPU_ATMEGA32U4
|
||||
while (!(dev[uart]->CSRA & (1 << UDRE1))) {};
|
||||
#else
|
||||
#if defined(UDRE) /* atmega8 */
|
||||
while (!(dev[uart]->CSRA & (1 << UDRE))) {};
|
||||
#elif defined(UDRE0)
|
||||
while (!(dev[uart]->CSRA & (1 << UDRE0))) {}
|
||||
#elif defined(UDRE1) /* 32u4 */
|
||||
while (!(dev[uart]->CSRA & (1 << UDRE1))) {};
|
||||
#endif
|
||||
/* start of TX won't finish until no data in UDRn and transmit shift
|
||||
register is empty */
|
||||
|
Loading…
Reference in New Issue
Block a user