summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorroot <root@lumpy.lan>2021-11-30 00:24:43 +0000
committerroot <root@lumpy.lan>2021-11-30 00:24:43 +0000
commit869118f74612829db47d0d681cee5b4af937b16f (patch)
tree9195fea1c0d6a002704ba2f452a4ec131923da80
parent440039cb23f786573940ec1eafa665f9de561eae (diff)
downloadmetric_clock-master.tar.gz
metric_clock-master.tar.bz2
metric_clock-master.zip
tmc2209 first cutHEADmaster
-rw-r--r--stm32/app/Makefile4
-rw-r--r--stm32/app/asm_fns.h5
-rw-r--r--stm32/app/board.h16
-rw-r--r--stm32/app/events.c5
-rw-r--r--stm32/app/gen/c.c109
-rw-r--r--stm32/app/hands.c38
-rw-r--r--stm32/app/leds.c3
-rw-r--r--stm32/app/motor.c295
-rw-r--r--stm32/app/project.h3
-rw-r--r--stm32/app/prototypes.h12
-rw-r--r--stm32/app/ring.h3
-rw-r--r--stm32/app/rtc.c2
-rw-r--r--stm32/app/time_fn.h4
-rw-r--r--stm32/app/tmc2209.c153
-rw-r--r--stm32/app/tmc2209.h286
-rw-r--r--stm32/app/usart.c83
16 files changed, 835 insertions, 186 deletions
diff --git a/stm32/app/Makefile b/stm32/app/Makefile
index 62a13cc..51756dc 100644
--- a/stm32/app/Makefile
+++ b/stm32/app/Makefile
@@ -25,8 +25,8 @@ LDLIBS+=-lm
V=1
default: ${PROG}.elf
-CSRCS= main.c cdcacm.c dfu.c ring.c usart.c ticker.c dummy_kb.c usb.c rtc.c time_fn.c events.c hands.c motor.c leds.c
-HSRCS = project.h
+CSRCS= main.c cdcacm.c dfu.c ring.c usart.c ticker.c dummy_kb.c usb.c rtc.c time_fn.c events.c hands.c motor.c leds.c tmc2209.c
+HSRCS = project.h asm_fns.h board.h pins.h ring.h time_fn.h tmc2209.h
BINARY = ${PROG}
diff --git a/stm32/app/asm_fns.h b/stm32/app/asm_fns.h
index b0d10d9..93e2a76 100644
--- a/stm32/app/asm_fns.h
+++ b/stm32/app/asm_fns.h
@@ -1,4 +1,5 @@
-static inline void compiler_mb(void) {
-asm volatile ("");
+static inline void compiler_mb (void)
+{
+ asm volatile ("");
}
diff --git a/stm32/app/board.h b/stm32/app/board.h
index 29d465d..1ff91ff 100644
--- a/stm32/app/board.h
+++ b/stm32/app/board.h
@@ -7,9 +7,21 @@
#define USART1_TX GPIO_USART1_TX
-#define USART1_TX_PORT GPIOA
+#define USART1_TX_PORT GPIO_BANK_USART1_TX
#define USART1_RX GPIO_USART1_RX
-#define USART1_RX_PORT GPIOA
+#define USART1_RX_PORT GPIO_BANK_USART1_RX
+
+#define USART2_TX GPIO_USART2_TX
+#define USART2_TX_PORT GPIO_BANK_USART2_TX
+
+#define USART2_RX GPIO_USART2_RX
+#define USART2_RX_PORT GPIO_BANK_USART2_RX
+
+#define USART3_TX GPIO_USART3_TX
+#define USART3_TX_PORT GPIO_BANK_USART3_TX
+
+#define USART3_RX GPIO_USART3_RX
+#define USART3_RX_PORT GPIO_BANK_USART3_RX
diff --git a/stm32/app/events.c b/stm32/app/events.c
index 2ad9b47..03b6e2a 100644
--- a/stm32/app/events.c
+++ b/stm32/app/events.c
@@ -8,6 +8,7 @@
// shamelessly stolen from Meeus Astronmical Algorithms Chapter 27 table 27.B
// chapter 25 is probably more tractable, but this is easier to code up
+# if 0
static double mean_vernal_equinox (unsigned year)
{
double y = year;
@@ -23,6 +24,7 @@ static double mean_summer_solstice (unsigned year)
y *= 0.001;
return 2451716.56767 + 365241.62603 * y + 0.00325 * (y * y) + 0.00888 * (y * y * y) - 0.00030 * (y * y * y * y);
}
+#endif
static double mean_autumnal_equinox (unsigned year)
{
@@ -32,6 +34,7 @@ static double mean_autumnal_equinox (unsigned year)
return 2451810.21715 + 365242.01767 * y - 0.11575 * (y * y) + 0.00337 * (y * y * y) + 0.00078 * (y * y * y * y);
}
+#if 0
static double mean_winter_solstice (unsigned year)
{
double y = year;
@@ -39,7 +42,7 @@ static double mean_winter_solstice (unsigned year)
y *= 0.001;
return 2451900.05952 + 365242.74049 * y - 0.06223 * (y * y) - 0.00823 * (y * y * y) + 0.00032 * (y * y * y * y);
}
-
+#endif
static double orbital_periodic_terms (double t)
{
diff --git a/stm32/app/gen/c.c b/stm32/app/gen/c.c
new file mode 100644
index 0000000..56e7237
--- /dev/null
+++ b/stm32/app/gen/c.c
@@ -0,0 +1,109 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+uint8_t crc_table[256];
+
+uint8_t flip_byte (uint8_t value)
+{
+ value = ((value >> 1) & 0x55) | ((value & 0x55) << 1);
+ value = ((value >> 2) & 0x33) | ((value & 0x33) << 2);
+ value = ((value >> 4) & 0x0F) | ((value & 0x0F) << 4);
+ return value;
+}
+
+
+uint8_t
+crc8 (uint8_t * data, size_t len)
+{
+ unsigned i, j;
+ uint8_t crc = 0, b;
+
+ for (i = 0; i < len; ++i, ++data)
+ {
+
+ b = *data;
+ for (j = 0; j < 8; j++)
+ {
+ if ((crc >> 7) ^ (b & 1))
+ {
+ crc = (crc << 1) ^ 7;
+ }
+ else
+ {
+ crc = crc << 1;
+ }
+
+ b >>= 1;
+ }
+ }
+ return crc;
+}
+
+void
+make_table (void)
+{
+ unsigned i;
+ unsigned j;
+ uint8_t b;
+
+ for (i = 0; i < 256; ++i)
+ {
+ b = i;
+ for (j = 0; j < 8; j++)
+ {
+
+ if (b & 1)
+ {
+ b = (b >> 1 ) ^ 0xe0;
+ }
+ else
+ {
+ b = b >> 1;
+ }
+
+ }
+ crc_table[i] = b;
+ }
+}
+
+uint8_t
+crc8_better (uint8_t * data, size_t len)
+{
+ uint8_t crc = 0;
+ unsigned i;
+
+ for (i = 0; i < len; i++, data++)
+ {
+ crc = crc_table[crc ^ *data];
+ }
+
+ return flip_byte(crc);
+}
+
+
+
+int
+main (int argc, char *argv[])
+{
+ uint8_t fish[4] = "\5\0\1\301";
+ size_t l;
+
+ make_table ();
+
+ for (l=0;l<256;++l) {
+ printf("0x%02x, ",crc_table[l]);
+ }
+
+ printf("\n");
+
+ for (l=0;l<4;++l ) {
+ printf ("%u %02x %02x %02x\n",(unsigned)l, crc8 (fish, l), crc8_better (fish, l), fish[l]);
+ }
+
+
+
+ return 0;
+}
+
+
diff --git a/stm32/app/hands.c b/stm32/app/hands.c
index f1543ac..4eda256 100644
--- a/stm32/app/hands.c
+++ b/stm32/app/hands.c
@@ -70,8 +70,6 @@ void hands_tick (void)
EPOCH e;
UTC u;
MTIME m;
- static unsigned old_pos[HANDS];
- unsigned i, p;
static uint32_t last;
@@ -87,18 +85,19 @@ void hands_tick (void)
u = time_epoch_to_utc (e);
m = time_to_metric (e, u);
-
#if 0
hands_pos[0] = calc_hour_pos (&m);
-if ((e.s & 31) <5) {
- hands_pos[1] =hands_pos[0];
-} else {
- hands_pos[1] = calc_minute_pos (&m);
-}
+ if ((e.s & 31) < 5)
+ hands_pos[1] = hands_pos[0];
+
+ else
+ hands_pos[1] = calc_minute_pos (&m);
+
#endif
hands_pos[0] = calc_second_pos (&m);
+ hands_pos[1] = calc_hour_pos (&m);
hands_pos[1] = calc_minute_pos (&m);
@@ -106,18 +105,23 @@ if ((e.s & 31) <5) {
hands_ready = 1;
#if 0
- for (i = 0, p = 0; i < HANDS; ++i) {
- if (hands_pos[i] != old_pos[i]) p++;
+ {
+ static unsigned old_pos[HANDS];
+ unsigned i;
- old_pos[i] = hands_pos[i];
+ for (i = 0, p = 0; i < HANDS; ++i) {
+ if (hands_pos[i] != old_pos[i]) p++;
- }
+ old_pos[i] = hands_pos[i];
+
+ }
- if (p) {
- printf("Epoch %d.%09d\r\n",(unsigned) e.s,(unsigned) e.ns);
- time_print_utc ("UTC: ", &u, NULL);
- time_print_metric ("Metric: ", &m, NULL);
- printf ("Hands: hour %4d/%4d min %4d/%4d\r\n", hands_pos[0], MOTOR_STEPS, hands_pos[1], MOTOR_STEPS);
+ if (p) {
+ printf ("Epoch %d.%09d\r\n", (unsigned) e.s, (unsigned) e.ns);
+ time_print_utc ("UTC: ", &u, NULL);
+ time_print_metric ("Metric: ", &m, NULL);
+ printf ("Hands: hour %4d/%4d min %4d/%4d\r\n", hands_pos[0], MOTOR_STEPS, hands_pos[1], MOTOR_STEPS);
+ }
}
#endif
diff --git a/stm32/app/leds.c b/stm32/app/leds.c
index b02e584..8faff1f 100644
--- a/stm32/app/leds.c
+++ b/stm32/app/leds.c
@@ -43,6 +43,7 @@ static void metric_pll (void)
ttg = 864 - (unsigned)v;
}
+#if 0
static void customary_pll (void)
{
static uint32_t last;
@@ -66,7 +67,7 @@ static void customary_pll (void)
// printf("C: %9u\r\n",(unsigned ) (e.ns/1000000));
}
-
+#endif
void led_tick (void)
diff --git a/stm32/app/motor.c b/stm32/app/motor.c
index 621812d..b599896 100644
--- a/stm32/app/motor.c
+++ b/stm32/app/motor.c
@@ -2,7 +2,7 @@
static unsigned motor_pos[HANDS];
-static unsigned off[HANDS];
+//static unsigned off[HANDS];
#ifdef HBRIDGE
@@ -17,25 +17,25 @@ static unsigned off[HANDS];
#else
-#define M1_DIR GPIO0
-#define M1_DIR_PORT GPIOB
-#define M1_STEP GPIO1
-#define M1_STEP_PORT GPIOB
-#define M1_EN GPIO2
-#define M1_EN_PORT GPIOB
-
-#define M2_DIR GPIO10
-#define M2_DIR_PORT GPIOC
-#define M2_STEP GPIO11
-#define M2_STEP_PORT GPIOC
-#define M2_EN GPIO12
-#define M2_EN_PORT GPIOC
-
-
-#define ADJUST_CCW GPIO0
-#define ADJUST_CCW_PORT GPIOC
-#define ADJUST_CW GPIO1
-#define ADJUST_CW_PORT GPIOC
+#define M1_DIR GPIO0
+#define M1_DIR_PORT GPIOB
+#define M1_STEP GPIO1
+#define M1_STEP_PORT GPIOB
+#define M1_EN GPIO2
+#define M1_EN_PORT GPIOB
+
+#define M2_DIR GPIO10
+#define M2_DIR_PORT GPIOC
+#define M2_STEP GPIO11
+#define M2_STEP_PORT GPIOC
+#define M2_EN GPIO12
+#define M2_EN_PORT GPIOC
+
+
+#define ADJUST_CCW GPIO0
+#define ADJUST_CCW_PORT GPIOC
+#define ADJUST_CW GPIO1
+#define ADJUST_CW_PORT GPIOC
#endif
@@ -46,18 +46,18 @@ static void coils (unsigned m, int a, int b, int c, int d)
if (!m) return;
- c^=d;
- d^=c;
- c^=d;
+ c ^= d;
+ d ^= c;
+ c ^= d;
#if 0
-a^=c;
-c^=a;
-a^=c;
+ a ^= c;
+ c ^= a;
+ a ^= c;
-b^=d;
-d^=b;
-b^=d;
+ b ^= d;
+ d ^= b;
+ b ^= d;
#endif
@@ -96,6 +96,7 @@ static void step (unsigned m, int d)
#ifdef HBRIDGE
#if 0
+
// full step
switch (s & 3) {
case 0:
@@ -114,63 +115,70 @@ static void step (unsigned m, int d)
coils (m, 1, 0, 0, 1);
break;
}
+
#endif
#if 0
-// half step
-coils (m, !! ((s + 1) & 4), !! ((s + 6) & 4), !! ((s + 4) & 4), !! ((s + 7) & 4));
+ // half step
+ coils (m, !! ((s + 1) & 4), !! ((s + 6) & 4), !! ((s + 4) & 4), !! ((s + 7) & 4));
#endif
#if 1
-//60deg phase
-
-switch(s%6) {
-case 0:
-coils(m,0,0,1,0);
-break;
-case 1:
-coils(m,1,0,1,0);
-break;
-case 2:
-coils(m,1,0,0,0);
-break;
-case 3:
-coils(m,0,0,0,1);
-break;
-case 4:
-coils(m,0,1,0,1);
-break;
-case 5:
-coils(m,0,1,0,0);
-break;
-}
+ //60deg phase
+
+ switch (s % 6) {
+ case 0:
+ coils (m, 0, 0, 1, 0);
+ break;
+
+ case 1:
+ coils (m, 1, 0, 1, 0);
+ break;
+
+ case 2:
+ coils (m, 1, 0, 0, 0);
+ break;
+
+ case 3:
+ coils (m, 0, 0, 0, 1);
+ break;
+
+ case 4:
+ coils (m, 0, 1, 0, 1);
+ break;
+
+ case 5:
+ coils (m, 0, 1, 0, 0);
+ break;
+ }
+
#endif
#else
-if (d<0) {
-if (!m) {
- SET(M1_DIR);
- SET(M1_STEP);
- delay_us(1);
- CLEAR(M1_STEP);
-} else {
- SET(M2_DIR);
- SET(M2_STEP);
- delay_us(1);
- CLEAR(M2_STEP);
-}
-} else if (d>0) {
-if (!m) {
- CLEAR(M1_DIR);
- SET(M1_STEP);
- delay_us(1);
- CLEAR(M1_STEP);
-} else {
- CLEAR(M2_DIR);
- SET(M2_STEP);
- delay_us(1);
- CLEAR(M2_STEP);
-}
-}
+ if (d < 0) {
+ if (!m) {
+ SET (M1_DIR);
+ SET (M1_STEP);
+ delay_us (1);
+ CLEAR (M1_STEP);
+ } else {
+ SET (M2_DIR);
+ SET (M2_STEP);
+ delay_us (1);
+ CLEAR (M2_STEP);
+ }
+ } else if (d > 0) {
+ if (!m) {
+ CLEAR (M1_DIR);
+ SET (M1_STEP);
+ delay_us (1);
+ CLEAR (M1_STEP);
+ } else {
+ CLEAR (M2_DIR);
+ SET (M2_STEP);
+ delay_us (1);
+ CLEAR (M2_STEP);
+ }
+ }
#endif
@@ -188,13 +196,12 @@ if (!m) {
void motor_tick (void)
{
- static uint32_t last,blast;
+ static uint32_t blast;
unsigned i, d;
- static unsigned adjusting =0;
- static unsigned zero=8000;
+ static unsigned adjusting = 0;
+ static unsigned zero = 8000;
unsigned hp[2];
- static unsigned s;
@@ -205,84 +212,86 @@ void motor_tick (void)
if ((ticks - blast) > 1000) {
- if (!GET(ADJUST_CCW)) {
- adjusting=8000;
- }
+ if (!GET (ADJUST_CCW))
+ adjusting = 8000;
- if (!GET(ADJUST_CW)) {
- zero=8000;
- }
- blast=ticks;
+ if (!GET (ADJUST_CW))
+ zero = 8000;
+
+ blast = ticks;
}
#ifndef HBRIDGE
- if (adjusting) {
- adjusting--;
-
- if (adjusting) {
- SET(M1_EN);
- SET(M2_EN);
- } else {
- CLEAR(M1_EN);
- CLEAR(M2_EN);
- }
-
- motor_pos[0]=motor_pos[1]=0;
- step(0,0);
- step(1,0);
-
- return;
+
+ if (adjusting) {
+ adjusting--;
+
+ if (adjusting) {
+ SET (M1_EN);
+ SET (M2_EN);
+ } else {
+ CLEAR (M1_EN);
+ CLEAR (M2_EN);
}
+
+ motor_pos[0] = motor_pos[1] = 0;
+ step (0, 0);
+ step (1, 0);
+
+ return;
+ }
+
#endif
-
+
if (zero || !hands_ready) {
- if (zero) zero--;
- hp[0]=0;
- hp[1]=0;
+ if (zero) zero--;
+
+ hp[0] = 0;
+ hp[1] = 0;
} else {
- hp[0]=hands_pos[0];
- hp[1]=hands_pos[1];
+ hp[0] = hands_pos[0];
+ hp[1] = hands_pos[1];
}
//printf("HANDS: %d -> %d %d -> %d\r\n",hands_pos[0],motor_pos[0],hands_pos[1],motor_pos[1]);
#if 0
-{
-unsigned static r=0;
-r++;
-r%=6000;
+ {
+ unsigned static r = 0;
+ r++;
+ r %= 6000;
-if (r<3000) {
-hp[0]=0;
-}
-}
+ if (r < 3000)
+ hp[0] = 0;
+ }
#endif
-{ unsigned static s=0;
+ {
+ static unsigned s = 0;
-if (!s) {
- printf("%4d %4d hp[0]=%6d mp[0]=%6d hp[1]=%6d mp[1]=%6d\r\n",
- zero,adjusting, hp[0],motor_pos[0],hp[1],motor_pos[1]);
-}
+ if (!s) {
+ printf ("%4d %4d hp[0]=%6d mp[0]=%6d hp[1]=%6d mp[1]=%6d\r\n",
+ zero, adjusting, hp[0], motor_pos[0], hp[1], motor_pos[1]);
+ }
-s++;
-s%=500;
-}
+ s++;
+ s %= 500;
+ }
for (i = 0; i < HANDS; ++i) {
d = MOTOR_STEPS;
- d+=hp[i];
+ d += hp[i];
d -= motor_pos[i];
d %= MOTOR_STEPS;
@@ -305,8 +314,8 @@ s%=500;
void motor_init (void)
{
- MAP_INPUT_PU(ADJUST_CCW);
- MAP_INPUT_PU(ADJUST_CW);
+ MAP_INPUT_PU (ADJUST_CCW);
+ MAP_INPUT_PU (ADJUST_CW);
#ifdef HBRIDGE
MAP_OUTPUT_PP (M1_A);
@@ -325,18 +334,24 @@ void motor_init (void)
MAP_OUTPUT_PP (M2_DIR);
MAP_OUTPUT_PP (M2_STEP);
- SET(M1_EN);
- CLEAR(M1_STEP);
- CLEAR(M1_DIR);
- delay_us(2);
- CLEAR(M1_EN);
+ SET (M1_EN);
+ CLEAR (M1_STEP);
+ CLEAR (M1_DIR);
+
+
+ SET (M2_EN);
+ CLEAR (M2_STEP);
+ CLEAR (M2_DIR);
+
+
+ if (tmc2209_init()) {
+ printf ("Motor controllers failed to init, not enabling drive\n");
+ return;
+ }
+ CLEAR (M1_EN);
+ CLEAR (M2_EN);
- SET(M2_EN);
- CLEAR(M2_STEP);
- CLEAR(M2_DIR);
- delay_us(2);
- CLEAR(M2_EN);
#endif
diff --git a/stm32/app/project.h b/stm32/app/project.h
index 471683b..a6239b9 100644
--- a/stm32/app/project.h
+++ b/stm32/app/project.h
@@ -37,7 +37,7 @@
#define HANDS 2
//#define MOTOR_STEPS (1080 * 2)
//#define MOTOR_STEPS (720 )
-#define USTEP 16
+#define USTEP 16
#define MOTOR_STEPS (720*USTEP)
#define MOTOR_PHASES 6
@@ -46,6 +46,7 @@
#include "pins.h"
#include "time_fn.h"
#include "asm_fns.h"
+#include "tmc2209.h"
#include "prototypes.h"
diff --git a/stm32/app/prototypes.h b/stm32/app/prototypes.h
index 18106bc..2e9f4b7 100644
--- a/stm32/app/prototypes.h
+++ b/stm32/app/prototypes.h
@@ -23,11 +23,12 @@ extern int ring_empty(ring_t *r);
extern int ring_read_byte(ring_t *r, uint8_t *c);
extern int ring_write(ring_t *r, uint8_t *buf, size_t len);
/* usart.c */
-extern ring_t usart_rx_ring;
-extern ring_t usart_tx_ring;
+extern ring_t usart1_rx_ring;
+extern ring_t usart1_tx_ring;
extern void usart1_isr(void);
-extern void usart_kick(void);
+extern void usart1_kick(void);
extern int _write(int file, char *ptr, int len);
+extern int usart_transact(uint32_t u, void *_b, size_t txl, size_t rxl);
extern void usart_init(void);
/* ticker.c */
extern volatile uint32_t ticks;
@@ -81,3 +82,8 @@ extern void motor_init(void);
/* leds.c */
extern void led_tick(void);
extern void leds_init(void);
+/* tmc2209.c */
+extern int tmc2209_write(uint32_t uart, uint8_t tmc_addr, uint8_t reg, uint32_t value);
+extern int tmc2209_read(uint32_t uart, uint8_t tmc_addr, uint8_t reg, uint32_t *value);
+extern int tmc2209_config(uint32_t u);
+extern int tmc2209_init(void);
diff --git a/stm32/app/ring.h b/stm32/app/ring.h
index ba8887b..1eae65b 100644
--- a/stm32/app/ring.h
+++ b/stm32/app/ring.h
@@ -1,5 +1,4 @@
-typedef struct ring
-{
+typedef struct ring {
uint8_t *data;
size_t size;
size_t write;
diff --git a/stm32/app/rtc.c b/stm32/app/rtc.c
index c20bb8d..80a0664 100644
--- a/stm32/app/rtc.c
+++ b/stm32/app/rtc.c
@@ -155,7 +155,7 @@ void rtc_init (void)
rtc_half = BKP_DR7;
#if 1
- rtc_offset.s = 1637490753 + 46850+ 48565+85980;
+ rtc_offset.s = 1637490753 + 46850 + 48565 + 85980;
rtc_offset.ns = 498866999;
bkp_write_off (rtc_offset);
#endif
diff --git a/stm32/app/time_fn.h b/stm32/app/time_fn.h
index 0775a0f..5ed3e91 100644
--- a/stm32/app/time_fn.h
+++ b/stm32/app/time_fn.h
@@ -18,8 +18,8 @@ typedef struct {
typedef struct {
- unsigned days;
- double ra;
+ unsigned days;
+ double ra;
} RA;
typedef struct {
diff --git a/stm32/app/tmc2209.c b/stm32/app/tmc2209.c
new file mode 100644
index 0000000..ae7407c
--- /dev/null
+++ b/stm32/app/tmc2209.c
@@ -0,0 +1,153 @@
+#include "project.h"
+
+#define TMC_WRITE_BIT 0x80
+
+static const uint8_t tmc2209_crc_table[256] = {
+ 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75, 0x0e, 0x9f, 0xed, 0x7c,
+ 0x09, 0x98, 0xea, 0x7b, 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
+ 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67, 0x38, 0xa9, 0xdb, 0x4a,
+ 0x3f, 0xae, 0xdc, 0x4d, 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
+ 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51, 0x2a, 0xbb, 0xc9, 0x58,
+ 0x2d, 0xbc, 0xce, 0x5f, 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
+ 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b, 0x6c, 0xfd, 0x8f, 0x1e,
+ 0x6b, 0xfa, 0x88, 0x19, 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
+ 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d, 0x46, 0xd7, 0xa5, 0x34,
+ 0x41, 0xd0, 0xa2, 0x33, 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
+ 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f, 0xe0, 0x71, 0x03, 0x92,
+ 0xe7, 0x76, 0x04, 0x95, 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
+ 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89, 0xf2, 0x63, 0x11, 0x80,
+ 0xf5, 0x64, 0x16, 0x87, 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
+ 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3, 0xc4, 0x55, 0x27, 0xb6,
+ 0xc3, 0x52, 0x20, 0xb1, 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
+ 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5, 0x9e, 0x0f, 0x7d, 0xec,
+ 0x99, 0x08, 0x7a, 0xeb, 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
+ 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7, 0xa8, 0x39, 0x4b, 0xda,
+ 0xaf, 0x3e, 0x4c, 0xdd, 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
+ 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1, 0xba, 0x2b, 0x59, 0xc8,
+ 0xbd, 0x2c, 0x5e, 0xcf
+};
+
+
+static uint8_t swab (uint8_t b)
+{
+ b = ((b >> 1) & 0x55) | ((b & 0x55) << 1);
+ b = ((b >> 2) & 0x33) | ((b & 0x33) << 2);
+ b = ((b >> 4) & 0x0F) | ((b & 0x0F) << 4);
+ return b;
+}
+
+static uint8_t tmc2209_crc8 (uint8_t *data, size_t len)
+{
+ uint8_t crc = 0;
+ unsigned i;
+
+ for (i = 0; i < len; i++, data++)
+ crc = tmc2209_crc_table[crc ^ *data];
+
+ return swab (crc);
+}
+
+
+int tmc2209_write (uint32_t uart, uint8_t tmc_addr, uint8_t reg, uint32_t value)
+{
+ uint8_t data[8];
+
+ data[0] = 0x05;
+ data[1] = tmc_addr;
+ data[2] = reg | TMC_WRITE_BIT;
+ data[3] = (value >> 24) & 0xFF;
+ data[4] = (value >> 16) & 0xFF;
+ data[5] = (value >> 8) & 0xFF;
+ data[6] = (value) & 0xFF;
+ data[7] = tmc2209_crc8 (data, 7);
+
+ return usart_transact (uart, data, sizeof (data), 0);
+}
+
+int tmc2209_read (uint32_t uart, uint8_t tmc_addr, uint8_t reg, uint32_t *value)
+{
+ uint8_t data[8] = { 0 };
+
+ data[0] = 0x05;
+ data[1] = tmc_addr;
+ data[2] = reg;
+ data[3] = tmc2209_crc8 (data, 3);
+
+ if (usart_transact (uart, data, 4, sizeof (data)))
+ return -1;
+
+ // Byte 0: Sync nibble correct?
+ if (data[0] != 0x05)
+ return -1;
+
+ // Byte 1: Master address correct?
+ if (data[1] != 0xFF)
+ return -1;
+
+ // Byte 2: Address correct?
+ if (data[2] != reg)
+ return -1;
+
+ // Byte 7: CRC correct?
+ if (data[7] != tmc2209_crc8 (data, 7))
+ return -1;
+
+ *value = data[3];
+ *value <<= 8;
+ *value |= data[4];
+ *value <<= 8;
+ *value |= data[6];
+ *value <<= 8;
+ *value |= data[7];
+
+
+ return 0;
+}
+
+int tmc2209_config (uint32_t u)
+{
+ uint32_t v;
+
+ if (tmc2209_read (u, 0, TMC2209_IOIN, &v))
+ return -1;
+
+ printf ("TMC2209 version %ld\n", (v & TMC2209_IOIN_VERSION_MASK) >> TMC2209_IOIN_VERSION_SHIFT);
+
+ v = TMC2209_GCONF_PDN_DISABLE_MASK | TMC2209_GCONF_MSTEP_REG_SELECT_MASK;
+
+ if (tmc2209_write (u, 0, TMC2209_GCONF, v))
+ return -1;
+
+ v = TMC2209_IHOLD_IRUN_IHOLDDELAY_MASK;
+
+ if (tmc2209_write (u, 0, TMC2209_IHOLD_IRUN, v))
+ return -1;
+
+ v = TMC2209_TPOWERDOWN_MASK;
+
+ if (tmc2209_write (u, 0, TMC2209_TPOWERDOWN, v))
+ return -1;
+
+
+ v = (5 << TMC2209_CHOPCONF_MRES_SHIFT) | TMC2209_CHOPCONF_INTPOL_MASK;
+
+ if (tmc2209_write (u, 0, TMC2209_CHOPCONF, v))
+ return -1;
+
+
+ return 0;
+}
+
+int tmc2209_init (void)
+{
+
+ if (tmc2209_config (USART2))
+ return -1;
+
+ if (tmc2209_config (USART3))
+ return -1;
+
+ return 0;
+}
+
+
diff --git a/stm32/app/tmc2209.h b/stm32/app/tmc2209.h
new file mode 100644
index 0000000..bfcb95a
--- /dev/null
+++ b/stm32/app/tmc2209.h
@@ -0,0 +1,286 @@
+
+
+#define TMC2209_GCONF 0x00
+
+#define TMC2209_GCONF_I_SCALE_ANALOG_MASK 0x01 // GCONF // I_scale_analog (Reset default=1)
+#define TMC2209_GCONF_I_SCALE_ANALOG_SHIFT 0 // min.: 0, max.: 1, default: 0
+#define TMC2209_GCONF_INTERNAL_RSENSE_MASK 0x02 // GCONF // internal_Rsense (Reset default: OTP)
+#define TMC2209_GCONF_INTERNAL_RSENSE_SHIFT 1 // min.: 0, max.: 1, default: 0
+#define TMC2209_GCONF_EN_SPREADCYCLE_MASK 0x04 // GCONF // en_spreadCycle (Reset default: OTP)
+#define TMC2209_GCONF_EN_SPREADCYCLE_SHIFT 2 // min.: 0, max.: 1, default: 0
+#define TMC2209_GCONF_SHAFT_MASK 0x08 // GCONF // controls motor direction
+#define TMC2209_GCONF_SHAFT_SHIFT 3 // min.: 0, max.: 1, default: 0
+#define TMC2209_GCONF_INDEX_OTPW_MASK 0x10 // GCONF // index_otpw
+#define TMC2209_GCONF_INDEX_OTPW_SHIFT 4 // min.: 0, max.: 1, default: 0
+#define TMC2209_GCONF_INDEX_STEP_MASK 0x20 // GCONF // index_step
+#define TMC2209_GCONF_INDEX_STEP_SHIFT 5 // min.: 0, max.: 1, default: 0
+#define TMC2209_GCONF_PDN_DISABLE_MASK 0x40 // GCONF // pdn_disable
+#define TMC2209_GCONF_PDN_DISABLE_SHIFT 6 // min.: 0, max.: 1, default: 0
+#define TMC2209_GCONF_MSTEP_REG_SELECT_MASK 0x80 // GCONF // mstep_reg_select
+#define TMC2209_GCONF_MSTEP_REG_SELECT_SHIFT 7 // min.: 0, max.: 1, default: 0
+#define TMC2209_GCONF_MULTISTEP_FILT_MASK 0x0100 // GCONF // multistep_filt (Reset default=1)
+#define TMC2209_GCONF_MULTISTEP_FILT_SHIFT 8 // min.: 0, max.: 1, default: 0
+#define TMC2209_GCONF_TEST_MODE_MASK 0x0200 // GCONF // test_mode 0
+#define TMC2209_GCONF_TEST_MODE_SHIFT 9 // min.: 0, max.: 1, default: 0
+#define TMC2209_GCONF_RESET_MASK 0x01 // GSTAT // reset
+#define TMC2209_GCONF_RESET_SHIFT 0 // min.: 0, max.: 1, default: 0
+
+
+
+#define TMC2209_GSTAT 0x01
+
+#define TMC2209_GSTAT_DRV_ERR_MASK 0x02 // GSTAT // drv_err
+#define TMC2209_GSTAT_DRV_ERR_SHIFT 1 // min.: 0, max.: 1, default: 0
+#define TMC2209_GSTAT_UV_CP_MASK 0x04 // GSTAT // uv_cp
+#define TMC2209_GSTAT_UV_CP_SHIFT 2 // min.: 0, max.: 1, default: 0
+
+
+
+#define TMC2209_IFCNT 0x02
+
+#define TMC2209_IFCNT_MASK 0xFF // IFCNT // Interface transmission counter. This register becomes incremented with each successful UART interface write access. Read out to check the serial transmission for lost data. Read accesses do not change the content. The counter wraps around from 255 to 0.
+#define TMC2209_IFCNT_SHIFT 0 // min.: 0, max.: 255, default: 0
+
+
+
+#define TMC2209_SLAVECONF 0x03
+
+#define TMC2209_SLAVECONF_MASK 0x0F00 // SLAVECONF // SENDDELAY for read access (time until reply is sent): 0, 1: 8 bit times 2, 3: 3*8 bit times 4, 5: 5*8 bit times 6, 7: 7*8 bit times 8, 9: 9*8 bit times 10, 11: 11*8 bit times 12, 13: 13*8 bit times 14, 15: 15*8 bit times
+#define TMC2209_SLAVECONF_SHIFT 8 // min.: 0, max.: 15, default: 0
+
+
+
+#define TMC2209_OTP_PROG 0x04
+
+#define TMC2209_OTP_PROG_OTPBIT_MASK 0x07 // OTP_PROG // Selection of OTP bit to be programmed to the selected byte location (n=0..7: programs bit n to a logic 1)
+#define TMC2209_OTP_PROG_OTPBIT_SHIFT 0 // min.: 0, max.: 7, default: 0
+#define TMC2209_OTP_PROG_OTPBYTE_MASK 0x30 // OTP_PROG // Selection of OTP programming location (0, 1 or 2)
+#define TMC2209_OTP_PROG_OTPBYTE_SHIFT 4 // min.: 0, max.: 3, default: 0
+#define TMC2209_OTP_PROG_OTPMAGIC_MASK 0xFF00 // OTP_PROG // Set to 0xBD to enable programming. A programming time of minimum 10ms per bit is recommended (check by reading OTP_READ).
+#define TMC2209_OTP_PROG_OTPMAGIC_SHIFT 8 // min.: 0, max.: 255, default: 0
+
+
+
+#define TMC2209_OTP_READ 0x05
+
+#define TMC2209_OTP_READ_OTP0_BYTE_0_READ_DATA_MASK 0x01 // OTP_READ // to be detailed
+#define TMC2209_OTP_READ_OTP0_BYTE_0_READ_DATA_SHIFT 0 // min.: 0, max.: 255, default: 0
+#define TMC2209_OTP_READ_OTP1_BYTE_1_READ_DATA_MASK 0x02 // OTP_READ // to be detailed
+#define TMC2209_OTP_READ_OTP1_BYTE_1_READ_DATA_SHIFT 8 // min.: 0, max.: 255, default: 0
+#define TMC2209_OTP_READ_OTP2_BYTE_2_READ_DATA_MASK 0x04 // OTP_READ // to be detailed
+#define TMC2209_OTP_READ_OTP2_BYTE_2_READ_DATA_SHIFT 16 // min.: 0, max.: 255, default: 0
+
+
+
+#define TMC2209_IOIN 0x06
+
+#define TMC2209_IOIN_ENN_MASK 0x01 // IOIN //
+#define TMC2209_IOIN_ENN_SHIFT 0 // min.: 0, max.: 1, default: 0
+#define TMC2209_IOIN_MS1_MASK 0x04 // IOIN //
+#define TMC2209_IOIN_MS1_SHIFT 2 // min.: 0, max.: 1, default: 0
+#define TMC2209_IOIN_MS2_MASK 0x08 // IOIN //
+#define TMC2209_IOIN_MS2_SHIFT 3 // min.: 0, max.: 1, default: 0
+#define TMC2209_IOIN_DIAG_MASK 0x10 // IOIN //
+#define TMC2209_IOIN_DIAG_SHIFT 4 // min.: 0, max.: 1, default: 0
+#define TMC2209_IOIN_PDN_UART_MASK 0x40 // IOIN //
+#define TMC2209_IOIN_PDN_UART_SHIFT 6 // min.: 0, max.: 1, default: 0
+#define TMC2209_IOIN_STEP_MASK 0x80 // IOIN //
+#define TMC2209_IOIN_STEP_SHIFT 7 // min.: 0, max.: 1, default: 0
+#define TMC2209_IOIN_SEL_A_MASK 0x0100 // IOIN // Driver type
+#define TMC2209_IOIN_SEL_A_SHIFT 8 // min.: 0, max.: 1, default: 0
+#define TMC2209_IOIN_DIR_MASK 0x0200 // IOIN //
+#define TMC2209_IOIN_DIR_SHIFT 9 // min.: 0, max.: 1, default: 0
+#define TMC2209_IOIN_VERSION_MASK 0xFF000000 // IOIN // VERSION: 0x20=first version of the IC Identical numbers mean full digital compatibility.
+#define TMC2209_IOIN_VERSION_SHIFT 24 // min.: 0, max.: 255, default: 0
+
+
+
+
+#define TMC2209_FACTORY_CONF 0x07
+
+#define TMC2209_FACTORY_CONF_FCLKTRIM_MASK 0x1F // FACTORY_CONF // FCLKTRIM (Reset default: OTP) 0-31: Lowest to highest clock frequency. Check at charge pump output. The frequency span is not guaranteed, but it is tested, that tuning to 12MHz internal clock is possible. The devices come preset to 12MHz clock frequency by OTP programming.
+#define TMC2209_FACTORY_CONF_FCLKTRIM_SHIFT 0 // min.: 0, max.: 31, default: 0
+#define TMC2209_FACTORY_CONF_OTTRIM_MASK 0x30 // FACTORY_CONF // OTTRIM (Default: OTP) %00: OT=143°C, OTPW=120°C %01: OT=150°C, OTPW=120°C %10: OT=150°C, OTPW=143°C %11: OT=157°C, OTPW=143°C
+#define TMC2209_FACTORY_CONF_OTTRIM_SHIFT 8 // min.: 0, max.: 3, default: 0
+
+#define TMC2209_IHOLD_IRUN 0x10
+
+#define TMC2209_IHOLD_IRUN_IHOLD_MASK 0x1F // IHOLD_IRUN // IHOLD (Reset default: OTP) Standstill current (0=1/32...31=32/32) In combination with stealthChop mode, setting IHOLD=0 allows to choose freewheeling or coil short circuit (passive braking) for motor stand still.
+#define TMC2209_IHOLD_IRUN_IHOLD_SHIFT 0 // min.: 0, max.: 31, default: 0
+#define TMC2209_IHOLD_IRUN_IRUN_MASK 0x1F00 // IHOLD_IRUN // IRUN (Reset default=31) Motor run current (0=1/32...31=32/32) Hint: Choose sense resistors in a way, that normal IRUN is 16 to 31 for best microstep performance.
+#define TMC2209_IHOLD_IRUN_IRUN_SHIFT 8 // min.: 0, max.: 31, default: 0
+#define TMC2209_IHOLD_IRUN_IHOLDDELAY_MASK 0x0F0000 // IHOLD_IRUN // IHOLDDELAY (Reset default: OTP) Controls the number of clock cycles for motor power down after standstill is detected (stst=1) and TPOWERDOWN has expired. The smooth transition avoids a motor jerk upon power down. 0: instant power down 1..15: Delay per current reduction step in multiple of 2^18 clocks
+#define TMC2209_IHOLD_IRUN_IHOLDDELAY_SHIFT 16 // min.: 0, max.: 15, default: 0
+
+
+
+
+#define TMC2209_TPOWERDOWN 0x11
+
+#define TMC2209_TPOWERDOWN_MASK 0xFF // TPOWERDOWN // (Reset default=20) Sets the delay time from stand still (stst) detection to motor current power down. Time range is about 0 to 5.6 seconds. 0...((2^8)-1) * 2^18 tclk Attention: A minimum setting of 2 is required to allow automatic tuning of stealthChop PWM_OFFS_AUTO.
+#define TMC2209_TPOWERDOWN_SHIFT 0 // min.: 0, max.: 255, default: 0
+
+
+
+
+#define TMC2209_TSTEP 0x12
+
+#define TMC2209_TSTEP_MASK 0x0FFFFF // TSTEP // Actual measured time between two 1/256 microsteps derived from the step input frequency in units of 1/fCLK. Measured value is (2^20)-1 in case of overflow or stand still. The TSTEP related threshold uses a hysteresis of 1/16 of the compare value to compensate for jitter in the clock or the step frequency: (Txxx*15/16)-1 is the lower compare value for each TSTEP based comparison. This means, that the lower switching velocity equals the calculated setting, but the upper switching velocity is higher as defined by the hysteresis setting.
+#define TMC2209_TSTEP_SHIFT 0 // min.: 0, max.: 1048575, default: 0
+
+
+
+#define TMC2209_TPWMTHRS 0x13
+
+#define TMC2209_TPWMTHRS_MASK 0x0FFFFF // TPWMTHRS // Sets the upper velocity for stealthChop voltage PWM mode. For TSTEP = TPWMTHRS, stealthChop PWM mode is enabled, if configured. When the velocity exceeds the limit set by TPWMTHRS, the driver switches to spreadCycle. 0 = Disabled
+#define TMC2209_TPWMTHRS_SHIFT 0 // min.: 0, max.: 1048575, default: 0
+
+
+
+#define TMC2209_TCOOLTHRS 0x14
+
+
+
+#define TMC2209_VACTUAL 0x22
+
+#define TMC2209_VACTUAL_MASK 0xFFFFFF // VACTUAL // VACTUAL allows moving the motor by UART control. It gives the motor velocity in +-(2^23)-1 [µsteps / t] 0: Normal operation. Driver reacts to STEP input. /=0: Motor moves with the velocity given by VACTUAL. Step pulses can be monitored via INDEX output. The motor direction is controlled by the sign of VACTUAL.
+#define TMC2209_VACTUAL_SHIFT 0 // min.: -8388608, max.: 8388607, default: 0
+
+
+
+#define TMC2209_SGTHRS 0x40
+
+
+
+#define TMC2209_SG_RESULT 0x41
+
+
+
+#define TMC2209_COOLCONF 0x42
+
+
+#define TMC2209_COOLCONF_SEMIN_MASK 0x0000000F
+#define TMC2209_COOLCONF_SEMIN_SHIFT 0
+#define TMC2209_COOLCONF_SEUP_MASK 0x00000060
+#define TMC2209_COOLCONF_SEUP_SHIFT 5
+#define TMC2209_COOLCONF_SEMAX_MASK 0x00000F00
+#define TMC2209_COOLCONF_SEMAX_SHIFT 8
+#define TMC2209_COOLCONF_SEDN_MASK 0x00006000
+#define TMC2209_COOLCONF_SEDN_SHIFT 13
+#define TMC2209_COOLCONF_SEIMIN_MASK 0x00008000
+#define TMC2209_COOLCONF_SEIMIN_SHIFT 15
+
+
+
+#define TMC2209_MSCNT 0x6A
+
+#define TMC2209_MSCNT_MASK 0x03FF // MSCNT // Microstep counter. Indicates actual position in the microstep table for CUR_A. CUR_B uses an offset of 256 into the table. Reading out MSCNT allows determination of the motor position within the electrical wave.
+#define TMC2209_MSCNT_SHIFT 0 // min.: 0, max.: 1023, default: 0
+
+
+
+
+#define TMC2209_MSCURACT 0x6B
+
+#define TMC2209_MSCURACT_CUR_A_MASK 0x01FF // MSCURACT // (signed) Actual microstep current for motor phase A as read from the internal sine wave table (not scaled by current setting)
+#define TMC2209_MSCURACT_CUR_A_SHIFT 0 // min.: -255, max.: 255, default: 0
+#define TMC2209_MSCURACT_CUR_B_MASK 0x01FF0000 // MSCURACT // (signed) Actual microstep current for motor phase B as read from the internal sine wave table (not scaled by current setting)
+#define TMC2209_MSCURACT_CUR_B_SHIFT 16 // min.: -255, max.: 255, default: 0
+
+
+
+#define TMC2209_CHOPCONF 0x6C
+
+#define TMC2209_CHOPCONF_TOFF_MASK 0x0F // CHOPCONF // chopper off time and driver enable, Off time setting controls duration of slow decay phase (Nclk = 12 + 32*Toff), %0000: Driver disable, all bridges off %0001: 1 - use only with TBL = 2 %0010 ... %1111: 2 - 15 (Default: OTP, resp. 3 in stealthChop mode)
+#define TMC2209_CHOPCONF_TOFF_SHIFT 0 // min.: 0, max.: 7, default: 0
+#define TMC2209_CHOPCONF_HSTRT_MASK 0x70 // CHOPCONF // hysteresis start value added to HEND, %000 - %111: Add 1, 2, ..., 8 to hysteresis low value HEND (1/512 of this setting adds to current setting) Attention: Effective HEND+HSTRT <= 16. Hint: Hysteresis decrement is done each 16 clocks. (Default: OTP, resp. 0 in stealthChop mode)
+#define TMC2209_CHOPCONF_HSTRT_SHIFT 4 // min.: 0, max.: 7, default: 0
+#define TMC2209_CHOPCONF_HEND_MASK 0x0780 // CHOPCONF // hysteresis low value OFFSET sine wave offset, %0000 - %1111: Hysteresis is -3, -2, -1, 0, 1, ..., 12 (1/512 of this setting adds to current setting) This is the hysteresis value which becomes used for the hysteresis chopper. (Default: OTP, resp. 5 in stealthChop mode)
+#define TMC2209_CHOPCONF_HEND_SHIFT 7 // min.: 0, max.: 255, default: 0
+#define TMC2209_CHOPCONF_TBL_MASK 0x018000 // CHOPCONF // blank time select, %00 - %11: Set comparator blank time to 16, 24, 32 or 40 clocks Hint: %00 or %01 is recommended for most applications (Default: OTP)
+#define TMC2209_CHOPCONF_TBL_SHIFT 15 // min.: 0, max.: 255, default: 0
+#define TMC2209_CHOPCONF_VSENSE_MASK 0x020000 // CHOPCONF // sense resistor voltage based current scaling
+#define TMC2209_CHOPCONF_VSENSE_SHIFT 17 // min.: 0, max.: 1, default: 0
+#define TMC2209_CHOPCONF_MRES_MASK 0x0F000000 // CHOPCONF // MRES micro step resolution, %0000: Native 256 microstep setting. %0001 - %1000: 128, 64, 32, 16, 8, 4, 2, FULLSTEP: Reduced microstep resolution. The resolution gives the number of microstep entries per sine quarter wave. When choosing a lower microstep resolution, the driver automatically uses microstep positions which result in a symmetrical wave. Number of microsteps per step pulse = 2^MRES (Selection by pins unless disabled by GCONF. mstep_reg_select)
+#define TMC2209_CHOPCONF_MRES_SHIFT 24 // min.: 0, max.: 255, default: 0
+#define TMC2209_CHOPCONF_INTPOL_MASK 0x10000000 // CHOPCONF // interpolation to 256 microsteps
+#define TMC2209_CHOPCONF_INTPOL_SHIFT 28 // min.: 0, max.: 1, default: 0
+#define TMC2209_CHOPCONF_DEDGE_MASK 0x20000000 // CHOPCONF // enable double edge step pulses
+#define TMC2209_CHOPCONF_DEDGE_SHIFT 29 // min.: 0, max.: 1, default: 0
+#define TMC2209_CHOPCONF_DISS2G_MASK 0x40000000 // CHOPCONF // short to GND protection disable
+#define TMC2209_CHOPCONF_DISS2G_SHIFT 30 // min.: 0, max.: 1, default: 0
+#define TMC2209_CHOPCONF_DISS2VS_MASK 0x80000000 // CHOPCONF // Low side short protection disable
+#define TMC2209_CHOPCONF_DISS2VS_SHIFT 31 // min.: 0, max.: 1, default: 0
+
+
+
+
+#define TMC2209_DRVSTATUS 0x6F
+
+#define TMC2209_DRV_STATUS_OTPW_MASK 0x01 // DRV_STATUS // overtemperature prewarning flag
+#define TMC2209_DRV_STATUS_OTPW_SHIFT 0 // min.: 0, max.: 1, default: 0
+#define TMC2209_DRV_STATUS_OT_MASK 0x02 // DRV_STATUS // overtemperature flag
+#define TMC2209_DRV_STATUS_OT_SHIFT 1 // min.: 0, max.: 1, default: 0
+#define TMC2209_DRV_STATUS_S2GA_MASK 0x04 // DRV_STATUS // short to ground indicator phase A
+#define TMC2209_DRV_STATUS_S2GA_SHIFT 2 // min.: 0, max.: 1, default: 0
+#define TMC2209_DRV_STATUS_S2GB_MASK 0x08 // DRV_STATUS // short to ground indicator phase B
+#define TMC2209_DRV_STATUS_S2GB_SHIFT 3 // min.: 0, max.: 1, default: 0
+#define TMC2209_DRV_STATUS_S2VSA_MASK 0x10 // DRV_STATUS // low side short indicator phase A
+#define TMC2209_DRV_STATUS_S2VSA_SHIFT 4 // min.: 0, max.: 1, default: 0
+#define TMC2209_DRV_STATUS_S2VSB_MASK 0x20 // DRV_STATUS // low side short indicator phase B
+#define TMC2209_DRV_STATUS_S2VSB_SHIFT 5 // min.: 0, max.: 1, default: 0
+#define TMC2209_DRV_STATUS_OLA_MASK 0x40 // DRV_STATUS // open load indicator phase A
+#define TMC2209_DRV_STATUS_OLA_SHIFT 6 // min.: 0, max.: 1, default: 0
+#define TMC2209_DRV_STATUS_OLB_MASK 0x80 // DRV_STATUS // open load indicator phase B
+#define TMC2209_DRV_STATUS_OLB_SHIFT 7 // min.: 0, max.: 1, default: 0
+#define TMC2209_DRV_STATUS_T120_MASK 0x0100 // DRV_STATUS // 120°C comparator
+#define TMC2209_DRV_STATUS_T120_SHIFT 8 // min.: 0, max.: 1, default: 0
+#define TMC2209_DRV_STATUS_T143_MASK 0x0200 // DRV_STATUS // 143°C comparator
+#define TMC2209_DRV_STATUS_T143_SHIFT 9 // min.: 0, max.: 1, default: 0
+#define TMC2209_DRV_STATUS_T150_MASK 0x0400 // DRV_STATUS // 150°C comparator
+#define TMC2209_DRV_STATUS_T150_SHIFT 10 // min.: 0, max.: 1, default: 0
+#define TMC2209_DRV_STATUS_T157_MASK 0x0800 // DRV_STATUS // 157°C comparator
+#define TMC2209_DRV_STATUS_T157_SHIFT 11 // min.: 0, max.: 1, default: 0
+#define TMC2209_DRV_STATUS_CS_ACTUAL_MASK 0x1F0000 // DRV_STATUS // actual motor current
+#define TMC2209_DRV_STATUS_CS_ACTUAL_SHIFT 16 // min.: 0, max.: 31, default: 0
+#define TMC2209_DRV_STATUS_STEALTH_MASK 0x40000000 // DRV_STATUS // stealthChop indicator
+#define TMC2209_DRV_STATUS_STEALTH_SHIFT 30 // min.: 0, max.: 1, default: 0
+#define TMC2209_DRV_STATUS_STST_MASK 0x80000000 // DRV_STATUS // standstill indicator
+#define TMC2209_DRV_STATUS_STST_SHIFT 31 // min.: 0, max.: 1, default: 0
+
+#define TMC2209_PWMCONF 0x70
+
+
+#define TMC2209_PWMCONF_PWM_OFS_MASK 0xFF // PWMCONF // User defined PWM amplitude offset (0-255) related to full motor current (CS_ACTUAL=31) in stand still. (Reset default=36) When using automatic scaling (pwm_autoscale=1) the value is used for initialization, only. The autoscale function starts with PWM_SCALE_AUTO=PWM_OFS and finds the required offset to yield the target current automatically. PWM_OFS = 0 will disable scaling down motor current below a motor specific lower measurement threshold. This setting should only be used under certain conditions, i.e. when the power supply voltage can vary up and down by a factor of two or more. It prevents the motor going out of regulation, but it also prevents power down below the regulation limit. PWM_OFS > 0 allows automatic scaling to low PWM duty cycles even below the lower regulation threshold. This allows low (standstill) current settings based on the actual (hold) current scale (register IHOLD_IRUN).
+#define TMC2209_PWMCONF_PWM_OFS_SHIFT 0 // min.: 0, max.: 255, default: 0
+#define TMC2209_PWMCONF_PWM_GRAD_MASK 0xFF00 // PWMCONF // Velocity dependent gradient for PWM amplitude: PWM_GRAD * 256 / TSTEP This value is added to PWM_AMPL to compensate for the velocity-dependent motor back-EMF. With automatic scaling (pwm_autoscale=1) the value is used for first initialization, only. Set PWM_GRAD to the application specific value (it can be read out from PWM_GRAD_AUTO) to speed up the automatic tuning process. An approximate value can be stored to OTP by programming OTP_PWM_GRAD.
+#define TMC2209_PWMCONF_PWM_GRAD_SHIFT 8 // min.: 0, max.: 255, default: 0
+#define TMC2209_PWMCONF_PWM_FREQ_MASK 0x030000 // PWMCONF // %00: fPWM=2/1024 fCLK %01: fPWM=2/683 fCLK %10: fPWM=2/512 fCLK %11: fPWM=2/410 fCLK
+#define TMC2209_PWMCONF_PWM_FREQ_SHIFT 16 // min.: 0, max.: 3, default: 0
+#define TMC2209_PWMCONF_PWM_AUTOSCALE_MASK 0x040000 // PWMCONF //
+#define TMC2209_PWMCONF_PWM_AUTOSCALE_SHIFT 18 // min.: 0, max.: 1, default: 0
+#define TMC2209_PWMCONF_PWM_AUTOGRAD_MASK 0x080000 // PWMCONF //
+#define TMC2209_PWMCONF_PWM_AUTOGRAD_SHIFT 19 // min.: 0, max.: 1, default: 0
+#define TMC2209_PWMCONF_FREEWHEEL_MASK 0x300000 // PWMCONF // Stand still option when motor current setting is zero (I_HOLD=0). %00: Normal operation %01: Freewheeling %10: Coil shorted using LS drivers %11: Coil shorted using HS drivers
+#define TMC2209_PWMCONF_FREEWHEEL_SHIFT 20 // min.: 0, max.: 3, default: 0
+#define TMC2209_PWMCONF_PWM_REG_MASK 0x0F000000 // PWMCONF // User defined maximum PWM amplitude change per half wave when using pwm_autoscale=1. (1...15): 1: 0.5 increments (slowest regulation) 2: 1 increment (default with OTP2.1=1) 3: 1.5 increments 4: 2 increments ... 8: 4 increments (default with OTP2.1=0) ... 15: 7.5 increments (fastest regulation)
+#define TMC2209_PWMCONF_PWM_REG_SHIFT 24 // min.: 0, max.: 25, default: 0
+#define TMC2209_PWMCONF_PWM_LIM_MASK 0xF0000000 // PWMCONF // Limit for PWM_SCALE_AUTO when switching back from spreadCycle to stealthChop. This value defines the upper limit for bits 7 to 4 of the automatic current control when switching back. It can be set to reduce the current jerk during mode change back to stealthChop. It does not limit PWM_GRAD or PWM_GRAD_AUTO offset. (Default = 12)
+#define TMC2209_PWMCONF_PWM_LIM_SHIFT 28 // min.: 0, max.: 15, default: 0
+
+
+
+#define TMC2209_PWMSCALE 0x71
+
+#define TMC2209_PWM_SCALE_SUM_MASK 0xFF // PWM_SCALE // Actual PWM duty cycle. This value is used for scaling the values CUR_A and CUR_B read from the sine wave table.
+#define TMC2209_PWM_SCALE_SUM_SHIFT 0 // min.: 0, max.: 255, default: 0
+#define TMC2209_PWM_SCALE_AUTO_MASK 0x01FF0000 // PWM_SCALE // 9 Bit signed offset added to the calculated PWM duty cycle. This is the result of the automatic amplitude regulation based on current measurement.
+#define TMC2209_PWM_SCALE_AUTO_SHIFT 16 // min.: -255, max.: 255, default: 0
+
+
+#define TMC2209_PWM_AUTO 0x72
+#define TMC2209_PWM_AUTO_PWM_OFS_AUTO_MASK 0xFF // PWM_AUTO // Automatically determined offset value
+#define TMC2209_PWM_AUTO_PWM_OFS_AUTO_SHIFT 0 // min.: 0, max.: 255, default: 0
+#define TMC2209_PWM_AUTO_PWM_GRAD_AUTO_MASK 0xFF0000 // PWM_AUTO // Automatically determined gradient value
+#define TMC2209_PWM_AUTO_PWM_GRAD_AUTO_SHIFT 16 // min.: 0, max.: 255, default: 0
+
diff --git a/stm32/app/usart.c b/stm32/app/usart.c
index 6b44656..e48eff5 100644
--- a/stm32/app/usart.c
+++ b/stm32/app/usart.c
@@ -2,11 +2,11 @@
#define BUFFER_SIZE 512
-ring_t usart_rx_ring;
-static uint8_t usart_rx_ring_buf[BUFFER_SIZE];
+ring_t usart1_rx_ring;
+static uint8_t usart1_rx_ring_buf[BUFFER_SIZE];
-ring_t usart_tx_ring;
-static uint8_t usart_tx_ring_buf[BUFFER_SIZE];
+ring_t usart1_tx_ring;
+static uint8_t usart1_tx_ring_buf[BUFFER_SIZE];
void
usart1_isr (void)
@@ -18,13 +18,13 @@ usart1_isr (void)
((USART_SR (USART1) & USART_SR_RXNE) != 0)) {
/* Retrieve the data from the peripheral. */
data = usart_recv (USART1);
- ring_write_byte (&usart_rx_ring, data);
+ ring_write_byte (&usart1_rx_ring, data);
}
/* Check if we were called because of TXE. */
if (((USART_CR1 (USART1) & USART_CR1_TXEIE) != 0) &&
((USART_SR (USART1) & USART_SR_TXE) != 0)) {
- if (ring_read_byte (&usart_tx_ring, &data)) {
+ if (ring_read_byte (&usart1_tx_ring, &data)) {
/*No more data, Disable the TXE interrupt, it's no longer needed. */
USART_CR1 (USART1) &= ~USART_CR1_TXEIE;
} else
@@ -32,9 +32,10 @@ usart1_isr (void)
}
}
-void usart_kick (void)
+
+void usart1_kick (void)
{
- if (!ring_empty (&usart_tx_ring))
+ if (!ring_empty (&usart1_tx_ring))
USART_CR1 (USART1) |= USART_CR1_TXEIE;
}
@@ -45,8 +46,8 @@ _write (int file, char *ptr, int len)
int ret;
if (file == 1) {
- ret = ring_write (&usart_tx_ring, (uint8_t *) ptr, len);
- usart_kick();
+ ret = ring_write (&usart1_tx_ring, (uint8_t *) ptr, len);
+ usart1_kick();
ring_write (&cdcacm_tx_ring, (uint8_t *) ptr, len);
if (ret < 0)
@@ -59,14 +60,44 @@ _write (int file, char *ptr, int len)
return -1;
}
+#define TRANSACT_TIMEOUT (HZ/2)
+
+int usart_transact (uint32_t u, void *_b, size_t txl, size_t rxl)
+{
+ uint8_t *b = _b;
+ uint32_t then = DWT_CYCCNT;
+
+ while (USART_SR (u) & USART_SR_RXNE)
+ (void) usart_recv (u);
+
+
+ while (txl--) {
+ while (! (USART_SR (USART1) & USART_SR_TXE))
+ if ((DWT_CYCCNT - then) > TRANSACT_TIMEOUT) return -1;
+
+ usart_send (u, * (b++));
+ }
+
+ b = _b;
+
+ while (rxl--) {
+ while (! (USART_SR (USART1) & USART_SR_RXNE))
+ if ((DWT_CYCCNT - then) > TRANSACT_TIMEOUT) return -1;
+
+ * (b++) = usart_recv (u);
+ }
+
+ return 0;
+}
+
void
usart_init (void)
{
- ring_init (&usart_rx_ring, usart_rx_ring_buf, sizeof (usart_rx_ring_buf));
- ring_init (&usart_tx_ring, usart_tx_ring_buf, sizeof (usart_tx_ring_buf));
+ ring_init (&usart1_rx_ring, usart1_rx_ring_buf, sizeof (usart1_rx_ring_buf));
+ ring_init (&usart1_tx_ring, usart1_tx_ring_buf, sizeof (usart1_tx_ring_buf));
/* Enable the USART1 interrupt. */
nvic_enable_irq (NVIC_USART1_IRQ);
@@ -85,4 +116,32 @@ usart_init (void)
USART_CR1 (USART1) |= USART_CR1_RXNEIE;
/* Finally enable USART1. */
usart_enable (USART1);
+
+
+ MAP_AF (USART2_TX);
+ MAP_AF_PU (USART2_RX);
+
+ /* Setup UART1 parameters. */
+ usart_set_baudrate (USART2, 115200);
+ usart_set_databits (USART2, 8);
+ usart_set_stopbits (USART2, USART_STOPBITS_1);
+ usart_set_parity (USART2, USART_PARITY_NONE);
+ usart_set_flow_control (USART2, USART_FLOWCONTROL_NONE);
+ usart_set_mode (USART2, USART_MODE_TX_RX);
+ usart_enable (USART2);
+
+ MAP_AF (USART3_TX);
+ MAP_AF_PU (USART3_RX);
+
+ /* Setup UART1 parameters. */
+ usart_set_baudrate (USART3, 115200);
+ usart_set_databits (USART3, 8);
+ usart_set_stopbits (USART3, USART_STOPBITS_1);
+ usart_set_parity (USART3, USART_PARITY_NONE);
+ usart_set_flow_control (USART3, USART_FLOWCONTROL_NONE);
+ usart_set_mode (USART3, USART_MODE_TX_RX);
+ usart_enable (USART3);
+
+
+
}