Skip to content

Mock for sleep and wdt #115

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

Merged
merged 11 commits into from
Feb 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Added
- Proper `ostream operator <<` for `nullptr`
- Proper comparison operations fro `nullptr`
- Mocks for avr/sleep.h and avr/wdt.h
- Definitions for ISR and ADCSRA

### Changed
- `Compare.h` heavily refactored to use a smallish macro
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
compile:
libraries: ~
platforms:
- uno
- leonardo

unittest:
libraries: ~
platforms:
- uno
- leonardo
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <avr/sleep.h>

#define BUTTON_INT_PIN 2

void setup() {
Serial.begin(115200);
Serial.println("start");
delay(200);
pinMode(BUTTON_INT_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(BUTTON_INT_PIN), isrButtonTrigger, FALLING);
}

void loop() {
// sleep unti an interrupt occurs
sleep_enable(); // enables the sleep bit, a safety pin
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_cpu(); // here the device is actually put to sleep
sleep_disable(); // disables the sleep bit, a safety pin

Serial.println("interrupt");
delay(200);
}

void isrButtonTrigger() {
// nothing to do, wakes up the CPU
}

11 changes: 11 additions & 0 deletions SampleProjects/DoSomething/examples/AvrWdtReset/.arduino-ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
compile:
libraries: ~
platforms:
- uno
- leonardo

unittest:
libraries: ~
platforms:
- uno
- leonardo
29 changes: 29 additions & 0 deletions SampleProjects/DoSomething/examples/AvrWdtReset/AvrWdtReset.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include <avr/wdt.h>

void setup() {
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);

wdt_enable(WDTO_4S);
// First timeout executes interrupt, second does reset.
// So first LED 4s off
// then LED 4s on
// then reset CPU and start again
WDTCSR |= (1 << WDIE);
}

void loop() {
// the program is alive...for now.
wdt_reset();

while (1)
; // do nothing. the program will lockup here.

// Can not get here
}

ISR (WDT_vect) {
// WDIE & WDIF is cleared in hardware upon entering this ISR
digitalWrite(LED_BUILTIN, HIGH);
}

10 changes: 10 additions & 0 deletions SampleProjects/TestSomething/test/adc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include <ArduinoUnitTests.h>
#include <Arduino.h>

unittest(check_ADCSRA_read_write) {
ADCSRA = 123;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Where is ADCSRA defined?

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 added explanations into this file


assertEqual(123, ADCSRA);
}

unittest_main()
7 changes: 6 additions & 1 deletion SampleProjects/TestSomething/test/interrupts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ unittest(interrupt_attachment) {
assertFalse(state->interrupt[0].attached);
}


// Just check if declaration compiles.
// WDT_vect defines the interrupt of the watchdog timer
// if configured accordinly.
// See avr/interrupt.h
ISR (WDT_vect) {
}

unittest_main()
65 changes: 65 additions & 0 deletions SampleProjects/TestSomething/test/sleep.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include <ArduinoUnitTests.h>
#include <avr/sleep.h>

GodmodeState* state = GODMODE();

unittest(sleep_enable) {
state->reset();
assertFalse(state->sleep.sleep_enable);
assertEqual(0, state->sleep.sleep_enable_count);

sleep_enable();

assertTrue(state->sleep.sleep_enable);
assertEqual(1, state->sleep.sleep_enable_count);
}

unittest(sleep_disable) {
state->reset();
assertEqual(0, state->sleep.sleep_disable_count);

sleep_disable();

assertFalse(state->sleep.sleep_enable);
assertEqual(1, state->sleep.sleep_disable_count);
}

unittest(set_sleep_mode) {
state->reset();
assertEqual(0, state->sleep.sleep_mode);

set_sleep_mode(SLEEP_MODE_PWR_DOWN);

assertEqual(SLEEP_MODE_PWR_DOWN, state->sleep.sleep_mode);
}

unittest(sleep_bod_disable) {
state->reset();
assertEqual(0, state->sleep.sleep_bod_disable_count);

sleep_bod_disable();

assertEqual(1, state->sleep.sleep_bod_disable_count);
}

unittest(sleep_cpu) {
state->reset();
assertEqual(0, state->sleep.sleep_cpu_count);

sleep_cpu();

assertEqual(1, state->sleep.sleep_cpu_count);
}

unittest(sleep_mode) {
state->reset();
assertEqual(0, state->sleep.sleep_mode_count);

sleep_mode();

assertEqual(1, state->sleep.sleep_mode_count);
assertEqual(1, state->sleep.sleep_enable_count);
assertEqual(1, state->sleep.sleep_disable_count);
}

unittest_main()
41 changes: 41 additions & 0 deletions SampleProjects/TestSomething/test/wdt.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <ArduinoUnitTests.h>
#include <avr/wdt.h>

GodmodeState* state = GODMODE();

unittest(taskWdtEnable_checkTimeout) {
state->reset();
assertEqual(0, state->wdt.timeout);

wdt_enable(WDTO_1S);

assertTrue(state->wdt.wdt_enable);
assertEqual(WDTO_1S, state->wdt.timeout);
assertEqual(1, state->wdt.wdt_enable_count);
}

unittest(taskWdtEnableDisable) {
state->reset();
assertEqual(0, state->wdt.wdt_enable_count);

wdt_enable(WDTO_1S);

assertTrue(state->wdt.wdt_enable);
assertEqual(1, state->wdt.wdt_enable_count);

wdt_disable();

assertFalse(state->wdt.wdt_enable);
assertEqual(1, state->wdt.wdt_enable_count);
}

unittest(wdt_reset) {
state->reset();
assertEqual(0, state->wdt.wdt_reset_count);

wdt_reset();

assertEqual(1, state->wdt.wdt_reset_count);
}

unittest_main()
3 changes: 3 additions & 0 deletions cpp/arduino/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ typedef uint8_t byte;
// Math and Trig
#include "AvrMath.h"

#include "AvrAdc.h"
#include "avr/interrupt.h"

#include "Godmode.h"


Expand Down
4 changes: 4 additions & 0 deletions cpp/arduino/AvrAdc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#include "AvrAdc.h"

// mock storage to allow access to ADCSRA
unsigned char sfr_store;
9 changes: 9 additions & 0 deletions cpp/arduino/AvrAdc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

// ADCSRA is defined in the CPU specific header files
// like iom328p.h.
// It is liked to _SFR_MEM8 what does not exists in the test environment.
// Therefore we define _SFR_MEM8 here and provide it a storage
// location so that the test code can read/write on it.
extern unsigned char sfr_store;
#define _SFR_MEM8(mem_addr) sfr_store
42 changes: 41 additions & 1 deletion cpp/arduino/Godmode.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,24 @@ class GodmodeState {
uint8_t mode;
};

struct SleepDef {
bool sleep_enable = false;
unsigned int sleep_enable_count = 0;
unsigned int sleep_disable_count = 0;
unsigned char sleep_mode = 0;
unsigned int sleep_cpu_count = 0;
unsigned int sleep_mode_count = 0;
unsigned int sleep_bod_disable_count = 0;
};

struct WdtDef {
bool wdt_enable = false;
unsigned char timeout = 0;
unsigned int wdt_enable_count = 0;
unsigned int wdt_disable_count = 0;
unsigned int wdt_reset_count = 0;
};

public:
unsigned long micros;
unsigned long seed;
Expand All @@ -52,6 +70,8 @@ class GodmodeState {
struct PortDef serialPort[NUM_SERIAL_PORTS];
struct InterruptDef interrupt[MOCK_PINS_COUNT]; // not sure how to get actual number
struct PortDef spi;
struct SleepDef sleep;
struct WdtDef wdt;

void resetPins() {
for (int i = 0; i < MOCK_PINS_COUNT; ++i) {
Expand Down Expand Up @@ -85,12 +105,32 @@ class GodmodeState {
spi.readDelayMicros = 0;
}

void resetSleep() {
sleep.sleep_enable = false;
sleep.sleep_enable_count = 0;
sleep.sleep_disable_count = 0;
sleep.sleep_mode = 0;
sleep.sleep_cpu_count = 0;
sleep.sleep_mode_count = 0;
sleep.sleep_bod_disable_count = 0;
}

void resetWdt() {
wdt.wdt_enable = false;
wdt.timeout = 0;
wdt.wdt_enable_count = 0;
wdt.wdt_disable_count = 0;
wdt.wdt_reset_count = 0;
}

void reset() {
resetClock();
resetPins();
resetInterrupts();
resetPorts();
resetSPI();
resetSleep();
resetWdt();
seed = 1;
}

Expand All @@ -114,7 +154,7 @@ int analogRead(uint8_t);
void analogWrite(uint8_t, int);
#define analogReadResolution(...) _NOP()
#define analogWriteResolution(...) _NOP()
void attachInterrupt(uint8_t interrupt, void ISR(void), uint8_t mode);
void attachInterrupt(uint8_t interrupt, void isr(void), uint8_t mode);
void detachInterrupt(uint8_t interrupt);

// TODO: issue #26 to track the commanded state here
Expand Down
15 changes: 15 additions & 0 deletions cpp/arduino/avr/interrupt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
This header file defines the macros required for the production
code for AVR CPUs to declare ISRs in the test environment.
See for more details
https://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html
*/
#pragma once

// Allows the production code to define an ISR method.
// These definitions come from the original avr/interrupt.h file
// https://www.nongnu.org/avr-libc/user-manual/interrupt_8h_source.html
#define _VECTOR(N) __vector_ ## N
#define ISR(vector, ...) \
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please add a link to the ISR() docs. Also, what is the extern doing here? What does this macro perform?

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 added an explanation there

extern "C" void vector (void) __VA_ARGS__; \
void vector (void)
42 changes: 42 additions & 0 deletions cpp/arduino/avr/sleep.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
This header file defines the functionality to put AVR CPUs to sleep mode.
For details see
https://www.nongnu.org/avr-libc/user-manual/group__avr__sleep.html
*/
#pragma once

#include <Godmode.h>

void sleep_enable() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please link to sleep-mode docs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

GodmodeState* godmode = GODMODE();
godmode->sleep.sleep_enable = true;
godmode->sleep.sleep_enable_count++;
}

void sleep_disable() {
GodmodeState* godmode = GODMODE();
godmode->sleep.sleep_enable = false;
godmode->sleep.sleep_disable_count++;
}

void set_sleep_mode(unsigned char mode) {
GodmodeState* godmode = GODMODE();
godmode->sleep.sleep_mode = mode;
}

void sleep_bod_disable() {
GodmodeState* godmode = GODMODE();
godmode->sleep.sleep_bod_disable_count++;
}

void sleep_cpu() {
GodmodeState* godmode = GODMODE();
godmode->sleep.sleep_cpu_count++;
}

void sleep_mode() {
GodmodeState* godmode = GODMODE();
sleep_enable();
godmode->sleep.sleep_mode_count++;
sleep_disable();
}
Loading