Skip to content

Commit

Permalink
Merge pull request #870 from bdring/Devt
Browse files Browse the repository at this point in the history
Devt
  • Loading branch information
bdring authored Apr 24, 2023
2 parents 468fee9 + 855b0c9 commit 196788a
Show file tree
Hide file tree
Showing 162 changed files with 1,656 additions and 1,452 deletions.
59 changes: 59 additions & 0 deletions FluidNC/esp32/delay_usecs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include "Driver/delay_usecs.h"

#include <esp_attr.h> // IRAM_ATTR
#include <xtensa/core-macros.h>

#include <sdkconfig.h>

#if CONFIG_IDF_TARGET_ESP32
# include "esp32/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S2
# include "esp32s2/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S3
# include "esp32s3/clk.h"
#elif CONFIG_IDF_TARGET_ESP32C3
# include "esp32c3/clk.h"
#elif CONFIG_IDF_TARGET_ESP32H2
# include "esp32h2/clk.h"
#endif

uint32_t ticks_per_us;
int esp_clk_cpu_freq(void);

void timing_init() {
ticks_per_us = esp_clk_cpu_freq() / 1000000;
}

void IRAM_ATTR delay_us(int32_t us) {
spinUntil(usToEndTicks(us));
}

int32_t IRAM_ATTR usToCpuTicks(int32_t us) {
return us * ticks_per_us;
}

int32_t IRAM_ATTR usToEndTicks(int32_t us) {
return getCpuTicks() + usToCpuTicks(us);
}

// At the usual ESP32 clock rate of 240MHz, the range of this is
// just under 18 seconds, but it really should be used only for
// short delays up to a few tens of microseconds.

void IRAM_ATTR spinUntil(int32_t endTicks) {
while ((getCpuTicks() - endTicks) < 0) {
#ifdef ESP32
asm volatile("nop");
#endif
}
}

// Short delays measured using the CPU cycle counter. There is a ROM
// routine "esp_delay_us(us)" that almost does what what we need,
// except that it is in ROM and thus dodgy for use from ISRs. We
// duplicate the esp_delay_us() here, but placed in IRAM, inlined,
// and factored so it can be used in different ways.

int32_t IRAM_ATTR getCpuTicks() {
return XTHAL_GET_CCOUNT();
}
1 change: 0 additions & 1 deletion FluidNC/esp32/gpio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ void gpio_mode(pinnum_t pin, bool input, bool output, bool pullup, bool pulldown
if (opendrain) {
conf.mode = (gpio_mode_t)((int)conf.mode | GPIO_MODE_DEF_OD);
}
log_debug("gpio conf " << conf.pull_up_en << " " << pin);
gpio_config(&conf);
}
void IRAM_ATTR gpio_set_interrupt_type(pinnum_t pin, int mode) {
Expand Down
8 changes: 2 additions & 6 deletions FluidNC/esp32/sdspi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#define CHECK_EXECUTE_RESULT(err, str) \
do { \
if ((err) != ESP_OK) { \
log_error(str << " code 0x" << String(err, 16)); \
log_error(str << " code 0x" << to_hex(err)); \
goto cleanup; \
} \
} while (0)
Expand Down Expand Up @@ -78,10 +78,7 @@ bool sd_init_slot(uint32_t freq_hz, int cs_pin, int cd_pin, int wp_pin) {

sdspi_device_config_t slot_config;

// If freq_hz is 0, use the system default
if (freq_hz) {
host_config.max_freq_khz = freq_hz / 1000;
}
host_config.max_freq_khz = freq_hz / 1000;

err = host_config.init();
CHECK_EXECUTE_RESULT(err, "host init failed");
Expand All @@ -104,7 +101,6 @@ bool sd_init_slot(uint32_t freq_hz, int cs_pin, int cd_pin, int wp_pin) {
// If you do it only once below, the attempt to change it seems to
// be ignored, and you get 20 MHz regardless of what you ask for.
if (freq_hz) {
printf("hz = %d\n", freq_hz);
err = sdspi_host_set_card_clk(host_config.slot, freq_hz / 1000);
CHECK_EXECUTE_RESULT(err, "set slot clock speed failed");
}
Expand Down
9 changes: 7 additions & 2 deletions FluidNC/esp32/spi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@

#include "Driver/spi.h"

#include <SPI.h>
#include "driver/spi_common.h"
#include "src/Config.h"

#include <sdkconfig.h>

#ifdef CONFIG_IDF_TARGET_ESP32S3
# define HSPI_HOST SPI2_HOST
#endif

bool spi_init_bus(pinnum_t sck_pin, pinnum_t miso_pin, pinnum_t mosi_pin, bool dma) {
// Start the SPI bus with the pins defined here. Once it has been started,
// those pins "stick" and subsequent attempts to restart it with defaults
Expand All @@ -22,7 +27,7 @@ bool spi_init_bus(pinnum_t sck_pin, pinnum_t miso_pin, pinnum_t mosi_pin, bool d
};

// Depends on the chip variant
return !spi_bus_initialize(HSPI_HOST, &bus_cfg, dma ? SPI_DMA_CH1 : SPI_DMA_DISABLED);
return !spi_bus_initialize(HSPI_HOST, &bus_cfg, dma ? SPI_DMA_CH_AUTO : SPI_DMA_DISABLED);
}

void spi_deinit_bus() {
Expand Down
83 changes: 3 additions & 80 deletions FluidNC/esp32/tmc_spi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,91 +36,14 @@
// with SCK, MOSI, and MISO pins assigned, via SPIBus.cpp

#include "src/Config.h"
#include "esp32/tmc_spi_support.h"
#include <TMCStepper.h> // https://github.com/teemuatlut/TMCStepper

#include "hal/spi_ll.h"

spi_dev_t* hw = SPI_LL_GET_HW(HSPI_HOST);

static spi_ll_clock_val_t clk_reg_val = 0;

// Establish the SPI bus configuration needed for TMC device access
// This should be done one before every TMC read or write operation,
// to reconfigure the bus from whatever mode the SD card driver used.
static void tmc_spi_bus_setup() {
#if 0
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->miso_io_num], PIN_FUNC_GPIO);
gpio_set_direction(bus_config->miso_io_num, GPIO_MODE_INPUT);
gpio_matrix_out(bus_config->miso_io_num, io_signal[host].spiq_out, false, false);
gpio_matrix_in(bus_config->miso_io_num, io_signal[host].spiq_in, false);
#endif

if (clk_reg_val == 0) {
spi_ll_master_cal_clock(SPI_LL_PERIPH_CLK_FREQ, 2000000, 128, &clk_reg_val);
}
spi_ll_master_set_clock_by_reg(hw, &clk_reg_val);

spi_ll_master_init(hw);
spi_ll_master_set_mode(hw, 3);
spi_ll_set_half_duplex(hw, false);

spi_ll_master_set_line_mode(hw, { 1, 1, 1 }); // Single-line transfers; not DIO or QIO
}

// Perform a full-duplex transfer from out/out_bitlen to in/in_bitlen
// If in_bitlen is 0, the input data will be ignored
static void tmc_spi_transfer_data(uint8_t* out, int out_bitlen, uint8_t* in, int in_bitlen) {
spi_ll_set_mosi_bitlen(hw, out_bitlen);

spi_ll_set_miso_bitlen(hw, in_bitlen);

spi_ll_set_addr_bitlen(hw, 0);
spi_ll_set_command_bitlen(hw, 0);

spi_ll_write_buffer(hw, out, out_bitlen);
spi_ll_enable_mosi(hw, 1);
if (in_bitlen) {
spi_ll_enable_miso(hw, 1);
}

spi_ll_clear_int_stat(hw);
spi_ll_master_user_start(hw);
while (!spi_ll_usr_is_done(hw)) {}

spi_ll_read_buffer(hw, in, in_bitlen); // No-op if in_bitlen is 0
}

// Do a single 5-byte (reg# + data) access to a TMC register,
// accounting for the number of TMC devices (index) daisy-chained
// before the target device. For reads, this is the first register
// access that latches the register data into the output register.
static void tmc_spi_rw_reg(uint8_t cmd, uint32_t data, int index) {
int before = index > 0 ? index - 1 : 0;

const size_t packetLen = 5;
size_t dummy_out_bytes = before * packetLen;
size_t total_bytes = (before + 1) * packetLen;
size_t total_bits = total_bytes * 8;

uint8_t out[total_bytes] = { 0 };

// The data always starts at the beginning of the buffer then
// the trailing 0 bytes will push it through the chain to the
// target chip.
out[0] = cmd;
out[1] = data >> 24;
out[2] = data >> 16;
out[3] = data >> 8;
out[4] = data >> 0;

tmc_spi_transfer_data(out, total_bits, NULL, 0);
}

// Replace the library's weak definition of TMC2130Stepper::write()
// This is executed in the object context so it has access to class
// data such as the CS pin that switchCSpin() uses
void TMC2130Stepper::write(uint8_t reg, uint32_t data) {
log_verbose("TMC reg 0x" << String(reg, 16) << " write 0x" << String(data, 16));
log_verbose("TMC reg 0x" << to_hex(reg) << " write 0x" << to_hex(data));
tmc_spi_bus_setup();

switchCSpin(0);
Expand Down Expand Up @@ -165,7 +88,7 @@ uint32_t TMC2130Stepper::read(uint8_t reg) {
data += (uint32_t)in[dummy_in_bytes + 4];
switchCSpin(1);

log_verbose("TMC reg 0x" << String(reg, 16) << " read 0x" << String(data, 16) << " status 0x" << String(status, 16));
log_verbose("TMC reg 0x" << to_hex(reg) << " read 0x" << to_hex(data) << " status 0x" << to_hex(status));

return data;
}
93 changes: 93 additions & 0 deletions FluidNC/esp32/tmc_spi_support.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Copyright (c) 2022 Mitch Bradley
// Use of this source code is governed by a GPLv3 license that can be found in the LICENSE file.

// C support routines for tmc_spi.cpp . These routines must be complied
// by a C compiler instead of a C++ compiler because of a problem in the
// ESP32_S3 version of esp_addr.h . It defines a FLAG_ATTR() macro in a
// way that causes compiler error on spi_ll.h

#include "hal/spi_ll.h"

#include <sdkconfig.h>
#ifdef CONFIG_IDF_TARGET_ESP32S3
# define HSPI_HOST SPI2_HOST
# define SPI2 GPSPI2
#endif

spi_dev_t* hw = &SPI2;

static spi_ll_clock_val_t clk_reg_val = 0;

// Establish the SPI bus configuration needed for TMC device access
// This should be done one before every TMC read or write operation,
// to reconfigure the bus from whatever mode the SD card driver used.
void tmc_spi_bus_setup() {
#if 0
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->miso_io_num], PIN_FUNC_GPIO);
gpio_set_direction(bus_config->miso_io_num, GPIO_MODE_INPUT);
gpio_matrix_out(bus_config->miso_io_num, io_signal[host].spiq_out, false, false);
gpio_matrix_in(bus_config->miso_io_num, io_signal[host].spiq_in, false);
#endif

if (clk_reg_val == 0) {
spi_ll_master_cal_clock(SPI_LL_PERIPH_CLK_FREQ, 2000000, 128, &clk_reg_val);
}
spi_ll_master_set_clock_by_reg(hw, &clk_reg_val);

spi_ll_master_init(hw);
spi_ll_master_set_mode(hw, 3);
spi_ll_set_half_duplex(hw, false);

spi_line_mode_t mode = { 1, 1, 1 };
spi_ll_master_set_line_mode(hw, mode); // Single-line transfers; not DIO or QIO
}

// Perform a full-duplex transfer from out/out_bitlen to in/in_bitlen
// If in_bitlen is 0, the input data will be ignored
void tmc_spi_transfer_data(uint8_t* out, int out_bitlen, uint8_t* in, int in_bitlen) {
spi_ll_set_mosi_bitlen(hw, out_bitlen);

spi_ll_set_miso_bitlen(hw, in_bitlen);

spi_ll_set_addr_bitlen(hw, 0);
spi_ll_set_command_bitlen(hw, 0);

spi_ll_write_buffer(hw, out, out_bitlen);
spi_ll_enable_mosi(hw, 1);
if (in_bitlen) {
spi_ll_enable_miso(hw, 1);
}

spi_ll_clear_int_stat(hw);
spi_ll_master_user_start(hw);
while (!spi_ll_usr_is_done(hw)) {}

spi_ll_read_buffer(hw, in, in_bitlen); // No-op if in_bitlen is 0
}

// Do a single 5-byte (reg# + data) access to a TMC register,
// accounting for the number of TMC devices (index) daisy-chained
// before the target device. For reads, this is the first register
// access that latches the register data into the output register.
void tmc_spi_rw_reg(uint8_t cmd, uint32_t data, int index) {
int before = index > 0 ? index - 1 : 0;

const size_t packetLen = 5;
size_t dummy_out_bytes = before * packetLen;
size_t total_bytes = (before + 1) * packetLen;
size_t total_bits = total_bytes * 8;

uint8_t out[total_bytes];

// The data always starts at the beginning of the buffer then
// the trailing 0 bytes will push it through the chain to the
// target chip.
out[0] = cmd;
out[1] = data >> 24;
out[2] = data >> 16;
out[3] = data >> 8;
out[4] = data >> 0;
memset(&out[5], 0, total_bytes - 5);

tmc_spi_transfer_data(out, total_bits, NULL, 0);
}
16 changes: 16 additions & 0 deletions FluidNC/esp32/tmc_spi_support.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) 2022 Mitch Bradley
// Use of this source code is governed by a GPLv3 license that can be found in the LICENSE file.

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

void tmc_spi_bus_setup();
void tmc_spi_transfer_data(uint8_t* out, int out_bitlen, uint8_t* in, int in_bitlen);
void tmc_spi_rw_reg(uint8_t cmd, uint32_t data, int index);

#ifdef __cplusplus
}
#endif
38 changes: 32 additions & 6 deletions FluidNC/esp32/wdt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,42 @@
#include <freertos/FreeRTOS.h>
#include "src/Config.h"

void enable_core0_WDT() {
static TaskHandle_t wdt_task_handle = nullptr;

static void get_wdt_task_handle() {
TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0);
if (idle_0 == NULL || esp_task_wdt_add(idle_0) != ESP_OK) {
log_error("Failed to add Core 0 IDLE task to WDT");
esp_err_t err;
err = esp_task_wdt_status(idle_0);
switch (err) {
case ESP_OK:
wdt_task_handle = idle_0;
break;
case ESP_ERR_NOT_FOUND:
wdt_task_handle = nullptr;
return;
case ESP_ERR_INVALID_STATE:
wdt_task_handle = nullptr;
return;
}
}

void enable_core0_WDT() {
if (!wdt_task_handle) {
return;
}
esp_err_t err;
if ((err = esp_task_wdt_add(wdt_task_handle)) != ESP_OK) {
log_error("Failed to add Core 0 IDLE task to WDT " << err);
}
}

void disable_core0_WDT() {
TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0);
if (idle_0 == NULL || esp_task_wdt_delete(idle_0) != ESP_OK) {
log_error("Failed to remove Core 0 IDLE task from WDT");
get_wdt_task_handle();
if (!wdt_task_handle) {
return;
}
esp_err_t err;
if ((err = esp_task_wdt_delete(wdt_task_handle)) != ESP_OK) {
log_error("Failed to remove Core 0 IDLE task from WDT " << err);
}
}
9 changes: 9 additions & 0 deletions FluidNC/include/Driver/delay_usecs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include <cstdint>

void timing_init();
void spinUntil(int32_t endTicks);
void delay_us(int32_t us);

int32_t usToCpuTicks(int32_t us);
int32_t usToEndTicks(int32_t us);
int32_t getCpuTicks();
Loading

0 comments on commit 196788a

Please sign in to comment.