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

SOFT 298: delay_us implemented without soft timer #364

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
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
20 changes: 0 additions & 20 deletions libraries/ms-common/src/delay.c

This file was deleted.

50 changes: 50 additions & 0 deletions libraries/ms-common/src/stm32f0xx/delay.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include "delay.h"

#include <stdbool.h>
#include <stddef.h>

#include "soft_timer.h"
#include "stm32f0xx.h"
#include "stm32f0xx_misc.h"
#include "wait.h"

// needs soft_timer to be initalized

static void prv_delay_us_sys_clock(uint32_t t) {
uint32_t current_time = TIM_GetCounter(TIM2); // use TIM2
uint32_t end_time = current_time + t;
// since t is uint32, there is a max of 1 rollover
bool rollover = (end_time < current_time);

while (rollover || current_time < end_time) {
// update time
uint32_t time = TIM_GetCounter(TIM2);
if (time < current_time) { // rollover detection
rollover = false;
}
current_time = time;
}
}

static void prv_delay_it(SoftTimerId timer_id, void *context) {
volatile bool *block = context;
*block = false;
}

static void prv_delay_us_soft_timer(uint32_t t) {
volatile bool block = true;
soft_timer_start(t, prv_delay_it, (void *)&block, NULL);
while (block) {
wait();
}
}

void delay_us(uint32_t t) {
// use softtimer if interrupts are not disabled
// use clock delay if iterrupts are disabled
if (__get_PRIMASK()) { // interrupts disabled
prv_delay_us_sys_clock(t);
} else {
prv_delay_us_soft_timer(t);
}
}
50 changes: 50 additions & 0 deletions libraries/ms-common/src/x86/delay.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include "delay.h"

#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <sys/time.h>
#include <time.h>

#include "soft_timer.h"
#include "wait.h"
#include "x86_interrupt.h"

static void prv_delay_us_sys_clock(uint32_t t) {
volatile struct timespec timer;

// Start clock
clock_gettime(CLOCK_MONOTONIC_RAW, &timer);
time_t start_sec = timer.tv_sec;
time_t start_nano = timer.tv_nsec;

time_t end_sec = start_sec + t / 1000000;
time_t end_nano = start_nano + (t % 1000000) * 1000;

while (timer.tv_sec < end_sec || (timer.tv_sec == end_sec && timer.tv_nsec < end_nano)) {
clock_gettime(CLOCK_MONOTONIC_RAW, &timer);
}
}

static void prv_delay_it(SoftTimerId timer_id, void *context) {
volatile bool *block = context;
*block = false;
}

static void prv_delay_us_soft_timer(uint32_t t) {
volatile bool block = true;
soft_timer_start(t, prv_delay_it, (void *)&block, NULL);
while (block) {
wait();
}
}

void delay_us(uint32_t t) {
// use softtimer if interrupts are not disabled
// use clock delay if iterrupts are disabled
if (x86_interrupt_in_handler()) { // interrupts disabled
prv_delay_us_sys_clock(t);
} else {
prv_delay_us_soft_timer(t);
}
}
17 changes: 17 additions & 0 deletions libraries/ms-common/test/test_delay.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include "soft_timer.h"
#include "unity.h"

bool soft_timer_done;

// These tests serve a dual purpose as they also implicitly test the wait
// module.

Expand All @@ -17,3 +19,18 @@ void teardown_test(void) {}
void test_delay_us(void) {
delay_us(10000);
}

// The following 2 functions test that delay_us can be used
// inside a soft timer callback without deadlock (issue SOFT-298)
static void callback(SoftTimerId timer, void *context) {
delay_us(10000);
soft_timer_done = true;
}
void test_delay_in_soft_timer(void) {
soft_timer_done = false;
soft_timer_start(10000, callback, NULL, NULL);

// Soft timer should be done after 20000 us
delay_us(20000);
TEST_ASSERT_TRUE(soft_timer_done);
}
6 changes: 3 additions & 3 deletions libraries/ms-common/test/test_watchdog.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ void test_watchdog_expiry(void) {
watchdog_start(&s_watchdog, TIMEOUT_MS, prv_expiry_callback, &context_data);
TEST_ASSERT_FALSE(s_expiry_called);

delay_ms(TIMEOUT_MS + 5);
delay_ms(TIMEOUT_MS + 50);

TEST_ASSERT_TRUE(s_expiry_called);
TEST_ASSERT_EQUAL(&context_data, s_passed_context);
Expand All @@ -67,7 +67,7 @@ void test_watchdog_expired_does_not_call_callback_multiple_times(void) {
uint32_t context_data = 0xdeadbeef;
watchdog_start(&s_watchdog, TIMEOUT_MS, prv_expiry_callback, &context_data);

delay_ms(TIMEOUT_MS + 5);
delay_ms(TIMEOUT_MS + 20);

TEST_ASSERT_TRUE(s_expiry_called);
TEST_ASSERT_EQUAL(&context_data, s_passed_context);
Expand All @@ -82,7 +82,7 @@ void test_watchdog_expired_can_start_again(void) {
watchdog_start(&s_watchdog, TIMEOUT_MS, prv_expiry_callback, &context_data);

// its expired
delay_ms(TIMEOUT_MS + 5);
delay_ms(TIMEOUT_MS + 20);
TEST_ASSERT_TRUE(s_expiry_called);
prv_reset_callback();

Expand Down
17 changes: 9 additions & 8 deletions libraries/ms-drivers/test/test_ads1259_adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#define NUM_CONFIG_REGISTERS 3
#define TEST_CHK_SUM_FLAG_BIT 0x80
#define TEST_DATA_SETTLING_TIME_MS 17
#define DATA_SETTLING_BUFFER_MS 3

#define TEST_BAUDRATE 60000
#define TEST_MOSI_PIN \
Expand Down Expand Up @@ -210,7 +211,7 @@ void test_ads1259_get_conversion_data() {
s_test_mode = ADS1259_MODE_MAX_POS_DATA;
uint32_t test_raw = 0x7FFFFF;
ads1259_get_conversion_data(&s_storage);
delay_ms(TEST_DATA_SETTLING_TIME_MS);
delay_ms(TEST_DATA_SETTLING_TIME_MS + DATA_SETTLING_BUFFER_MS);
TEST_ASSERT_EQUAL(0xFF, s_storage.conv_data.LSB | s_storage.conv_data.MID);
TEST_ASSERT_EQUAL(0x7F, s_storage.conv_data.MSB);
// Math changed as a result of hardware testing, so assertions on s_storage.reading are wrong.
Expand All @@ -222,32 +223,32 @@ void test_ads1259_get_conversion_data() {
s_test_mode = ADS1259_MODE_MAX_NEG_DATA;
test_raw = 0x800000;
ads1259_get_conversion_data(&s_storage);
delay_ms(TEST_DATA_SETTLING_TIME_MS);
delay_ms(TEST_DATA_SETTLING_TIME_MS + DATA_SETTLING_BUFFER_MS);
// TEST_ASSERT_EQUAL(-50, s_storage.reading);

// test with min readable pos data
s_test_mode = ADS1259_MODE_MIN_POS_DATA;
ads1259_get_conversion_data(&s_storage);
delay_ms(TEST_DATA_SETTLING_TIME_MS);
delay_ms(TEST_DATA_SETTLING_TIME_MS + DATA_SETTLING_BUFFER_MS);
// TEST_ASSERT_EQUAL(0.000095, s_storage.reading);

// test with min readable neg data
s_test_mode = ADS1259_MODE_MIN_NEG_DATA;
ads1259_get_conversion_data(&s_storage);
delay_ms(TEST_DATA_SETTLING_TIME_MS);
delay_ms(TEST_DATA_SETTLING_TIME_MS + DATA_SETTLING_BUFFER_MS);
// TEST_ASSERT_EQUAL(-0.000095, s_storage.reading);

// test with zero data
s_test_mode = ADS1259_MODE_ZERO_DATA;
ads1259_get_conversion_data(&s_storage);
delay_ms(TEST_DATA_SETTLING_TIME_MS);
delay_ms(TEST_DATA_SETTLING_TIME_MS + DATA_SETTLING_BUFFER_MS);
// TEST_ASSERT_EQUAL(0, s_storage.reading);

// test with a random data set
s_test_mode = ADS1259_MODE_MIXED_DATA;
test_raw = 0x102030;
ads1259_get_conversion_data(&s_storage);
delay_ms(TEST_DATA_SETTLING_TIME_MS);
delay_ms(TEST_DATA_SETTLING_TIME_MS + DATA_SETTLING_BUFFER_MS);
TEST_ASSERT_EQUAL(0x10, s_storage.conv_data.MSB);
TEST_ASSERT_EQUAL(0x20, s_storage.conv_data.MID);
TEST_ASSERT_EQUAL(0x30, s_storage.conv_data.LSB);
Expand All @@ -258,13 +259,13 @@ void test_ads1259_get_conversion_data() {
s_test_mode = ADS1259_MODE_CHECKSUM_FAULT;
s_checksum = false;
ads1259_get_conversion_data(&s_storage);
delay_ms(TEST_DATA_SETTLING_TIME_MS);
delay_ms(TEST_DATA_SETTLING_TIME_MS + DATA_SETTLING_BUFFER_MS);
TEST_ASSERT_TRUE(s_checksum);

// test out of range flag triggered
s_test_mode = ADS1259_MODE_OUT_RANGE_FLAG_TRIGGERED;
s_out_of_range = false;
ads1259_get_conversion_data(&s_storage);
delay_ms(TEST_DATA_SETTLING_TIME_MS);
delay_ms(TEST_DATA_SETTLING_TIME_MS + DATA_SETTLING_BUFFER_MS);
TEST_ASSERT_TRUE(s_out_of_range);
}
13 changes: 7 additions & 6 deletions mu/ctl/req.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import requests
from mu.srv.server import TCP_PORT

def send(route, params=None, body=None):
url = 'http://localhost:{}/{}'.format(TCP_PORT, route)
return requests.get(url, params=params, json=body)
import requests
from mu.srv.server import TCP_PORT


def send(route, params=None, body=None):
url = 'http://localhost:{}/{}'.format(TCP_PORT, route)
return requests.get(url, params=params, json=body)
72 changes: 36 additions & 36 deletions mu/ctl/sims.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
import json
import mu.ctl.req as req
def reset(args):
r = req.send('reset')
print(r.text)
def start(args):
params = { 'sim': args.sim, 'proj': args.proj }
r = req.send('start', params)
print(r.text)
def stop(args):
params = { 'sim': args.sim }
r = req.send('stop', params)
print(r.text)
def sims(args):
r = req.send('sims')
sims = json.loads(r.text)
print('Available sims:')
for sim in sims:
print(sim)
def sim_list(args):
r = req.send('list')
sims = json.loads(r.text)
print('Running sims:')
for sim in sims:
print(sim)
import json

import mu.ctl.req as req


def reset(args):
r = req.send('reset')
print(r.text)


def start(args):
params = {'sim': args.sim, 'proj': args.proj}
r = req.send('start', params)
print(r.text)


def stop(args):
params = {'sim': args.sim}
r = req.send('stop', params)
print(r.text)


def sims(args):
r = req.send('sims')
sims = json.loads(r.text)
print('Available sims:')
for sim in sims:
print(sim)


def sim_list(args):
r = req.send('list')
sims = json.loads(r.text)
print('Running sims:')
for sim in sims:
print(sim)