mirror of
https://github.com/eddyem/stm32samples.git
synced 2026-03-20 00:30:57 +03:00
Compare commits
3 Commits
65c9ae34bc
...
61262435a8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61262435a8 | ||
|
|
27eb723d80 | ||
|
|
57a44f1c66 |
@@ -39,12 +39,15 @@ static int write2flash(const void*, const void*, uint32_t);
|
|||||||
// 'memcpy' forming offset 8 is out of the bounds [0, 4] of object '__varsstart' with type 'uint32_t'
|
// 'memcpy' forming offset 8 is out of the bounds [0, 4] of object '__varsstart' with type 'uint32_t'
|
||||||
const user_conf *Flash_Data = (const user_conf *)(&__varsstart);
|
const user_conf *Flash_Data = (const user_conf *)(&__varsstart);
|
||||||
|
|
||||||
// default pin config: all are low speed floating inputs
|
// default pin config
|
||||||
|
// simple FL IN
|
||||||
#define PINEN {.enable = 1}
|
#define PINEN {.enable = 1}
|
||||||
|
// USART1 @9600 with monitoring
|
||||||
|
#define U1 {.enable = 1, .mode = MODE_AF, .speed = SPEED_HIGH, .afno = 1, .af = FUNC_USART, .monitor = 1}
|
||||||
// GPIOA, enabled: PA0-PA3, PA5-PA7, PA9, PA10
|
// GPIOA, enabled: PA0-PA3, PA5-PA7, PA9, PA10
|
||||||
#define PACONF \
|
#define PACONF \
|
||||||
[0] = PINEN, [1] = PINEN, [2] = PINEN, [3] = PINEN, [5] = PINEN, \
|
[0] = PINEN, [1] = PINEN, [2] = PINEN, [3] = PINEN, [5] = PINEN, \
|
||||||
[6] = PINEN, [7] = PINEN, [9] = PINEN, [10] = PINEN
|
[6] = PINEN, [7] = PINEN, [9] = U1, [10] = U1
|
||||||
|
|
||||||
// GPIOB, enabled: PB0-PB7, PB10, PB11
|
// GPIOB, enabled: PB0-PB7, PB10, PB11
|
||||||
#define PBCONF \
|
#define PBCONF \
|
||||||
@@ -60,6 +63,7 @@ user_conf the_conf = {
|
|||||||
},
|
},
|
||||||
.iIlengths = {14, 16},
|
.iIlengths = {14, 16},
|
||||||
.pinconfig = {[0] = {PACONF}, [1] = {PBCONF}},
|
.pinconfig = {[0] = {PACONF}, [1] = {PBCONF}},
|
||||||
|
.usartconfig = {.speed = 9600, .idx = 0, .RXen = 1, .TXen = 1, .textproto = 1, .monitor = 1},
|
||||||
};
|
};
|
||||||
|
|
||||||
int currentconfidx = -1; // index of current configuration
|
int currentconfidx = -1; // index of current configuration
|
||||||
|
|||||||
@@ -42,41 +42,93 @@ typedef struct{
|
|||||||
#define CANUSART(x) ((x) & (1<<FUNC_USART))
|
#define CANUSART(x) ((x) & (1<<FUNC_USART))
|
||||||
#define CANSPI(x) ((x) & (1<<FUNC_SPI))
|
#define CANSPI(x) ((x) & (1<<FUNC_SPI))
|
||||||
#define CANI2C(x) ((x) & (1<<FUNC_I2C))
|
#define CANI2C(x) ((x) & (1<<FUNC_I2C))
|
||||||
|
#define CANPWM(x) ((x) & (1<<FUNC_PWM))
|
||||||
|
|
||||||
// AF for USART, SPI, I2C:
|
// AF for USART, SPI, I2C:
|
||||||
#define _U(x) [FUNC_USART] = x
|
#define _U(x) [FUNC_USART] = x
|
||||||
// _S(0) or _U(0) have no sence, but lets understand that this pin have SPI or USART
|
// _S(0) or _U(0) have no sence, but lets understand that this pin have SPI or USART
|
||||||
#define _S(x) [FUNC_SPI] = x
|
#define _S(x) [FUNC_SPI] = x
|
||||||
#define _I(x) [FUNC_I2C] = x
|
#define _I(x) [FUNC_I2C] = x
|
||||||
|
#define _P(x) [FUNC_PWM] = x
|
||||||
|
// Here included only common AF for STM32F042 and STM32F072 and without negative timer outputs (stars - collisions)
|
||||||
static const pinprops_t pin_props[2][16] = {
|
static const pinprops_t pin_props[2][16] = {
|
||||||
[0] = { // PORT A
|
[0] = { // PORT A
|
||||||
[0] = { .funcs = 0b00000001, .AF = {0}}, // PA0: ADC0, AF2 (TIM2_CH1)
|
[0] = { .funcs = 0b00000001, .AF = {0}}, // PA0: ADC0
|
||||||
[1] = { .funcs = 0b00000001, .AF = {0}}, // PA1: ADC1, AF2 (TIM2_CH2)
|
[1] = { .funcs = 0b00010001, .AF = {_P(2)}}, // PA1: ADC1, AF2 (TIM2_CH2*)
|
||||||
[2] = { .funcs = 0b00000011, .AF = {_U(1)}}, // PA2: ADC2, AF2 (TIM2_CH3), AF1 (USART2_TX)
|
[2] = { .funcs = 0b00010011, .AF = {_U(1), _P(2)}}, // PA2: ADC2, AF2 (TIM2_CH3**), AF1 (USART2_TX)
|
||||||
[3] = { .funcs = 0b00000011, .AF = {_U(1)}}, // PA3: ADC3, AF2 (TIM2_CH4), AF1 (USART2_RX)
|
[3] = { .funcs = 0b00010011, .AF = {_U(1), _P(2)}}, // PA3: ADC3, AF2 (TIM2_CH4***), AF1 (USART2_RX)
|
||||||
[5] = { .funcs = 0b00000101, .AF = {_S(0)}}, // PA5: ADC5, AF9 (SPI1_SCK)
|
[5] = { .funcs = 0b00000101, .AF = {_S(0)}}, // PA5: ADC5, AF9 (SPI1_SCK)
|
||||||
[6] = { .funcs = 0b00000101, .AF = {_S(0)}}, // PA6: ADC6, AF0 (SPI1_MISO)
|
[6] = { .funcs = 0b00010101, .AF = {_S(0), _P(5)}}, // PA6: ADC6, AF0 (SPI1_MISO), AF5 (TIM16_CH1)
|
||||||
[7] = { .funcs = 0b00000101, .AF = {_S(0)}}, // PA7: ADC7, AF0 (SPI1_MOSI)
|
[7] = { .funcs = 0b00010101, .AF = {_S(0), _P(4)}}, // PA7: ADC7, AF0 (SPI1_MOSI), AF4 (TIM14_CH1)
|
||||||
[9] = { .funcs = 0b00000010, .AF = {_U(1)}}, // PA9: AF1 (USART1_TX)
|
[9] = { .funcs = 0b00010010, .AF = {_U(1), _P(2)}}, // PA9: AF1 (USART1_TX), AF2 (TIM1_CH2)
|
||||||
[10] = { .funcs = 0b00000010, .AF = {_U(1)}}, // PA10: AF1 (USART1_RX)
|
[10] = { .funcs = 0b00010010, .AF = {_U(1), _P(2)}}, // PA10: AF1 (USART1_RX), AF2 (TIM1_CH3)
|
||||||
},
|
},
|
||||||
[1] = { // PORT B
|
[1] = { // PORT B
|
||||||
[0] = { .funcs = 0b00000001, .AF = {0}}, // PB0: ADC8, AF1 (TIM3_CH3), AF2 (TIM1_CH2N)
|
[0] = { .funcs = 0b00010001, .AF = {_P(1)}}, // PB0: ADC8, AF1 (TIM3_CH3)
|
||||||
[1] = { .funcs = 0b00000001, .AF = {0}}, // PB1: ADC9, AF0 (TIM14_CH1), AF1 (TIM3_CH4), AF2 (TIM1_CH3N)
|
[1] = { .funcs = 0b00010001, .AF = {_P(1)}}, // PB1: ADC9, AF1 (TIM3_CH4)
|
||||||
[2] = { .funcs = 0b00000000, .AF = {0}}, // PB2: nothing except GPIO
|
[2] = { .funcs = 0b00000000, .AF = {0}}, // PB2: nothing except GPIO
|
||||||
[3] = { .funcs = 0b00000100, .AF = {_S(0)}}, // PB3: AF0, (SPI1_SCK), AF2 (TIM2_CH2)
|
[3] = { .funcs = 0b00010100, .AF = {_S(0), _P(2)}}, // PB3: AF0, (SPI1_SCK), AF2 (TIM2_CH2*)
|
||||||
[4] = { .funcs = 0b00000100, .AF = {_S(0)}}, // PB4: AF0 (SPI1_MISO), AF1 (TIM3_CH1)
|
[4] = { .funcs = 0b00010100, .AF = {_S(0), _P(1)}}, // PB4: AF0 (SPI1_MISO), AF1 (TIM3_CH1)
|
||||||
[5] = { .funcs = 0b00000100, .AF = {_S(0)}}, // PB5: AF0 (SPI1_MOSI), AF1 (TIM3_CH2)
|
[5] = { .funcs = 0b00010100, .AF = {_S(0), _P(1)}}, // PB5: AF0 (SPI1_MOSI), AF1 (TIM3_CH2)
|
||||||
[6] = { .funcs = 0b00001010, .AF = {_U(0), _I(1)}}, // PB6: AF0 (USART1_TX), AF1 (I2C1_SCL), AF2 (TIM16_CH1N)
|
[6] = { .funcs = 0b00001010, .AF = {_U(0), _I(1)}}, // PB6: AF0 (USART1_TX), AF1 (I2C1_SCL)
|
||||||
[7] = { .funcs = 0b00001010, .AF = {_U(0), _I(1)}}, // PB7: AF0 (USART1_RX), AF1 (I2C1_SDA), AF2 (TIM17_CH1N)
|
[7] = { .funcs = 0b00001010, .AF = {_U(0), _I(1)}}, // PB7: AF0 (USART1_RX), AF1 (I2C1_SDA)
|
||||||
[10] = { .funcs = 0b00001000, .AF = {_I(1)}}, // PB10: AF1 (I2C1_SCL), AF2 (TIM2_CH3)
|
[10] = { .funcs = 0b00011000, .AF = {_I(1), _P(2)}}, // PB10: AF1 (I2C1_SCL), AF2 (TIM2_CH3**)
|
||||||
[11] = { .funcs = 0b00001000, .AF = {_I(1)}}, // PB11: AF1 (I2C1_SDA), AF2 (TIM2_CH4)
|
[11] = { .funcs = 0b00011000, .AF = {_I(1), _P(2)}}, // PB11: AF1 (I2C1_SDA), AF2 (TIM2_CH4***)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#undef _U
|
#undef _U
|
||||||
#undef _S
|
#undef _S
|
||||||
#undef _I
|
#undef _I
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
PWM (start - collisions):
|
||||||
|
PxN XY (XY: TIMX_CHY)
|
||||||
|
PA1 22 *
|
||||||
|
PA2 23 **
|
||||||
|
PA3 24 ***
|
||||||
|
PA6 161
|
||||||
|
PA7 141
|
||||||
|
PA9 12
|
||||||
|
PA10 13
|
||||||
|
PB0 33
|
||||||
|
PB1 34
|
||||||
|
PB3 22 *
|
||||||
|
PB4 31
|
||||||
|
PB5 32
|
||||||
|
PB10 23 **
|
||||||
|
PB11 24 ***
|
||||||
|
-> need to set up timers / channels
|
||||||
|
TIM1 / 2 3
|
||||||
|
TIM2 / 2 3 4
|
||||||
|
TIM3 / 1 2 3 4
|
||||||
|
TIM14 / 1
|
||||||
|
TIM16 / 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PT(t, ch) {.tim = t, .chidx = ch}
|
||||||
|
#define PTC(t, ch, P, p) {.tim = t, .chidx = ch, .collision = 1, .collport = P, .collpin = p}
|
||||||
|
static const pwmtimer_t timer_map[2][16] = {
|
||||||
|
[0] = {
|
||||||
|
[1] = PTC(TIM2, 1, 1, 3),
|
||||||
|
[2] = PTC(TIM2, 2, 1, 10),
|
||||||
|
[3] = PTC(TIM2, 3, 1, 11),
|
||||||
|
[6] = PT(TIM16, 0),
|
||||||
|
[7] = PT(TIM14, 0),
|
||||||
|
[9] = PT(TIM1, 1),
|
||||||
|
[10] = PT(TIM1, 2)
|
||||||
|
},
|
||||||
|
[1] = {
|
||||||
|
[0] = PT(TIM3, 2),
|
||||||
|
[1] = PT(TIM3, 3),
|
||||||
|
[3] = PTC(TIM2, 1, 0, 1),
|
||||||
|
[4] = PT(TIM3, 0),
|
||||||
|
[5] = PT(TIM3, 1),
|
||||||
|
[10] = PTC(TIM2, 2, 0, 2),
|
||||||
|
[11] = PTC(TIM2, 3, 0, 3)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#undef PT
|
||||||
|
#undef PTC
|
||||||
|
|
||||||
typedef struct{
|
typedef struct{
|
||||||
uint8_t isrx : 1;
|
uint8_t isrx : 1;
|
||||||
@@ -434,3 +486,17 @@ uint16_t gpio_alert(uint8_t port){
|
|||||||
}
|
}
|
||||||
return alert;
|
return alert;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief canPWM - check if pin have PWM ability
|
||||||
|
* @param port - port (0/1 for GPIOA/GPIOB)
|
||||||
|
* @param pin - pin (0..15)
|
||||||
|
* @param t (o) - struct for pin's PWM timer
|
||||||
|
* @return TRUE if can, FALSE if no
|
||||||
|
*/
|
||||||
|
int canPWM(uint8_t port, uint8_t pin, pwmtimer_t *t){
|
||||||
|
if(port > 1 || pin > 15) return 0;
|
||||||
|
if(t) *t = timer_map[port][pin];
|
||||||
|
if(timer_map[port][pin].tim) return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stm32f0.h>
|
||||||
|
|
||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
#define USBIF IGPIO
|
#define USBIF IGPIO
|
||||||
@@ -60,13 +61,14 @@ typedef enum{
|
|||||||
} pinspeed_t;
|
} pinspeed_t;
|
||||||
|
|
||||||
// !!! FuncNames means position of bit in funcvalues_t.flags!
|
// !!! FuncNames means position of bit in funcvalues_t.flags!
|
||||||
enum FuncNames{ // shift 1 by this to get "canUSART" etc; not more than 7!
|
typedef enum FuncNames{ // shift 1 by this to get "canUSART" etc; not more than 7!
|
||||||
FUNC_AIN = 0,
|
FUNC_AIN = 0,
|
||||||
FUNC_USART = 1,
|
FUNC_USART = 1,
|
||||||
FUNC_SPI = 2,
|
FUNC_SPI = 2,
|
||||||
FUNC_I2C = 3,
|
FUNC_I2C = 3,
|
||||||
|
FUNC_PWM = 4,
|
||||||
FUNC_AMOUNT // just for arrays' sizes
|
FUNC_AMOUNT // just for arrays' sizes
|
||||||
};
|
} funcnames_t;
|
||||||
/*
|
/*
|
||||||
typedef union{
|
typedef union{
|
||||||
struct{
|
struct{
|
||||||
@@ -84,11 +86,20 @@ typedef struct{
|
|||||||
pinout_t otype : 1;
|
pinout_t otype : 1;
|
||||||
pinspeed_t speed : 2;
|
pinspeed_t speed : 2;
|
||||||
uint8_t afno : 3; // alternate function number (only if mode == MODE_AF)
|
uint8_t afno : 3; // alternate function number (only if mode == MODE_AF)
|
||||||
uint8_t af : 3; // alternate function name (`FuncNames`)
|
funcnames_t af : 3; // alternate function name (`FuncNames`)
|
||||||
uint8_t monitor : 1; // monitor changes
|
uint8_t monitor : 1; // monitor changes
|
||||||
uint16_t threshold; // threshold for ADC measurement
|
uint16_t threshold; // threshold for ADC measurement
|
||||||
} pinconfig_t;
|
} pinconfig_t;
|
||||||
|
|
||||||
|
// Timers for PWM
|
||||||
|
typedef struct{
|
||||||
|
volatile TIM_TypeDef *tim; // timer
|
||||||
|
uint8_t chidx : 2; // channel index (0..3)
|
||||||
|
uint8_t collision : 1; // have collision with other channel (1)
|
||||||
|
uint8_t collport : 1; // collision port index (0 - GPIOA, 1 - GPIOB)
|
||||||
|
uint8_t collpin : 4; // collision pin index (0..15)
|
||||||
|
} pwmtimer_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
typedef struct{
|
typedef struct{
|
||||||
uint32_t speed;
|
uint32_t speed;
|
||||||
@@ -110,3 +121,5 @@ int gpio_reinit();
|
|||||||
int pin_out(uint8_t port, uint8_t pin, uint8_t newval);
|
int pin_out(uint8_t port, uint8_t pin, uint8_t newval);
|
||||||
int16_t pin_in(uint8_t port, uint8_t pin);
|
int16_t pin_in(uint8_t port, uint8_t pin);
|
||||||
uint16_t gpio_alert(uint8_t port);
|
uint16_t gpio_alert(uint8_t port);
|
||||||
|
|
||||||
|
int canPWM(uint8_t port, uint8_t pin, pwmtimer_t *t);
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ extern volatile uint32_t Tms;
|
|||||||
static uint8_t curbuf[MAXSTRLEN]; // buffer for receiving data from USART etc
|
static uint8_t curbuf[MAXSTRLEN]; // buffer for receiving data from USART etc
|
||||||
|
|
||||||
static uint8_t usart_text = 0; // ==1 for text USART proto
|
static uint8_t usart_text = 0; // ==1 for text USART proto
|
||||||
|
static uint8_t hex_input_mode = 0; // ==0 for text input, 1 for HEX + text in quotes
|
||||||
|
|
||||||
// TODO: add analog threshold!
|
// TODO: add analog threshold!
|
||||||
|
|
||||||
@@ -48,20 +49,21 @@ static uint8_t usart_text = 0; // ==1 for text USART proto
|
|||||||
COMMAND(dumpconf, "dump current configuration") \
|
COMMAND(dumpconf, "dump current configuration") \
|
||||||
COMMAND(eraseflash, "erase full flash storage") \
|
COMMAND(eraseflash, "erase full flash storage") \
|
||||||
COMMAND(help, "show this help") \
|
COMMAND(help, "show this help") \
|
||||||
|
COMMAND(hexinput, "input is text (0) or hex + text in quotes (1)") \
|
||||||
COMMAND(mcutemp, "get MCU temperature (degC*10)") \
|
COMMAND(mcutemp, "get MCU temperature (degC*10)") \
|
||||||
COMMAND(mcureset, "reset MCU") \
|
COMMAND(mcureset, "reset MCU") \
|
||||||
COMMAND(PA, "GPIOA setter/getter (type PA0=help for further info)") \
|
COMMAND(PA, "GPIOA setter/getter (type PA0=help for further info)") \
|
||||||
COMMAND(PB, "GPIOB setter/getter") \
|
COMMAND(PB, "GPIOB setter/getter") \
|
||||||
COMMAND(readconf, "re-read config from flash") \
|
COMMAND(pwmmap, "show pins with PWM ability") \
|
||||||
|
COMMAND(readconf, "re-read config from flash") \
|
||||||
COMMAND(reinit, "apply pin config") \
|
COMMAND(reinit, "apply pin config") \
|
||||||
COMMAND(saveconf, "save current user configuration into flash") \
|
COMMAND(saveconf, "save current user configuration into flash") \
|
||||||
COMMAND(sendcan, "send all after '=' to CAN USB interface") \
|
COMMAND(sendcan, "send all after '=' to CAN USB interface") \
|
||||||
COMMAND(setiface, "set/get name of interface x (0 - CAN, 1 - GPIO)") \
|
COMMAND(setiface, "set/get name of interface x (0 - CAN, 1 - GPIO)") \
|
||||||
COMMAND(storeconf, "save config to flash") \
|
COMMAND(storeconf, "save config to flash") \
|
||||||
COMMAND(time, "show current time (ms)") \
|
COMMAND(time, "show current time (ms)") \
|
||||||
COMMAND(vdd, "get approx Vdd value (V*100)") \
|
COMMAND(USART, "Read USART data or send (USART=hex)") \
|
||||||
COMMAND(USART, "Read USART data or send (USART=hex)")
|
COMMAND(vdd, "get approx Vdd value (V*100)")
|
||||||
// COMMAND(usartconf, "set USART params (e.g. usartconf=115200 8N1)")
|
|
||||||
// COMMAND(SPI, "Read SPI data or send (SPI=hex)")
|
// COMMAND(SPI, "Read SPI data or send (SPI=hex)")
|
||||||
// COMMAND(spiconf, "set SPI params")
|
// COMMAND(spiconf, "set SPI params")
|
||||||
|
|
||||||
@@ -102,7 +104,7 @@ enum MiscValues{
|
|||||||
MISC_THRESHOLD,
|
MISC_THRESHOLD,
|
||||||
MISC_SPEED,
|
MISC_SPEED,
|
||||||
MISC_TEXT,
|
MISC_TEXT,
|
||||||
MISC_BIN
|
MISC_HEX
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: add HEX input?
|
// TODO: add HEX input?
|
||||||
@@ -124,7 +126,7 @@ KW(AIN) \
|
|||||||
KW(THRESHOLD) \
|
KW(THRESHOLD) \
|
||||||
KW(SPEED) \
|
KW(SPEED) \
|
||||||
KW(TEXT) \
|
KW(TEXT) \
|
||||||
KW(BIN) \
|
KW(HEX) \
|
||||||
|
|
||||||
enum{ // indexes of string keywords
|
enum{ // indexes of string keywords
|
||||||
#define KW(k) STR_ ## k,
|
#define KW(k) STR_ ## k,
|
||||||
@@ -157,7 +159,7 @@ static const Keyword keywords[] = {
|
|||||||
KEY(THRESHOLD, GROUP_MISC, MISC_THRESHOLD)
|
KEY(THRESHOLD, GROUP_MISC, MISC_THRESHOLD)
|
||||||
KEY(SPEED, GROUP_MISC, MISC_SPEED)
|
KEY(SPEED, GROUP_MISC, MISC_SPEED)
|
||||||
KEY(TEXT, GROUP_MISC, MISC_TEXT)
|
KEY(TEXT, GROUP_MISC, MISC_TEXT)
|
||||||
KEY(BIN, GROUP_MISC, MISC_BIN)
|
KEY(HEX, GROUP_MISC, MISC_HEX)
|
||||||
#undef K
|
#undef K
|
||||||
};
|
};
|
||||||
#define NUM_KEYWORDS (sizeof(keywords)/sizeof(keywords[0]))
|
#define NUM_KEYWORDS (sizeof(keywords)/sizeof(keywords[0]))
|
||||||
@@ -170,6 +172,7 @@ static const char* errtxt[ERR_AMOUNT] = {
|
|||||||
[ERR_WRONGLEN] = "WRONGLEN",
|
[ERR_WRONGLEN] = "WRONGLEN",
|
||||||
[ERR_CANTRUN] = "CANTRUN",
|
[ERR_CANTRUN] = "CANTRUN",
|
||||||
[ERR_BUSY] = "BUSY",
|
[ERR_BUSY] = "BUSY",
|
||||||
|
[ERR_OVERFLOW] = "OVERFLOW",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *pinhelp =
|
static const char *pinhelp =
|
||||||
@@ -181,8 +184,8 @@ static const char *pinhelp =
|
|||||||
" MISC: MONITOR - send data by USB as only state changed\n"
|
" MISC: MONITOR - send data by USB as only state changed\n"
|
||||||
" THRESHOLD (ADC only) - monitoring threshold, ADU\n"
|
" THRESHOLD (ADC only) - monitoring threshold, ADU\n"
|
||||||
" SPEED - interface speed/frequency\n"
|
" SPEED - interface speed/frequency\n"
|
||||||
" TEXT - USART means data as text ('\n'-separated strings)\n"
|
" TEXT - USART means data as text ('\\n'-separated strings)\n"
|
||||||
" BIN - USART means data as binary (output: HEX)\n"
|
" HEX - USART means data as binary (output: HEX)\n"
|
||||||
"\n"
|
"\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -235,6 +238,47 @@ static bool argsvals(char *args, int32_t *parno, int32_t *parval){
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief parse_hex_data - data parsing in case of `hex + text` input format
|
||||||
|
* @param input - input string
|
||||||
|
* @param output - output data
|
||||||
|
* @param max_len - length of `output`
|
||||||
|
* @return amount of parsed bytes or -1 in case of overflow or error
|
||||||
|
*/
|
||||||
|
static int parse_hex_data(char *input, uint8_t *output, int max_len){
|
||||||
|
if(!input || !*input || !output || max_len < 1) return 0;
|
||||||
|
char *p = input;
|
||||||
|
int out_idx = 0;
|
||||||
|
while(*p && out_idx < max_len){
|
||||||
|
while(*p == ' ' || *p == ',') ++p; // omit spaces and commas as delimeters
|
||||||
|
if(*p == '\0') break; // EOL
|
||||||
|
if(*p == '"'){ // TEXT (start/end)
|
||||||
|
++p;
|
||||||
|
while(*p && *p != '"'){
|
||||||
|
if(out_idx >= max_len) return -1;
|
||||||
|
output[out_idx++] = *p++;
|
||||||
|
}
|
||||||
|
if(*p == '"'){
|
||||||
|
++p; // go to next symbol after closing quotation mark
|
||||||
|
}else return -1; // no closing
|
||||||
|
}else{ // HEX number
|
||||||
|
char *start = p;
|
||||||
|
while(*p && *p != ' ' && *p != ',' && *p != '"') ++p;
|
||||||
|
char saved = *p;
|
||||||
|
*p = '\0'; // temporarily for `gethex`
|
||||||
|
uint32_t val;
|
||||||
|
const char *end = gethex(start, &val);
|
||||||
|
if(end != p || val > 0xFF){ // not a hex number or have more than 2 symbols
|
||||||
|
*p = saved;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*p = saved;
|
||||||
|
output[out_idx++] = (uint8_t)val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out_idx;
|
||||||
|
}
|
||||||
|
|
||||||
// `port` and `pin` are checked in `parse_pin_command`
|
// `port` and `pin` are checked in `parse_pin_command`
|
||||||
// `PAx = ` also printed there
|
// `PAx = ` also printed there
|
||||||
static void pin_getter(uint8_t port, uint8_t pin){
|
static void pin_getter(uint8_t port, uint8_t pin){
|
||||||
@@ -329,7 +373,7 @@ static errcodes_t pin_setter(uint8_t port, uint8_t pin, char *setter){
|
|||||||
case MISC_TEXT: // what to do, if textproto is set, but user wants binary?
|
case MISC_TEXT: // what to do, if textproto is set, but user wants binary?
|
||||||
UsartConf.textproto = 1;
|
UsartConf.textproto = 1;
|
||||||
break;
|
break;
|
||||||
case MISC_BIN: // clear text flag
|
case MISC_HEX: // clear text flag
|
||||||
UsartConf.textproto = 0;
|
UsartConf.textproto = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -357,7 +401,7 @@ static errcodes_t pin_setter(uint8_t port, uint8_t pin, char *setter){
|
|||||||
curconf.pull = static_cast <pinpull_t> (pull_set);
|
curconf.pull = static_cast <pinpull_t> (pull_set);
|
||||||
curconf.otype = static_cast <pinout_t> (otype_set);
|
curconf.otype = static_cast <pinout_t> (otype_set);
|
||||||
curconf.speed = SPEED_MEDIUM;
|
curconf.speed = SPEED_MEDIUM;
|
||||||
curconf.af = func_set;
|
curconf.af = static_cast <funcnames_t> (func_set);
|
||||||
curconf.monitor = monitor;
|
curconf.monitor = monitor;
|
||||||
if(!set_pinfunc(port, pin, &curconf)) return ERR_BADVAL;
|
if(!set_pinfunc(port, pin, &curconf)) return ERR_BADVAL;
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
@@ -574,8 +618,17 @@ static errcodes_t cmd_sendcan(const char _U_ *cmd, char *args){
|
|||||||
if(!args) return ERR_BADVAL;
|
if(!args) return ERR_BADVAL;
|
||||||
char *setter = splitargs(args, NULL);
|
char *setter = splitargs(args, NULL);
|
||||||
if(!setter) return ERR_BADVAL;
|
if(!setter) return ERR_BADVAL;
|
||||||
if(USB_sendstr(ICAN, setter)) return ERR_OK;
|
if(hex_input_mode){
|
||||||
USB_putbyte(ICAN, '\n');
|
int len = parse_hex_data(setter, curbuf, MAXSTRLEN);
|
||||||
|
if(len < 0) return ERR_BADVAL;
|
||||||
|
if(len == 0) return ERR_AMOUNT;
|
||||||
|
if(USB_send(ICAN, curbuf, len)) return ERR_OK;
|
||||||
|
}else{
|
||||||
|
if(USB_sendstr(ICAN, setter)){
|
||||||
|
USB_putbyte(ICAN, '\n');
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
return ERR_CANTRUN;
|
return ERR_CANTRUN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -627,6 +680,36 @@ static errcodes_t cmd_help(const char _U_ *cmd, char _U_ *args){
|
|||||||
return ERR_AMOUNT;
|
return ERR_AMOUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static errcodes_t cmd_hexinput(const char *cmd, char *args){
|
||||||
|
int32_t val;
|
||||||
|
if(argsvals(args, NULL, &val)){
|
||||||
|
if(val == 0 || val == 1) hex_input_mode = (uint8_t)val;
|
||||||
|
else return ERR_BADVAL;
|
||||||
|
}
|
||||||
|
CMDEQ();
|
||||||
|
SENDn(hex_input_mode ? "1" : "0");
|
||||||
|
return ERR_AMOUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static errcodes_t cmd_pwmmap(const char _U_ *cmd, char _U_ *args){
|
||||||
|
pwmtimer_t t;
|
||||||
|
SEND("PWM pins:\n");
|
||||||
|
for(int port = 0; port < 2; ++port){
|
||||||
|
for(int pin = 0; pin < 16; ++pin){
|
||||||
|
if(!canPWM(port, pin, &t)) continue;
|
||||||
|
SEND((port == 0) ? "PA" : "PB");
|
||||||
|
SEND(u2str(pin));
|
||||||
|
if(t.collision){
|
||||||
|
SEND(" conflicts with ");
|
||||||
|
SEND((t.collport == 0) ? "PA" : "PB");
|
||||||
|
SEND(u2str(t.collpin));
|
||||||
|
}
|
||||||
|
NL();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ERR_AMOUNT;
|
||||||
|
}
|
||||||
|
|
||||||
static int sendfun(const char *s){
|
static int sendfun(const char *s){
|
||||||
if(!s) return 0;
|
if(!s) return 0;
|
||||||
return USB_sendstr(IGPIO, s);
|
return USB_sendstr(IGPIO, s);
|
||||||
@@ -637,7 +720,7 @@ static void sendusartdata(const uint8_t *buf, int len){
|
|||||||
SEND(str_keywords[STR_USART]); SEND(EQ);
|
SEND(str_keywords[STR_USART]); SEND(EQ);
|
||||||
if(usart_text){
|
if(usart_text){
|
||||||
USB_send(IGPIO, curbuf, len);
|
USB_send(IGPIO, curbuf, len);
|
||||||
if(curbuf[len-1] != '\n') NL();
|
NL(); // always add newline at the end to mark real newline ("\n\n") and piece of line ("\n")
|
||||||
}else{
|
}else{
|
||||||
NL();
|
NL();
|
||||||
hexdump(sendfun, (uint8_t*)curbuf, len);
|
hexdump(sendfun, (uint8_t*)curbuf, len);
|
||||||
@@ -649,14 +732,17 @@ static errcodes_t cmd_USART(const char _U_ *cmd, char *args){
|
|||||||
char *setter = splitargs(args, NULL);
|
char *setter = splitargs(args, NULL);
|
||||||
if(setter){
|
if(setter){
|
||||||
DBG("Try to send over USART\n");
|
DBG("Try to send over USART\n");
|
||||||
int l = strlen(setter);
|
if(hex_input_mode){
|
||||||
if(usart_text){ // add '\n' as we removed it @ parser
|
int len = parse_hex_data(setter, curbuf, MAXSTRLEN);
|
||||||
if(setter[l-1] != '\n') setter[l++] = '\n';
|
if(len < 0) return ERR_BADVAL;
|
||||||
|
if(len > 0) return usart_send(curbuf, len);
|
||||||
|
}else{ // text mode: "AS IS"
|
||||||
|
int l = strlen(setter);
|
||||||
|
if(usart_text){ // add '\n' as we removed it @ parser
|
||||||
|
setter[l++] = '\n';
|
||||||
|
}
|
||||||
|
return usart_send((uint8_t*)setter, l);
|
||||||
}
|
}
|
||||||
l = usart_send((uint8_t*)setter, l);
|
|
||||||
if(l < 0) return ERR_BUSY;
|
|
||||||
else if(l == 0) return ERR_CANTRUN;
|
|
||||||
return ERR_OK;
|
|
||||||
} // getter: try to read
|
} // getter: try to read
|
||||||
int l = usart_receive(curbuf, MAXSTRLEN);
|
int l = usart_receive(curbuf, MAXSTRLEN);
|
||||||
if(l < 0) return ERR_CANTRUN;
|
if(l < 0) return ERR_CANTRUN;
|
||||||
@@ -711,3 +797,10 @@ void GPIO_process(){
|
|||||||
if(ans) SENDn(ans);
|
if(ans) SENDn(ans);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// starting init by flash settings
|
||||||
|
void GPIO_init(){
|
||||||
|
gpio_reinit();
|
||||||
|
usartconf_t usc;
|
||||||
|
if(get_curusartconf(&usc)) usart_text = usc.textproto;
|
||||||
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ typedef enum{
|
|||||||
ERR_WRONGLEN, // wrong message length
|
ERR_WRONGLEN, // wrong message length
|
||||||
ERR_CANTRUN, // can't run given command due to bad parameters or other
|
ERR_CANTRUN, // can't run given command due to bad parameters or other
|
||||||
ERR_BUSY, // target interface busy, try later
|
ERR_BUSY, // target interface busy, try later
|
||||||
|
ERR_OVERFLOW, // string was too long -> overflow
|
||||||
ERR_AMOUNT // amount of error codes or "send nothing"
|
ERR_AMOUNT // amount of error codes or "send nothing"
|
||||||
} errcodes_t;
|
} errcodes_t;
|
||||||
|
|
||||||
@@ -39,3 +40,4 @@ typedef enum{
|
|||||||
#define ADC_THRES_DEFAULT 100
|
#define ADC_THRES_DEFAULT 100
|
||||||
|
|
||||||
void GPIO_process();
|
void GPIO_process();
|
||||||
|
void GPIO_init();
|
||||||
|
|||||||
@@ -17,12 +17,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "adc.h"
|
#include "adc.h"
|
||||||
#include "gpio.h"
|
#include "gpioproto.h"
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
|
|
||||||
uint8_t ledsON = 0;
|
uint8_t ledsON = 0;
|
||||||
|
|
||||||
TRUE_INLINE void gpio_setup(){ // setup some common GPIO
|
TRUE_INLINE void pins_setup(){ // setup some common GPIO
|
||||||
// Set LEDS (PB15/PA8) as output
|
// Set LEDS (PB15/PA8) as output
|
||||||
pin_set(LED0_port, LED0_pin); // clear LEDs
|
pin_set(LED0_port, LED0_pin); // clear LEDs
|
||||||
pin_set(LED1_port, LED1_pin);
|
pin_set(LED1_port, LED1_pin);
|
||||||
@@ -37,9 +37,9 @@ void hardware_setup(){
|
|||||||
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_DMA1EN;
|
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_DMA1EN;
|
||||||
RCC->APB2ENR |= RCC_APB2ENR_USART1EN | RCC_APB2ENR_SYSCFGEN;
|
RCC->APB2ENR |= RCC_APB2ENR_USART1EN | RCC_APB2ENR_SYSCFGEN;
|
||||||
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
|
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
|
||||||
gpio_setup();
|
pins_setup();
|
||||||
//gpio_reinit();
|
|
||||||
adc_setup();
|
adc_setup();
|
||||||
|
GPIO_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void iwdg_setup(){
|
void iwdg_setup(){
|
||||||
|
|||||||
32
F0:F030,F042,F072/usbcan_gpio/pwm.c
Normal file
32
F0:F030,F042,F072/usbcan_gpio/pwm.c
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the usbcangpio project.
|
||||||
|
* Copyright 2026 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "pwm.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* initial setup of all available PWM timers / channels:
|
||||||
|
* TIM1 / 2 3
|
||||||
|
* TIM2 / 2 3 4
|
||||||
|
* TIM3 / 1 2 3 4
|
||||||
|
* TIM14 / 1
|
||||||
|
* TIM16 / 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
void pwm_setup(){
|
||||||
|
;
|
||||||
|
}
|
||||||
21
F0:F030,F042,F072/usbcan_gpio/pwm.h
Normal file
21
F0:F030,F042,F072/usbcan_gpio/pwm.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the usbcangpio project.
|
||||||
|
* Copyright 2026 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
void pwm_setup();
|
||||||
@@ -147,7 +147,8 @@ static const char *getdec(const char *buf, uint32_t *N){
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
// read hexadecimal number (without 0x prefix!)
|
// read hexadecimal number (without 0x prefix!)
|
||||||
static const char *gethex(const char *buf, uint32_t *N){
|
const char *gethex(const char *buf, uint32_t *N){
|
||||||
|
if(!buf || !N) return NULL;
|
||||||
const char *start = buf;
|
const char *start = buf;
|
||||||
uint32_t num = 0;
|
uint32_t num = 0;
|
||||||
while(*buf){
|
while(*buf){
|
||||||
|
|||||||
@@ -37,12 +37,13 @@
|
|||||||
#define REPOURL "https://github.com/eddyem/stm32samples/tree/master/F0:F030,F042,F072/usbcan_gpio " RLSDBG " build #" BUILD_NUMBER "@" BUILD_DATE "\n"
|
#define REPOURL "https://github.com/eddyem/stm32samples/tree/master/F0:F030,F042,F072/usbcan_gpio " RLSDBG " build #" BUILD_NUMBER "@" BUILD_DATE "\n"
|
||||||
|
|
||||||
// max string len to '\n' (including '\0')
|
// max string len to '\n' (including '\0')
|
||||||
#define MAXSTRLEN 128
|
#define MAXSTRLEN 256
|
||||||
|
|
||||||
void hexdump(int (*sendfun)(const char *s), uint8_t *arr, uint16_t len);
|
void hexdump(int (*sendfun)(const char *s), uint8_t *arr, uint16_t len);
|
||||||
const char *u2str(uint32_t val);
|
const char *u2str(uint32_t val);
|
||||||
const char *i2str(int32_t i);
|
const char *i2str(int32_t i);
|
||||||
const char *uhex2str(uint32_t val);
|
const char *uhex2str(uint32_t val);
|
||||||
|
const char *gethex(const char *buf, uint32_t *N);
|
||||||
char *getnum(const char *txt, uint32_t *N);
|
char *getnum(const char *txt, uint32_t *N);
|
||||||
char *omit_spaces(const char *buf);
|
char *omit_spaces(const char *buf);
|
||||||
char *getint(const char *txt, int32_t *I);
|
char *getint(const char *txt, int32_t *I);
|
||||||
|
|||||||
@@ -209,10 +209,14 @@ int usart_process(uint8_t *buf, int len){
|
|||||||
int remained = DMA1_Channel5->CNDTR;
|
int remained = DMA1_Channel5->CNDTR;
|
||||||
int write_idx = DMARXBUFSZ - remained; // next symbol to be written
|
int write_idx = DMARXBUFSZ - remained; // next symbol to be written
|
||||||
int available = (write_idx - dma_read_idx); // length of data available
|
int available = (write_idx - dma_read_idx); // length of data available
|
||||||
|
if(available < 0) available += DMARXBUFSZ; // write to the left of read
|
||||||
|
if(available == 0){
|
||||||
|
RXrdy = 0; // clear old ready flag if got no data
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
int monitored_len = available;
|
int monitored_len = available;
|
||||||
uint8_t locmonitor = monitor; // if `buf` not pointed, set this flag to zero
|
uint8_t locmonitor = monitor; // if `buf` not pointed, set this flag to zero
|
||||||
if(available < 0) available += DMARXBUFSZ; // write to the left of read
|
if(available > 0){
|
||||||
if(available){
|
|
||||||
if(locmonitor){
|
if(locmonitor){
|
||||||
if(buf && len > 0){
|
if(buf && len > 0){
|
||||||
if(len < monitored_len) monitored_len = len;
|
if(len < monitored_len) monitored_len = len;
|
||||||
@@ -222,24 +226,32 @@ int usart_process(uint8_t *buf, int len){
|
|||||||
if(available >= (DMARXBUFSZ/2) || RXrdy){ // enough data or lonely couple of bytes but need to show
|
if(available >= (DMARXBUFSZ/2) || RXrdy){ // enough data or lonely couple of bytes but need to show
|
||||||
// copy data in one or two chunks (wrap handling)
|
// copy data in one or two chunks (wrap handling)
|
||||||
int wrOK = FALSE;
|
int wrOK = FALSE;
|
||||||
|
// check if we can write to RB `available` bytes
|
||||||
|
int canRB = TRUE;
|
||||||
|
if(!locmonitor){
|
||||||
|
int rballow = RBin.length - 1 - RB_datalen(&RBin);
|
||||||
|
if(rballow < available) canRB = FALSE;
|
||||||
|
}
|
||||||
if(dma_read_idx + available <= DMARXBUFSZ){ // head before tail
|
if(dma_read_idx + available <= DMARXBUFSZ){ // head before tail
|
||||||
if(locmonitor){
|
if(locmonitor){
|
||||||
memcpy(buf, &inbuffer[dma_read_idx], monitored_len);
|
memcpy(buf, &inbuffer[dma_read_idx], monitored_len);
|
||||||
ret = monitored_len;
|
ret = monitored_len;
|
||||||
wrOK = TRUE;
|
wrOK = TRUE;
|
||||||
}else{
|
}else{
|
||||||
if(available == RB_write(&RBin, &inbuffer[dma_read_idx], available)) wrOK = TRUE;
|
if(canRB && available == RB_write(&RBin, &inbuffer[dma_read_idx], available)) wrOK = TRUE;
|
||||||
|
else if(buf && len > 0) ret = RB_read(&RBin, buf, len); // ringbuffer overfull -> emerge clearing
|
||||||
}
|
}
|
||||||
}else{ // head after tail - two chunks
|
}else{ // head after tail - two chunks
|
||||||
int first = DMARXBUFSZ - dma_read_idx;
|
int first = DMARXBUFSZ - dma_read_idx;
|
||||||
if(locmonitor){
|
if(locmonitor){
|
||||||
memcpy(buf, &inbuffer[dma_read_idx], first);
|
memcpy(buf, &inbuffer[dma_read_idx], first);
|
||||||
memcpy(buf, inbuffer, monitored_len - first);
|
memcpy(buf + first, inbuffer, monitored_len - first);
|
||||||
ret = monitored_len;
|
ret = monitored_len;
|
||||||
wrOK = TRUE;
|
wrOK = TRUE;
|
||||||
}else{
|
}else{
|
||||||
if((first == RB_write(&RBin, &inbuffer[dma_read_idx], first)) &&
|
if(canRB && (first == RB_write(&RBin, &inbuffer[dma_read_idx], first)) &&
|
||||||
(available - first) == RB_write(&RBin, inbuffer, available - first)) wrOK = TRUE;
|
(available - first) == RB_write(&RBin, inbuffer, available - first)) wrOK = TRUE;
|
||||||
|
else if(buf && len > 0) ret = RB_read(&RBin, buf, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(wrOK){
|
if(wrOK){
|
||||||
@@ -247,29 +259,20 @@ int usart_process(uint8_t *buf, int len){
|
|||||||
dma_read_idx = write_idx; // update read pointer
|
dma_read_idx = write_idx; // update read pointer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}else if(available < 0){ // das ist fantastisch!
|
||||||
|
if(buf && len > 0) ret = RB_read(&RBin, buf, len);
|
||||||
|
DBG("WTF? USART's `available` < 0!!!\n");
|
||||||
}
|
}
|
||||||
#if 0
|
// we can work with RBout to send more than `usart_send` can
|
||||||
// Output data
|
// here we can send next data portion
|
||||||
if(TXrdy){ // ready to send new data - here we can process RBout, if have
|
|
||||||
int got = RB_read...
|
|
||||||
if(got > 0){ // send next data portion
|
|
||||||
volatile DMA_Channel_TypeDef *T = cfg->dma_tx_channel;
|
|
||||||
T->CCR &= ~DMA_CCR_EN;
|
|
||||||
T->CMAR = (uint32_t) outbuffers[i];
|
|
||||||
T->CNDTR = got;
|
|
||||||
TXrdy = 0;
|
|
||||||
T->CCR |= DMA_CCR_EN; // start new transmission
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// send data buffer
|
// send data buffer
|
||||||
int usart_send(const uint8_t *data, int len){
|
errcodes_t usart_send(const uint8_t *data, int len){
|
||||||
if(curUSARTidx == -1 || !data || len < 1) return 0;
|
if(curUSARTidx == -1 || !data || len < 1) return ERR_CANTRUN;
|
||||||
if(TXrdy == 0) return -1;
|
if(TXrdy == 0) return ERR_BUSY;
|
||||||
if(len > DMATXBUFSZ) len = DMATXBUFSZ;
|
if(len > DMATXBUFSZ) return ERR_OVERFLOW;
|
||||||
memcpy(outbuffer, data, len);
|
memcpy(outbuffer, data, len);
|
||||||
volatile DMA_Channel_TypeDef *T = DMA1_Channel4;
|
volatile DMA_Channel_TypeDef *T = DMA1_Channel4;
|
||||||
T->CCR &= ~DMA_CCR_EN;
|
T->CCR &= ~DMA_CCR_EN;
|
||||||
@@ -277,7 +280,7 @@ int usart_send(const uint8_t *data, int len){
|
|||||||
T->CNDTR = len;
|
T->CNDTR = len;
|
||||||
TXrdy = 0;
|
TXrdy = 0;
|
||||||
T->CCR |= DMA_CCR_EN; // start new transmission
|
T->CCR |= DMA_CCR_EN; // start new transmission
|
||||||
return len;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -19,12 +19,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "gpioproto.h"
|
||||||
|
|
||||||
// DMA linear buffers for Rx/Tx
|
// DMA linear buffers for Rx/Tx
|
||||||
#define DMARXBUFSZ 128
|
#define DMARXBUFSZ 192
|
||||||
#define DMATXBUFSZ 128
|
#define DMATXBUFSZ 192
|
||||||
// incoming ring buffer - only if there's a lot of data in DMA RX buffer
|
// incoming ring buffer - only if there's a lot of data in DMA RX buffer
|
||||||
#define RXRBSZ 256
|
#define RXRBSZ 384
|
||||||
|
|
||||||
#define USART_MIN_SPEED 1024
|
#define USART_MIN_SPEED 1024
|
||||||
#define USART_MAX_SPEED 1000000
|
#define USART_MAX_SPEED 1000000
|
||||||
@@ -51,4 +52,4 @@ void get_defusartconf(usartconf_t *c);
|
|||||||
int usart_process(uint8_t *buf, int len);
|
int usart_process(uint8_t *buf, int len);
|
||||||
|
|
||||||
int usart_receive(uint8_t *buf, int len);
|
int usart_receive(uint8_t *buf, int len);
|
||||||
int usart_send(const uint8_t *data, int len);
|
errcodes_t usart_send(const uint8_t *data, int len);
|
||||||
|
|||||||
Binary file not shown.
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE QtCreatorProject>
|
<!DOCTYPE QtCreatorProject>
|
||||||
<!-- Written by QtCreator 18.0.2, 2026-03-14T01:13:52. -->
|
<!-- Written by QtCreator 18.0.2, 2026-03-15T02:24:04. -->
|
||||||
<qtcreator>
|
<qtcreator>
|
||||||
<data>
|
<data>
|
||||||
<variable>EnvironmentId</variable>
|
<variable>EnvironmentId</variable>
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ hashgen/Readme
|
|||||||
hashgen/hashgen.c
|
hashgen/hashgen.c
|
||||||
hashgen/mktestdic
|
hashgen/mktestdic
|
||||||
main.c
|
main.c
|
||||||
|
pwm.c
|
||||||
|
pwm.h
|
||||||
ringbuffer.c
|
ringbuffer.c
|
||||||
ringbuffer.h
|
ringbuffer.h
|
||||||
strfunc.c
|
strfunc.c
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
#define BUILD_NUMBER "173"
|
#define BUILD_NUMBER "192"
|
||||||
#define BUILD_DATE "2026-03-14"
|
#define BUILD_DATE "2026-03-15"
|
||||||
|
|||||||
Reference in New Issue
Block a user