Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cpu/atmega*: factorise common code into atmega_common #9866

Merged
merged 7 commits into from Nov 4, 2018

Conversation

kYc0o
Copy link
Contributor

@kYc0o kYc0o commented Aug 30, 2018

Contribution description

This PR aims to take some commits from #9130 to ease the review.
In this PR I took code from atmega platforms and place it in atmega_common, since it was basically all the same.

Testing procedure

Please run at least one example/test for each of these platforms:

Issues/PRs references

#9130

@kYc0o kYc0o added Platform: AVR Platform: This PR/issue effects AVR-based platforms Type: cleanup The issue proposes a clean-up / The PR cleans-up parts of the codebase / documentation CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Area: boards Area: Board ports Area: cpu Area: CPU/MCU ports labels Aug 30, 2018
@kYc0o kYc0o added this to the Release 2018.10 milestone Aug 30, 2018
A-Paul
A-Paul previously requested changes Aug 30, 2018
Copy link
Member

@A-Paul A-Paul left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running tests/{od,shell,thread_basic,thread_flood,xtimer_usleep} is successful.
But tests/xtimer_hang hangs (nomen est omen) before boot message. Crosschecked with master, which is fine.

Copy link
Contributor

@ZetaR60 ZetaR60 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few things below. I haven't tested yet, but it is next on my todo list.

cpu/atmega_common/cpu.c Outdated Show resolved Hide resolved
cpu/atmega_common/cpu.c Show resolved Hide resolved
@Josar
Copy link
Contributor

Josar commented Sep 2, 2018

Thumps up for generalizing code for all platforms.

@kYc0o
Copy link
Contributor Author

kYc0o commented Sep 3, 2018

I just pushed some modifications to generalise a bit more the code, however some registers don't exists for some platforms. @Josar and @ZetaR60 can you test on your atmega boards? So far some tests are ok with the mega2560 and uno.

@A-Paul I'll check this strange behaviour for xtimer.

@kYc0o
Copy link
Contributor Author

kYc0o commented Sep 3, 2018

@kaspar030 murdock seems frozen...

@kYc0o
Copy link
Contributor Author

kYc0o commented Sep 5, 2018

Rebased since #9781 was merged. @A-Paul I did the tests you mentioned and they run successfully on arduino-mega2560. Which platform are you using?

@A-Paul
Copy link
Member

A-Paul commented Sep 6, 2018

@kYc0o , in your list of boards I dedicated myself to test the arduino-duemilanove. ;-)

@Josar
Copy link
Contributor

Josar commented Sep 6, 2018

@kYc0o run this tests on jiminy with expected behaviour.

  • tests_xtimer_usleep_short
  • tests_xtimer_usleep
  • tests_xtimer_reset
  • tests_xtimer_remove
  • tests_xtimer_periodic_wakeup
  • tests_xtimer_hang
  • tests_thread_priority_inversion
  • tests_thread_race

@kYc0o
Copy link
Contributor Author

kYc0o commented Sep 6, 2018

@kYc0o , in your list of boards I dedicated myself to test the arduino-duemilanove. ;-)

Unfortunately @A-Paul I don't have that platform. Do you mind to test with the most recent commits? I don't see how that specific test can be affected by this PR.

@A-Paul
Copy link
Member

A-Paul commented Sep 6, 2018

After checking out your last changes I get compile errors for some tests. I only tried tests/xtimer_*.
I concatenated the make output (error lines only) to this gist:

https://gist.github.com/A-Paul/62c3838be10840386451d5a57b655824#file-gistfile1-txt

This happened to me with arduino-uno and arduino-duemilanove.

@kYc0o
Copy link
Contributor Author

kYc0o commented Sep 6, 2018

@kYc0o run this tests on jiminy with expected behaviour.

Thanks @Josar, can you tick your board?

After checking out your last changes I get compile errors for some tests.

Yes that's normal since #9781, which added linker scripts for AVR platforms, so now they will fail if the memory doesn't fit. Maybe this PR is increasing the size for the given tests? Anyways Murdock should have complained about it, and it doesn't.

@kYc0o
Copy link
Contributor Author

kYc0o commented Sep 6, 2018

Anyways Murdock should have complained about it, and it doesn't.

Overlooked the errors on Murdock, it does appear there. I'll check why there's a huge memory increase by this PR.

@kYc0o
Copy link
Contributor Author

kYc0o commented Sep 6, 2018

Well I found the reason, which is basically that having a common THREAD_STACKSIZE_DEFAULT per architecture increased the stack for all CPUs, and atmega328p is on the limit of RAM for many examples. Thus, 256B more is enough to overflow the RAM. This is also true for some tests with other atmegas.

My 2c is that I blacklist these platforms from this tests since running tests with less than 256B of memory left may lead to errors.

Any opinions?

Copy link
Contributor

@ZetaR60 ZetaR60 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test results on mega-xplained:

shell			still reboot loops!
xtimer_hang		fail (misses more than 10%)

thread_basic		pass
thread_flood		pass
thread_race		pass
xtimer_periodic_wakeup	pass
xtimer_remove		pass
xtimer_reset		pass
xtimer_usleep		pass
xtimer_usleep_short	pass

cpu/atmega_common/cpu.c Outdated Show resolved Hide resolved
cpu/atmega_common/cpu.c Show resolved Hide resolved
ISR(BADISR_vect){

ISR(BADISR_vect)
{
_reset_cause();

printf_P(PSTR("FATAL ERROR: BADISR_vect called, unprocessed Interrupt.\n"
"STOP Execution.\n"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error message could probably be a core_panic with reason PANIC_DUMMY_HANDLER.

It would need to go where the while (1) {} is, because a panic halts the system.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I'll modify that part and make the corresponding tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking, is there an easy way to trigger this? So we can make a proper test.

cpu/atmega_common/cpu.c Outdated Show resolved Hide resolved
cpu/atmega_common/cpu.c Outdated Show resolved Hide resolved
@ZetaR60
Copy link
Contributor

ZetaR60 commented Sep 6, 2018

I think that blacklisting the ATmega328P is fine because it is already known that ATmega has problems with the stack size being too small. ATmega328P is pretty limited compared to the typical RIOT MCU, and we probably don't want to keep the more capable systems broken in order to accommodate it.

I think a more comprehensive change to how stack sizes are determined is needed to properly support the ATmega328P.

@A-Paul
Copy link
Member

A-Paul commented Sep 10, 2018

sure why. Anyone else tried reboot using the shell?

@ZetaR60, I checked tests/shell with this PR on an arduino-duemilanove and arduino-mega2560.
With both boards:
Reset button: OK, make reset: OK, > reboot : loop
When looping neither reseting with button or make reset will change that state. Only reconnecting the board will.

This effect seems to be fairly common. Just an example:
https://andreasrohner.at/posts/Electronics/How-to-make-the-Watchdog-Timer-work-on-an-Arduino-Pro-Mini-by-replacing-the-bootloader/

@A-Paul
Copy link
Member

A-Paul commented Sep 10, 2018

I think a more comprehensive change to how stack sizes are determined is needed to properly support the ATmega328P.

There is some 'magic' for handling constant data and strings to lower ram usage.
https://www.microchip.com/webdoc/AVRLibcReferenceManual/pgmspace.html
On the fly, I can figure out at least one occurrence (cpu/atmega_common/cpu.c:127) where this is used. I guess that has potential for saving ram.

@Josar
Copy link
Contributor

Josar commented Sep 11, 2018

I can not push to your repo so i will post it here.

cpu.c

/*
* Since atmega MCUs do not feature a software reset, the watchdog timer
* is being used. It will be set to the shortest time and then force a
* reset. Therefore the MCUSR register needs to be resetted as fast as
* possible. 
* Which means in the bootloader or in the following init0 if no bootloader is used.
* Bootloader resets watchdog and pass MCUSR in r2 (e.g. Optiboot) in order to pass
* information about the reset cause to the application.
* When no Bootloader is used the watchdog will be disabled in the init0 section.
* When a software reset was triggered, r3 will contain 0xAA. 
* In order to prevent changes to the values from the .init section, MCUSR and r3 
* are saved in the .init0 section
*/
uint8_t mcusr_mirror __attribute__((section(".noinit")));
uint8_t soft_rst __attribute__((section(".noinit")));
void get_mcusr(void) __attribute__((naked)) __attribute__((section(".init0")));

void get_mcusr(void)
{
    /* save soft reset flag set in reset routine */
    __asm__ __volatile__("mov %0, r3\n" : "=r" (soft_rst) :);
#ifdef BOOTLOADER_CLEARS_WATCHDOG_AND_PASSES_MCUSR
    /* save the reset flags passed from the bootloader */
    __asm__ __volatile__("mov %0, r2\n" : "=r" (mcusr_mirror) :);
#else
    /* save the reset flags */
#if defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) ||	\
    defined(__AVR_ATmega16__)   || defined(__AVR_ATmega162__) ||	\
    defined (__AVR_ATmega128__)
  mcusr_mirror = MCUCSR;
  MCUSR = 0;
#else
  mcusr_mirror = MCUSR;
  MCUSR = 0;
#endif
    wdt_disable();
#endif
}

board.h (jiminy)

/**
 * @name Indicate Watchdog cleared in bootloader an 
 * 
 * AVR CPUs need to reset the Watchdog as fast as possible.
 * This flag indicates that the watchdog is reseted in the bootloader
 * and that the MCUSR value is stored in register 2 (r2)
 * @{
 */
#define BOOTLOADER_CLEARS_WATCHDOG_AND_PASSES_MCUSR 1
/** @} */

@kYc0o
Copy link
Contributor Author

kYc0o commented Sep 19, 2018

@Josar thanks for your patch! I'll add it soon to make this ready. I'll also address your comments @ZetaR60. Sorry for the delay.

@Josar
Copy link
Contributor

Josar commented Sep 19, 2018

@kYc0o this patch is only tested for the atmega256rfr2. The other part has to be tested and verified.

@kYc0o
Copy link
Contributor Author

kYc0o commented Sep 19, 2018

@Josar yes sure, I'll make tests on the platforms I have.

Copy link
Contributor

@ZetaR60 ZetaR60 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple minor suggestions, otherwise it looks good!

Thanks for your work on this kYc0o!

/* save the reset flags */
#if defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) || \
defined(__AVR_ATmega16__) || defined(__AVR_ATmega162__) || \
defined (__AVR_ATmega128__)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this amounts to "the system has an MCUCSR register", then this complex ifdef can be changed to #ifdef MCUCSR.

cpu/atmega_common/cpu.c Show resolved Hide resolved
@ZetaR60
Copy link
Contributor

ZetaR60 commented Oct 6, 2018

I wrote a quick test case to generate a BADISR. It is pretty tightly linked to this PR so you might want to add it here, but I can create a separate PR if you want. (Sorry for the blocks of code; we need hide-able sections in comments).

tests/atmega_badisr/main.c

/*
 * Copyright (C) 2018 Acutam Automation, LLC
 *
 * 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 details.
 */

/**
 * @ingroup     tests
 * @{
 *
 * @file
 * @brief       Test for ATmega BADISR handling
 *
 * @author      Matthew Blue <matthew.blue.neuro@gmail.com>
 *
 * @}
 */

#include <avr/io.h>
#include <stdio.h>

int main(void)
{
    puts("ATmega BADISR test routine");

    /* Initialize timer 0 */
    TCCR0A = 0;
    TCCR0B = 0;
    TCNT0 = 0;

    /* Enable overflow interrupt without defining ISR */
#ifdef TOIE0
    TIMSK0 = (1 << TOIE0);
#else
    TIMSK0 = (1 << TOIE);
#endif

    /* Clear interrupt flags (oddly, by writing a 1) */
#ifdef TOV0
    TIFR0 = (1 << TOV0);
#else
    TIFR0 = (1 << TOV);
#endif

    /* Start the clock (will BADISR at overflow) */
    TCCR0B = (1 << CS00);

    /* Wait for BADISR */
    while (1) {}

    return 0;
}

tests/atmega_badisr/Makefile

include ../Makefile.tests_common

BOARD_WHITELIST += arduino-duemilanove \
                   arduino-mega2560 \
                   arduino-uno \
                   jiminy-mega256rfr2 \
                   mega-xplained \
                   waspmote-pro

TEST_ON_CI_WHITELIST += arduino-duemilanove \
                        arduino-mega2560 \
                        arduino-uno \
                        jiminy-mega256rfr2 \
                        mega-xplained \
                        waspmote-pro

include $(RIOTBASE)/Makefile.include

tests/atmega_badisr/tests/01-run.py

#!/usr/bin/env python3

# Copyright (C) 2018 Acutam Automation, LLC
#
# 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 details.

import sys
from testrunner import run


def testfunc(child):
    child.expect_exact("ATmega BADISR test routine")
    child.expect_exact("*** RIOT kernel panic:")
    child.expect_exact("*** halted.")

if __name__ == "__main__":
    sys.exit(run(testfunc))

Note that Makefile definitions for tests have changed since this PR was created. Without a rebase you will need to add this to the Makefile:

test:
        tests/01-run.py

And here are the results I get on mega-xplained:

user@lm:~/Desktop/RIOT/tests/atmega_badisr$ make BOARD=mega-xplained term
/home/user/Desktop/RIOT/makefiles/toolchain/gnu.inc.mk:18: objcopy not found. Hex file will not be created.
/bin/sh: 1: avr-ld: not found
/home/user/Desktop/RIOT/dist/tools/pyterm/pyterm -p "/dev/ttyACM0" -b "9600"
No handlers could be found for logger "root"
2018-10-06 17:34:26,585 - INFO # Connect to serial port /dev/ttyACM0
Welcome to pyterm!
Type '/exit' to exit.
2018-10-06 17:34:28,588 - INFO # 

2018-10-06 17:34:28,659 - INFO # main(): This is RIOT! (Version: 2016.03-devel-9848-gb45d51-6807c15f4413-cpu/atmega/reuse_common)
2018-10-06 17:34:28,689 - INFO # ATmega BADISR test routine
2018-10-06 17:34:28,788 - INFO # *** RIOT kernel panic:
2018-10-06 17:34:28,789 - INFO #    
2018-10-06 17:34:28,790 - INFO # 
2018-10-06 17:34:28,791 - INFO # *** halted.
2018-10-06 17:34:28,792 - INFO # 
2018-10-06 17:34:33,904 - INFO # Exiting Pyterm

Note that the message for core_panic is not being printed.

@kYc0o
Copy link
Contributor Author

kYc0o commented Oct 11, 2018

@ZetaR60 comments addressed. For your test, maybe you can push a PR based on this one, with the "waiting for PR" label set.

Note that the message for core_panic is not being printed.

Maybe you need to activate DEVELHELP in the test makefile to having it printed.

I hope @Josar will have time soon to get this finally merged. Thanks @ZetaR60 for your testing and review!

@kYc0o
Copy link
Contributor Author

kYc0o commented Oct 11, 2018

@PeterKietzmann can you perform a quick test on waspmote-pro? compiling and flashing tests/shell and perform reboot should be enough.

@kYc0o
Copy link
Contributor Author

kYc0o commented Oct 30, 2018

@Josar could you run the tests on your platform?

@Josar
Copy link
Contributor

Josar commented Oct 31, 2018

shell			no reboot loop
xtimer_hang		pass (hiccup, but passed)
thread_basic		pass
thread_flood		pass
thread_race		pass
xtimer_periodic_wakeup	pass
xtimer_remove		pass
xtimer_reset		pass
xtimer_usleep		pass
xtimer_usleep_short	pass

@kYc0o
Copy link
Contributor Author

kYc0o commented Oct 31, 2018

Great! so, @ZetaR60 you can ACK now. I'll take care of the overflowed tests to get Murdock pass.

@ZetaR60
Copy link
Contributor

ZetaR60 commented Nov 1, 2018

Double checked the tests before ACK:

shell			no reboot loop
xtimer_hang		pass
thread_basic		pass
thread_flood		pass
thread_race		pass
xtimer_periodic_wakeup	pass
xtimer_remove		pass
xtimer_reset		pass
xtimer_usleep		pass
xtimer_usleep_short	pass

Removes duplicated code for atmega platforms. They were all
basically the same, only with the exception of atmegarfr2,
for which there is an #if statement to use the code in the
same file.
Removes redundancy of code since all the boards were defining
the same variables. Moreover, the stack sizes are unified per
architecture, as required.
cpu.c and startup.c were redundant in most platforms, except for
atmega256rfr2. The common code is now in cpu/atmega_common/cpu.c
and cpu/atmega_common/startup.c. cpu_conf.h is also removed as
it's now in cpu/atmega_common/include thus shared by all atmega
based platforms.
This adds a LED_PANIC macro which defines which LED,
or combination of LEDs should notify a panic error.
This is currently used to signal BADISR_vect errors.
The `atmega_set_prescaler` was using a "sensible" default
but it's better to define it at the board level to make
it clear.
This variable helps to inform at boot time that some
information about the booting process, e.g. reset cause.
The unification of a bigger stack for the atmega platforms
makes some boards to not have enough memory to provide
the big stack plus the application code.

It is possible though, to override the stack size to a
smaller amount if running the test is necessary.
@ZetaR60 ZetaR60 merged commit 8130874 into RIOT-OS:master Nov 4, 2018
@ZetaR60
Copy link
Contributor

ZetaR60 commented Nov 4, 2018

Merging. Thanks for the cleanup @kYc0o !

@kaspar030
Copy link
Contributor

+215 -721! Nice one!

@kYc0o kYc0o deleted the cpu/atmega/reuse_common branch November 5, 2018 00:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: boards Area: Board ports Area: cpu Area: CPU/MCU ports CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Platform: AVR Platform: This PR/issue effects AVR-based platforms Type: cleanup The issue proposes a clean-up / The PR cleans-up parts of the codebase / documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants