Skip to content

Commit

Permalink
Merge pull request #619 from Paciente8159/616-bug-if-a-timeout-assert…
Browse files Browse the repository at this point in the history
…-loop-using-mcu_millis-is-called-inside-an-isr-the-program-stalls

Fix program stall while waiting for timeout condition inside an ISR
  • Loading branch information
Paciente8159 authored Feb 13, 2024
2 parents 04b7b98 + fc4fef3 commit c43e408
Show file tree
Hide file tree
Showing 30 changed files with 428 additions and 265 deletions.
2 changes: 1 addition & 1 deletion uCNC/src/hal/boards/lpc176x/lpc176x.ini
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ platform_packages = Paciente8159/framework-arduino-lpc176x @ https://github.com/
; lib_deps = https://github.com/Paciente8159/uCNC-tinyusb/archive/refs/heads/master.zip
lib_ldf_mode = off
lib_compat_mode = strict
build_flags = ${common.build_flags} -D NXP_LPC17xx -D USE_ARDUINO_CDC
build_flags = ${common.build_flags} -D NXP_LPC17xx -D USE_ARDUINO_CDC -D USE_ARDUINO_WIRE

[env:LPC176X-RE-ARM]
extends = common_lpc176x
Expand Down
2 changes: 1 addition & 1 deletion uCNC/src/hal/boards/rp2040/boardmap_rpi_pico.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ extern "C"
#define I2C_CLK_BIT 27
#define I2C_DATA_BIT 26
#define I2C_PORT 1
#define I2C_ADDRESS 1
// #define I2C_ADDRESS 1

/**
* This is an example of how to use RP2040 PIO to control
Expand Down
7 changes: 6 additions & 1 deletion uCNC/src/hal/boards/samd21/boardmap_mzero.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,12 @@ extern "C"
#define I2C_DATA_BIT 22
#define I2C_DATA_PORT A
#define I2C_PORT 3
// #define I2C_ADDRESS 1
// #define I2C_ADDRESS 0

// #define DIN30_BIT 23
// #define DIN30_PORT A
// #define DIN31_BIT 22
// #define DIN31_PORT A

#define ONESHOT_TIMER 2

Expand Down
17 changes: 11 additions & 6 deletions uCNC/src/hal/boards/stm32/boardmap_blackpill.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ extern "C"
#define LIMIT_A_PORT B // assigns LIMIT_A port

// Enable limits switch interrupt
// #define LIMIT_X_ISR
// #define LIMIT_Y_ISR
// #define LIMIT_Z_ISR
// #define LIMIT_A_ISR
#define LIMIT_X_ISR
#define LIMIT_Y_ISR
#define LIMIT_Z_ISR
#define LIMIT_A_ISR

// Setup control input pins
#define ESTOP_BIT 5
Expand All @@ -71,8 +71,8 @@ extern "C"
#define FHOLD_PORT B
#define CS_RES_BIT 7
#define CS_RES_PORT B
// #define SAFETY_DOOR_BIT 8
// #define SAFETY_DOOR_PORT B
#define SAFETY_DOOR_BIT 8
#define SAFETY_DOOR_PORT B
// Setup probe pin
#define PROBE_BIT 9
#define PROBE_PORT B
Expand Down Expand Up @@ -145,6 +145,11 @@ extern "C"
// #define I2C_DATA_BIT 7
// #define I2C_DATA_PORT B
// #define I2C_PORT 1
// #define DIN7_BIT 5
// #define DIN7_PORT A
// #define DIN7_ISR
// #define DIN7_PULLUP


#define ONESHOT_TIMER 1

Expand Down
19 changes: 12 additions & 7 deletions uCNC/src/hal/boards/stm32/boardmap_bluepill.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ extern "C"
#define FHOLD_PORT B
#define CS_RES_BIT 7
#define CS_RES_PORT B
// #define SAFETY_DOOR_BIT 8
// #define SAFETY_DOOR_PORT B
#define SAFETY_DOOR_BIT 8
#define SAFETY_DOOR_PORT B
// Setup probe pin
#define PROBE_BIT 9
#define PROBE_PORT B
Expand Down Expand Up @@ -140,13 +140,18 @@ extern "C"
// On STM32F1x cores this will default to Timer 3
//#define SERVO_TIMER 3

#define I2C_CLK_BIT 10
#define I2C_CLK_PORT B
#define I2C_DATA_BIT 11
#define I2C_DATA_PORT B
#define I2C_PORT 2
// #define I2C_CLK_BIT 10
// #define I2C_CLK_PORT B
// #define I2C_DATA_BIT 11
// #define I2C_DATA_PORT B
// #define I2C_PORT 2
// #define I2C_ADDRESS 1

// #define DIN7_BIT 5
// #define DIN7_PORT B
// #define DIN7_ISR
// #define DIN7_PULLUP

#define ONESHOT_TIMER 1

#ifdef __cplusplus
Expand Down
89 changes: 49 additions & 40 deletions uCNC/src/hal/mcus/avr/mcu_avr.c
Original file line number Diff line number Diff line change
Expand Up @@ -859,10 +859,9 @@ uint32_t mcu_millis()

uint32_t mcu_micros()
{
uint32_t rtc_elapsed = RTC_TCNT;
uint32_t ms = mcu_runtime_ms;

return ((rtc_elapsed * 1000) / RTC_OCRA) + (ms * 1000);
return ((ms * 1000) + mcu_free_micros());
}

void mcu_start_rtc()
Expand Down Expand Up @@ -1064,18 +1063,23 @@ static void mcu_i2c_write_stop(bool *stop)
{
if (*stop)
{
uint32_t ms_timeout = mcu_millis() + 25;
int32_t ms_timeout = 25;

TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN);
while ((TWCR & (1 << TWSTO)) && (ms_timeout > mcu_millis()))
;
__TIMEOUT_MS__(ms_timeout)
{
if (!(TWCR & (1 << TWSTO)))
{
return;
}
}
}
}

static uint8_t mcu_i2c_write(uint8_t data, bool send_start, bool send_stop)
static uint8_t mcu_i2c_write(uint8_t data, bool send_start, bool send_stop, uint32_t ms_timeout)
{
bool stop __attribute__((__cleanup__(mcu_i2c_write_stop))) = send_stop;
uint32_t ms_timeout = mcu_millis() + 25;
int32_t timeout = ms_timeout;
if (send_start)
{
// init
Expand All @@ -1092,15 +1096,20 @@ static uint8_t mcu_i2c_write(uint8_t data, bool send_start, bool send_stop)
}

TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
while (!(TWCR & (1 << TWINT)))
__TIMEOUT_MS__(timeout)
{
if (ms_timeout < mcu_millis())
if (TWCR & (1 << TWINT))
{
stop = true;
return I2C_NOTOK;
if (TW_STATUS != TW_START && TW_STATUS != TW_REP_START)
{
stop = true;
return I2C_NOTOK;
}
break;
}
}
if (TW_STATUS != TW_START && TW_STATUS != TW_REP_START)

__TIMEOUT_ASSERT__(timeout)
{
stop = true;
return I2C_NOTOK;
Expand All @@ -1109,64 +1118,64 @@ static uint8_t mcu_i2c_write(uint8_t data, bool send_start, bool send_stop)

TWDR = data;
TWCR = (1 << TWINT) | (1 << TWEN);
while (!(TWCR & (1 << TWINT)))
timeout = ms_timeout;
__TIMEOUT_MS__(timeout)
{
if (ms_timeout < mcu_millis())
if (TWCR & (1 << TWINT))
{
stop = true;
return I2C_NOTOK;
}
}
switch (TW_STATUS)
{
case TW_MT_SLA_ACK:
case TW_MT_DATA_ACK:
case TW_MR_SLA_ACK:
case TW_MR_DATA_ACK:
break;
default:
stop = true;
return I2C_NOTOK;
}

switch (TW_STATUS)
{
case TW_MT_SLA_ACK:
case TW_MT_DATA_ACK:
case TW_MR_SLA_ACK:
case TW_MR_DATA_ACK:
break;
default:
stop = true;
return I2C_NOTOK;
return I2C_OK;
}
}

return I2C_OK;
stop = true;
return I2C_NOTOK;
}

static uint8_t mcu_i2c_read(uint8_t *data, bool with_ack, bool send_stop, uint32_t ms_timeout)
{
*data = 0xFF;
ms_timeout += mcu_millis();
bool stop __attribute__((__cleanup__(mcu_i2c_write_stop))) = send_stop;

TWCR = (1 << TWINT) | (1 << TWEN) | ((!with_ack) ? 0 : (1 << TWEA));
while (!(TWCR & (1 << TWINT)))
__TIMEOUT_MS__(ms_timeout)
{
if (ms_timeout < mcu_millis())
if (TWCR & (1 << TWINT))
{
stop = true;
return I2C_NOTOK;
*data = TWDR;
return I2C_OK;
}
}

*data = TWDR;
return I2C_OK;
stop = true;
return I2C_NOTOK;
}

#ifndef mcu_i2c_send
// master sends command to slave
uint8_t mcu_i2c_send(uint8_t address, uint8_t *data, uint8_t datalen, bool release)
uint8_t mcu_i2c_send(uint8_t address, uint8_t *data, uint8_t datalen, bool release, uint32_t ms_timeout)
{
if (data && datalen)
{
if (mcu_i2c_write(address << 1, true, false) == I2C_OK) // start, send address, write
if (mcu_i2c_write(address << 1, true, false, ms_timeout) == I2C_OK) // start, send address, write
{
// send data, stop
do
{
datalen--;
bool last = (datalen == 0);
if (mcu_i2c_write(*data, false, (release & last)) != I2C_OK)
if (mcu_i2c_write(*data, false, (release & last), ms_timeout) != I2C_OK)
{
return I2C_NOTOK;
}
Expand All @@ -1188,7 +1197,7 @@ uint8_t mcu_i2c_receive(uint8_t address, uint8_t *data, uint8_t datalen, uint32_
{
if (data && datalen)
{
if (mcu_i2c_write((address << 1) | 0x01, true, false) == I2C_OK) // start, send address, write
if (mcu_i2c_write((address << 1) | 0x01, true, false, ms_timeout) == I2C_OK) // start, send address, write
{
do
{
Expand Down
2 changes: 2 additions & 0 deletions uCNC/src/hal/mcus/avr/mcumap_avr.h
Original file line number Diff line number Diff line change
Expand Up @@ -4648,6 +4648,8 @@ extern "C"
#define US_DELAY_TICK (F_CPU / 3000000UL)
#define US_DELAY_TICK2 (F_CPU / 4000000UL)

#define mcu_free_micros() ((1000UL*RTC_TCNT)/RTC_OCRA)

#ifdef MCU_HAS_SPI
#define mcu_spi_xmit(X) \
({ \
Expand Down
2 changes: 1 addition & 1 deletion uCNC/src/hal/mcus/esp32/esp32_arduino.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -933,7 +933,7 @@ static File upload_file;
#endif
}

uint8_t mcu_i2c_send(uint8_t address, uint8_t *data, uint8_t datalen, bool release)
uint8_t mcu_i2c_send(uint8_t address, uint8_t *data, uint8_t datalen, bool release, uint32_t ms_timeout)
{
I2C_REG.beginTransmission(address);
I2C_REG.write(data, datalen);
Expand Down
5 changes: 5 additions & 0 deletions uCNC/src/hal/mcus/esp32/mcu_esp32.c
Original file line number Diff line number Diff line change
Expand Up @@ -936,6 +936,11 @@ uint32_t mcu_micros()
return (uint32_t)esp_system_get_time();
}

uint32_t mcu_free_micros()
{
return (uint32_t)(esp_system_get_time() % 1000);
}

void esp32_delay_us(uint16_t delay)
{
int64_t time = esp_system_get_time() + delay - 1;
Expand Down
5 changes: 5 additions & 0 deletions uCNC/src/hal/mcus/esp8266/mcu_esp8266.c
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,11 @@ void esp8266_delay_us(uint16_t delay)
;
}

uint32_t mcu_free_micros()
{
return (uint32_t)(esp_system_get_time() % 1000);
}

/**
* runs all internal tasks of the MCU.
* for the moment these are:
Expand Down
61 changes: 61 additions & 0 deletions uCNC/src/hal/mcus/lpc176x/lpc176x_arduino.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,5 +78,66 @@ extern "C"
}

#endif

#if defined(MCU_HAS_I2C) && defined(USE_ARDUINO_WIRE)
#include <Wire.h>
#define I2C_REG Wire
#if I2C_ADDRESS!=0
#error "I2C slave mode not supported
#endif

extern "C"
{
#if (I2C_ADDRESS != 0)
static uint8_t mcu_i2c_buffer_len;
static uint8_t mcu_i2c_buffer[I2C_SLAVE_BUFFER_SIZE];
void rp2040_i2c_onreceive(int len)
{
uint8_t l = I2C_REG.readBytes(mcu_i2c_buffer, len);
mcu_i2c_slave_cb(mcu_i2c_buffer, &l);
mcu_i2c_buffer_len = l;
}

void rp2040_i2c_onrequest(void)
{
I2C_REG.write(mcu_i2c_buffer, mcu_i2c_buffer_len);
}

#endif

void mcu_i2c_config(uint32_t frequency)
{
#if I2C_ADDRESS == 0
I2C_REG.begin();
#else
I2C_REG.onReceive(rp2040_i2c_onreceive);
I2C_REG.onRequest(rp2040_i2c_onrequest);
I2C_REG.begin(I2C_ADDRESS);
#endif
}

uint8_t mcu_i2c_send(uint8_t address, uint8_t *data, uint8_t datalen, bool release, uint32_t ms_timeout)
{
I2C_REG.beginTransmission(address);
I2C_REG.write(data, datalen);
return (I2C_REG.endTransmission() == 0) ? I2C_OK : I2C_NOTOK;
}

uint8_t mcu_i2c_receive(uint8_t address, uint8_t *data, uint8_t datalen, uint32_t ms_timeout)
{
if (I2C_REG.requestFrom(address, datalen) == datalen)
{
while(datalen--){
*data = (uint8_t)I2C_REG.read();
data++;
}

return I2C_OK;
}

return I2C_NOTOK;
}
}
#endif
}
#endif
Loading

0 comments on commit c43e408

Please sign in to comment.