mirror of
https://github.com/eddyem/stm32samples.git
synced 2025-12-06 10:45:11 +03:00
Continue to write USB protocol documentation and fix bugs in code.
This commit is contained in:
parent
018f0d4b33
commit
b10fb37c58
@ -4,6 +4,7 @@ MCU := F303xd
|
||||
# change this linking script depending on particular MCU model,
|
||||
LDSCRIPT := stm32f303xD.ld
|
||||
DEFINES := -DUSB2_16
|
||||
#DEFINES := -DUSB1_16
|
||||
|
||||
include ../makefile.f3
|
||||
include ../../makefile.stm32
|
||||
|
||||
@ -9,7 +9,7 @@ Eighth stepper could be changed to 8 dependent multiplexed. Based on STM32F303VD
|
||||
|
||||
### Sorted by pin number
|
||||
|
||||
|**Pin #**|**Pin name **| **function**| **settings** |**comment ** |
|
||||
| Pin # | Pin name | function | settings | comment |
|
||||
|---------|-------------|-------------|---------------|---------------------|
|
||||
| 1 | PE2 | DIAG | in | `diag` output of TMC|
|
||||
| 2 | PE3 | MUL0 | slow out | multiplexer address |
|
||||
@ -113,23 +113,36 @@ Eighth stepper could be changed to 8 dependent multiplexed. Based on STM32F303VD
|
||||
| 100 | (VDD) | | | |
|
||||
|
||||
### Some comments.
|
||||
_DIAG_ input used to detect problems with TMC drivers (multiplexed by _MUL_ outputs).
|
||||
Each motor have next control signals: _EN_ - enable driver, _DIR_ - rotation direction, _STEP_ - microstepping clock signal, _L0_ - zero end-switch, _L1_ - max end-switch (or Cable Select for SPI-based TMC).
|
||||
_MOTMUL_ - external multiplexer or other GPIO signals (e.g. to manage of 64 stepper motors).
|
||||
_ADC1 in_ - four external ADC signals (0..3.3V).
|
||||
_SPI1_ used to manage TMC drivers in case of SPI-based.
|
||||
_USART1_ - to connect external something (master or slave).
|
||||
_OUT_ - external GPIO.
|
||||
_USART2 Tx_ used to manage USART-based TMC (numbers 0-3).
|
||||
_USART3 Tx_ used to manage USART-based TMC (numbers 4-7).
|
||||
_SCRN_ - control signals for SPI TFT screen.
|
||||
_BTN_ - external button, keypad, joystick etc. Two of them could be connected to I2C devices.
|
||||
_USB_ and _CAN_ used as main device control buses.
|
||||
_SW_ used as debugging/sewing; also (I remember about USB pullup only after end of PCB design) _SWDIO_ used as USB pullup (so the device have no USB in debug mode - when BTN0 and BTN1 are pressed at start).
|
||||
**DIAG** input used to detect problems with TMC drivers (multiplexed by **MUL** outputs).
|
||||
|
||||
Each motor have next control signals: **EN** - enable driver, **DIR** - rotation direction, **STEP** - microstepping clock signal, **L0** - zero end-switch,
|
||||
**L1** - max end-switch (or Cable Select for SPI-based TMC).
|
||||
|
||||
**MOTMUL** - external multiplexer or other GPIO signals (e.g. to manage of 64 stepper motors).
|
||||
|
||||
**ADC1 in** - four external ADC signals (0..3.3V).
|
||||
|
||||
**SPI1** used to manage TMC drivers in case of SPI-based.
|
||||
|
||||
**USART1** - to connect external something (master or slave).
|
||||
|
||||
**OUT** - external GPIO.
|
||||
|
||||
**USART2 Tx** used to manage USART-based TMC (numbers 0-3).
|
||||
|
||||
**USART3 Tx** used to manage USART-based TMC (numbers 4-7).
|
||||
|
||||
**SCRN** - control signals for SPI TFT screen.
|
||||
|
||||
**BTN** - external button, keypad, joystick etc. Two of them could be connected to I2C devices.
|
||||
|
||||
**USB** and **CAN** used as main device control buses.
|
||||
|
||||
**SW** used as debugging/flashing.
|
||||
|
||||
### Sorted by ports (with AF numbers).
|
||||
|
||||
|**Pin #**|**Pin name **| **function**| **settings** |**comment ** |
|
||||
| Pin # | Pin name | function | settings | comment |
|
||||
|---------|-------------|-------------|---------------|---------------------|
|
||||
| 23 | PA0 | ADC1 in1 | ADC | External ADC inputs |
|
||||
| 24 | PA1 | ADC1 in2 | ADC | |
|
||||
@ -216,18 +229,233 @@ _SW_ used as debugging/sewing; also (I remember about USB pullup only after end
|
||||
| 10 | PF9 | M0 STEP | AF3 (T15ch1) | clock of motor |
|
||||
| 11 | PF10 | M0 EN | slow out | l-s 0 or CS of SPI |
|
||||
|
||||
|
||||
## DMA usage
|
||||
|
||||
* ADC1 - DMA1_ch1
|
||||
* ADC2 - DMA2_ch1
|
||||
* USART2 (PDN-UART for drivers 0..3) - DMA1_ch6 (Rx), DMA1_ch7 (Tx)
|
||||
* USART3 (PDN-UART for drivers 4..7) - DMA1_ch3 (Rx), DMA1_ch2 (Tx)
|
||||
* SPI2 (screen) - DMA1_ch4 (Rx), DMA1_ch5 (Tx) [or may be dedicated to USART1]
|
||||
|
||||
# Other stepper drivers connection
|
||||
|
||||
## DRV8825
|
||||
Solder jumpers E2, B and A to connect ~RST and ~SLP to 3.3V.
|
||||
# Stepper drivers connection
|
||||
|
||||
Microstepping selection produced by soldering H2 (bit0), G2 (bit1) and/or C (bit2).
|
||||
After changing stepper type by soldering/desoldering appropriate jumpers, don't forget to change their types in settings
|
||||
(and save settings in MSU flash memory after checking it with `dumpconf`).
|
||||
|
||||
Connection diagram for soldering jumpers shown on reverse side of PCB.
|
||||
|
||||
Jumpers **A**, **B** and **C** allow to short the contacts of driver's pins 6 (CLK / DCO / ~SLEEP), 5 (PDN_UART / SDO / ~RESET) and 4
|
||||
(SPREAD / CS / M2), respectively.
|
||||
|
||||
Jumper **D1** connects MCU UART output with jumper **E1**, **D2** connects MCU MISO with same contact of **E1**.
|
||||
Jumpers **E1** and **E2** allows to pullup pin 5 of driver to be connected with 3.3V or UART/MISO.
|
||||
|
||||
Jumper **F1** allows to connect pin 4 to CS line. **F2** connects pin 4 to 3.3V.
|
||||
|
||||
Jumper **G1** connects pin 3 (MS2 / SCK / M1) to SCK line. **G2** connects this pin to 3.3V.
|
||||
|
||||
Jumper **H1** connects pin pin 2 (MS1 / SDI / M0) to MOSI line **H2** connects it to 3.3V.
|
||||
|
||||
So, depending on driver type and its mode you can solder these jumpers so, than driver can work over PDN-UART, SPI or configuration
|
||||
pins can select microstepping directly.
|
||||
|
||||
|
||||
## DRV8825 and other simplest drivers
|
||||
Solder jumpers **E2**, **B** and **A** to connect **~RST** and **~SLP** to 3.3V.
|
||||
|
||||
Microstepping selection produced by soldering **H2** (bit0), **G2** (bit1) and/or **C** (bit2).
|
||||
|
||||
## TMC2209 and other PDN-UART based
|
||||
Solder jumpers **D1** and **E1** to connect MCU UART2/UART3 to PDN-UART pin of driver. Solder jumpers **G2**/**H2** according
|
||||
address table (X - soldered, O - not soldered):
|
||||
|
||||
| Address | G2 | H2 |
|
||||
|:-------:|:-----:|:-----:|
|
||||
| 0 | **O** | **O** |
|
||||
| 1 | **O** | **X** |
|
||||
| 2 | **X** | **O** |
|
||||
| 3 | **X** | **X** |
|
||||
| 4 | **O** | **O** |
|
||||
| 5 | **O** | **X** |
|
||||
| 6 | **X** | **O** |
|
||||
| 7 | **X** | **X** |
|
||||
|
||||
## TMC2130 and other SPI based
|
||||
(not negotiated yet)
|
||||
|
||||
Solder jumpers **D2** and **E1** to connect MISO, **F1** to connect CS, **G1** for SCK and **H1** for MOSI.
|
||||
|
||||
# Protocol
|
||||
|
||||
## Errors
|
||||
Error codes are in brackets:
|
||||
|
||||
- **OK** (0) - all OK;
|
||||
- **BADPAR** (1) - bad parameter (`N`) value (e.g. greater than max available or absent);
|
||||
- **BADVAL** (2) - bad setter value (absent, text or over range);
|
||||
- **WRONGLEN** (3) - (only for CAN bus, you can't meet in text protocol) wrong CAN message length;
|
||||
- **BADCMD** (4) - unknown command, in case of USB proto user will see full command list instead of this error;
|
||||
- **CANTRUN** (5) - can't run required function.
|
||||
|
||||
## USB
|
||||
|
||||
Used simple text protocol each string should contain one command and ends with `'\n'`.
|
||||
Uppercase N at the end of command means parameter number (No of motor, button, ADC channel etc).
|
||||
Getters and action commands have simplest format `command[N]`: some commands have no parameter,
|
||||
other have two variants - with and without parameter; wariant without parameter will act on all
|
||||
parameters (e.g. getter for all buttons) - in this case `N` enclosed in square brackets.
|
||||
Setters have format `command[N] = value`. The `value` is integer number, so in case floating values
|
||||
you need to multiply it by 1000 and write result. So, voltage and temperature are measured in millivolts
|
||||
and thousandths of degC respectively.
|
||||
|
||||
Some commands (especially that have no CAN analogue) have non-standard format described later.
|
||||
They are not intended to be used in automatic control systems, only in manual mode.
|
||||
|
||||
Answer for every (excluding special) setter and getter in case of success is `command[N]=value`
|
||||
showing current value for getter or new value for setter.
|
||||
In case of error you will see one of error mesages (message `OK` with errcode=0 usually not shown).
|
||||
Also you can get such answers:
|
||||
|
||||
- `BADCMD` - wrong command (not in dictionary);
|
||||
- `BADARGS` - bad arguments format (e.g. for command `cansend` etc);
|
||||
- `FAIL` - if something wrong and parser got impermissible error code.
|
||||
|
||||
In following list letter `G` means "getter", `S` - "setter", no of them - custom USB-only command.
|
||||
The number in brackets is CAN command code. The asterisk following command means that it isn't implemented yet (and maybe
|
||||
will be never implemented).
|
||||
|
||||
### absposN (35) GS
|
||||
Absolute stepper position in steps, setter just changes current value. E.g. you want to set current position
|
||||
as zero (be carefull: `gotoz` will zero position again on a zero-point limit switch). Maximum absolute value is `maxstepsN`.
|
||||
### accelN (17) GS
|
||||
Stepper acceleration/deceleration on ramp (steps/s^2), only positive. Maximum value is `ACCELMAXSTEPS` from `flash.h`.
|
||||
### adcN (4) G
|
||||
ADC value (N=0..3).
|
||||
### buttonN (5) G
|
||||
Given (N=0..6) buttons' state. If number is right, returns two strings: `buttonN=state` (where `state` is
|
||||
`none`, `press`, `hold` or `release`) and `buttontmN=time` (where `time` is time from start of last event).
|
||||
|
||||
!!!NOTE: Button numbering starts from 0, not 1 as shown on PCB!!!
|
||||
### canerrcodes
|
||||
Print last CAN errcodes.
|
||||
Print "No errors" or last error code.
|
||||
### canfilter DATA
|
||||
CAN bus hardware filters, format: bank# FIFO# mode(M/I) num0 [num1 [num2 [num3]]] .
|
||||
By default have two filters allowing to listen any CAN ID:
|
||||
|
||||
Filter 0, FIFO0 in MASK mode: ID=0x01, MASK=0x01
|
||||
Filter 1, FIFO1 in MASK mode: ID=0x00, MASK=0x01
|
||||
|
||||
### canflood ID DATA
|
||||
Send or clear (if empty) flood message: ID byte0 ... byteN.
|
||||
On empy message return `NO ID given, send nothing!` (and stops flooding), or `Message parsed OK`.
|
||||
### canfloodT N
|
||||
Flood period, N in milliseconds (N >= 0ms).
|
||||
### canid [ID]
|
||||
Get or set CAN ID of device. Default CAN ID is "1".
|
||||
### canignore [ID]
|
||||
Software ignore list (max 10 IDs), negative to delete all, non-negative to add next.
|
||||
### canincrflood ID
|
||||
Send incremental flood message with given ID. Message have uint32_t little endian type and increments
|
||||
for each packet starting from 0. Empty command stops flooding (`canflood` too).
|
||||
### canpause
|
||||
Pause filtered IN packets displaying. Returns `Pause CAN messages`.
|
||||
### canreinit
|
||||
Reinit CAN with last settings. Returns `OK`.
|
||||
### canresume
|
||||
Resume filtered IN packets displaying, returns `RESUME CAN messages`.
|
||||
### cansend ID [data]
|
||||
Send data over CAN with given ID. If `data` is omitted, send empty message.
|
||||
In case of absence of `ACK` you can get message `CAN bus is off, try to restart it`.
|
||||
### canspeed N
|
||||
CAN bus speed (in kbps, 50 <= N <= 1500)
|
||||
In case of setter, store new speed value in global parameters (and if you call `saveconf` later, it will be saved in flash memory).
|
||||
### canstat
|
||||
Get CAN bus status: values of registers `CAN->MSR`, `CAN->TSR`, `CAN->RF0R` and `CAN->RF1F`.
|
||||
### diagn[N] (37) G *
|
||||
DIAG state of motor N (or all)\n"
|
||||
### drvtypeN (45) GS
|
||||
Nth driver type (0 - only step/dir, 1 - UART, 2 - SPI, 3 - reserved). This parameter is taken from `.drvtype` bits of `motflags` settings parameter.
|
||||
### dumperr
|
||||
Dump error codes. Returns:
|
||||
|
||||
Error codes:
|
||||
0 - OK
|
||||
1 - BADPAR
|
||||
2 - BADVAL
|
||||
3 - WRONGLEN
|
||||
4 - BADCMD
|
||||
5 - CANTRUN
|
||||
|
||||
### dumpcmd
|
||||
Dump command codes. Returns all list of CAN bus command codes.
|
||||
### dumpconf
|
||||
Dump current configuration. Returns a lot of information both common (like CAN bus speed, ID and so on) and
|
||||
for each motor driver. You can call independeng getters for each of this parameter.
|
||||
### dumpmotflags
|
||||
Dump motor flags' bits (for `motflagsN`) and reaction to limit switches (`eswreact`) values:
|
||||
|
||||
Motor flags:
|
||||
bit0 - 0: reverse - invert motor's rotation
|
||||
bit1 - 1: [reserved]
|
||||
bit2 - 2: [reserved]
|
||||
bit3 - 3: donthold - clear motor's power after stop
|
||||
bit4 - 4: eswinv - inverse end-switches (1->0 instead of 0->1)
|
||||
bit5 - 5: [reserved]
|
||||
bit6 - 6,7: drvtype - driver type (0 - only step/dir, 1 - UART, 2 - SPI, 3 - reserved)
|
||||
End-switches reaction:
|
||||
0 - ignore end-switches
|
||||
1 - stop @ esw in any moving direction
|
||||
2 - stop only when moving in given direction (e.g. to minus @ESW0)
|
||||
|
||||
### dumpstates
|
||||
Dump motors' state codes (for getter `stateN`):
|
||||
|
||||
Motor's state codes:
|
||||
0 - relax
|
||||
1 - acceleration
|
||||
2 - moving
|
||||
3 - moving at lowest speed
|
||||
4 - deceleration
|
||||
5 - stalled (not used here!)
|
||||
6 - error
|
||||
|
||||
### emstop[N] (29 with `N` and 31 without)
|
||||
Emergency stop Nth motor or all (if `N` absent). Returns `OK` or error text.
|
||||
|
||||
"eraseflash [=N] (38) erase flash data storage (full or only N'th page of it)\n"
|
||||
"esw[N] (6) G end-switches state\n"
|
||||
"eswreactN (24) GS end-switches reaction (0 - ignore, 1 - stop@any, 2 - stop@zero)\n"
|
||||
"gotoN (26) GS move motor to given absolute position\n"
|
||||
"gotozN (32) find zero position & refresh counters\n"
|
||||
"gpioconfN* - GS GPIO configuration (0 - PUin, 1 - PPout, 2 - ODout), N=0..2\n"
|
||||
"gpioN* (12) GS GPIO values, N=0..2\n"
|
||||
help
|
||||
"maxspeedN (18) GS max speed (steps per sec)\n"
|
||||
"maxstepsN (21) GS max steps (from zero ESW)\n"
|
||||
"mcut (7) G MCU T\n"
|
||||
"mcuvdd (8) G MCU Vdd\n"
|
||||
"microstepsN (16) GS microsteps settings (2^0..2^9)\n"
|
||||
"minspeedN (19) min speed (steps per sec)\n"
|
||||
"motcurrentN (46) GS motor current (1..32 for 1/32..32/32 of max current)\n"
|
||||
"motflagsN (23) motorN flags\n"
|
||||
"motmul* (36) GS external multiplexer status (<0 - disable, 0..7 - enable and set address)\n"
|
||||
"motno (44) GS motor number for next `pdn` commands\n"
|
||||
"motreinit (25) re-init motors after configuration changed\n"
|
||||
"pdnN (43) GS read/write TMC2209 registers over uart @ motor0\n"
|
||||
"ping (1)- echo given command back\n"
|
||||
"relposN (27) GS relative move (get remaining)\n"
|
||||
"relslowN (28) GS like 'relpos' but with slowest speed\n"
|
||||
"reset (9) software reset\n"
|
||||
"saveconf (13) save current configuration\n"
|
||||
"screen* - GS screen enable (1) or disable (0)\n"
|
||||
"speedlimit (20) G limiting speed for current microsteps setting\n"
|
||||
"stateN (33) G motor state (0-relax, 1-accel, 2-move, 3-mvslow, 4-decel, 5-stall, 6-err)\n"
|
||||
"stopN (30) stop motor with deceleration\n"
|
||||
"time (10) G time from start (ms)\n"
|
||||
"tmcbus* - GS TMC control bus (0 - USART, 1 - SPI)\n"
|
||||
"udata* (39) GS data by usart in slave mode (text strings, '\\n'-terminated)\n"
|
||||
"usartstatus* (40) GS status of USART1 (0 - off, 1 - master, 2 - slave)\n"
|
||||
"vdrive (41) G approx voltage on Vdrive\n"
|
||||
"vfive (42) G approx voltage on 5V bus\n"
|
||||
|
||||
## CAN bus
|
||||
Default CAN ID is 1.
|
||||
@ -37,6 +37,7 @@ static int8_t first_nonfree_idx = -1; // index of first data cell
|
||||
static uint16_t oldspeed = 100; // speed of last init
|
||||
uint32_t floodT = FLOOD_PERIOD_MS; // flood period in ms
|
||||
static uint8_t incrflood = 0; // ==1 for incremental flooding
|
||||
static uint32_t incrmessagectr = 0; // counter for incremental flooding
|
||||
|
||||
static uint32_t last_err_code = 0;
|
||||
static CAN_status can_status = CAN_STOP;
|
||||
@ -130,7 +131,7 @@ so if TBS1=4 and TBS2=3, sum=8, bit sampling freq is 48/8 = 6MHz
|
||||
void CAN_setup(uint16_t speed){
|
||||
if(speed == 0) speed = oldspeed;
|
||||
else if(speed < 50) speed = 50;
|
||||
else if(speed > 3000) speed = 3000;
|
||||
else if(speed > 1500) speed = 1500;
|
||||
oldspeed = speed;
|
||||
uint32_t tmout = 10000;
|
||||
/* Enable the peripheral clock CAN */
|
||||
@ -240,7 +241,6 @@ void CAN_proc(){
|
||||
CAN_setup(0);
|
||||
}
|
||||
static uint32_t lastFloodTime = 0;
|
||||
static uint32_t incrmessagectr = 0;
|
||||
if(flood_msg && (Tms - lastFloodTime) >= floodT){ // flood every ~5ms
|
||||
lastFloodTime = Tms;
|
||||
CAN_send(flood_msg->data, flood_msg->length, flood_msg->ID);
|
||||
@ -305,8 +305,11 @@ CAN_status CAN_send(uint8_t *msg, uint8_t len, uint16_t target_id){
|
||||
}
|
||||
|
||||
void CAN_flood(CAN_message *msg, int incr){
|
||||
if(incr){ incrflood = 1; return; }
|
||||
incrflood = 0;
|
||||
if(incr){
|
||||
incrmessagectr = 0;
|
||||
incrflood = 1;
|
||||
return;
|
||||
}else incrflood = 0;
|
||||
if(!msg) flood_msg = NULL;
|
||||
else{
|
||||
memcpy(&loc_flood_msg, msg, sizeof(CAN_message));
|
||||
|
||||
@ -108,6 +108,11 @@ errcodes cu_emstop(uint8_t _U_ par, int32_t _U_ *val){
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
errcodes cu_emstopall(uint8_t _U_ par, int32_t _U_ *val){
|
||||
for(int i = 0; i < MOTORSNO; ++i) emstopmotor(i);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
errcodes cu_eraseflash(uint8_t _U_ par, int32_t _U_ *val){
|
||||
NOPARCHK(par);
|
||||
if(ISSETTER(par)){
|
||||
|
||||
@ -113,6 +113,7 @@ errcodes cu_canid(uint8_t par, int32_t *val);
|
||||
errcodes cu_diagn(uint8_t par, int32_t *val);
|
||||
errcodes cu_drvtype(uint8_t par, int32_t *val);
|
||||
errcodes cu_emstop(uint8_t par, int32_t *val);
|
||||
errcodes cu_emstopall(uint8_t par, int32_t *val);
|
||||
errcodes cu_eraseflash(uint8_t par, int32_t *val);
|
||||
errcodes cu_esw(uint8_t par, int32_t *val);
|
||||
errcodes cu_eswreact(uint8_t par, int32_t *val);
|
||||
|
||||
@ -32,12 +32,12 @@ static const uint32_t FLASH_blocksize = (uint32_t)&_BLOCKSIZE;
|
||||
// max amount of Config records stored (will be recalculate in flashstorage_init()
|
||||
static uint32_t maxCnum = 1024 / sizeof(user_conf); // can't use blocksize here
|
||||
|
||||
#define DEFMF {.donthold = 1, .drvtype = DRVTYPE_UART}
|
||||
#define DEFMF {.donthold = 1, .drvtype = DRVTYPE_SIMPLE}
|
||||
|
||||
#define USERCONF_INITIALIZER { \
|
||||
.userconf_sz = sizeof(user_conf) \
|
||||
,.CANspeed = 100 \
|
||||
,.CANID = 0xaa \
|
||||
,.CANID = 1 \
|
||||
,.microsteps = {32,32,32,32,32,32,32,32}\
|
||||
,.accel = {500,500,500,500,500,500,500,500} \
|
||||
,.maxspd = {2000,2000,2000,2000,2000,2000,2000,2000} \
|
||||
@ -203,8 +203,8 @@ int erase_storage(int npage){
|
||||
|
||||
int fn_dumpconf(uint32_t _U_ hash, char _U_ *args){ // "dumpconf" (3271513185)
|
||||
#ifdef EBUG
|
||||
USB_sendstr("flashsize="); printu(FLASH_SIZE); USB_putbyte('*');
|
||||
printu(FLASH_blocksize); USB_putbyte('='); printu(FLASH_SIZE*FLASH_blocksize);
|
||||
USB_sendstr("flashsize="); printu(FLASH_SIZE); USB_sendstr("kB\nblocksize=");
|
||||
printu(FLASH_blocksize);
|
||||
newline();
|
||||
#endif
|
||||
USB_sendstr("userconf_addr="); printuhex((uint32_t)Flash_Data);
|
||||
@ -230,7 +230,7 @@ int fn_dumpconf(uint32_t _U_ hash, char _U_ *args){ // "dumpconf" (3271513185)
|
||||
printu(the_conf.motcurrent[i]);
|
||||
PROPNAME("motflags");
|
||||
printuhex(*((uint8_t*)&the_conf.motflags[i]));
|
||||
PROPNAME("eswreaction");
|
||||
PROPNAME("eswreact");
|
||||
printu(the_conf.ESW_reaction[i]);
|
||||
#undef PROPNAME
|
||||
}
|
||||
|
||||
@ -63,6 +63,7 @@ typedef struct{
|
||||
* struct to save user configurations
|
||||
*/
|
||||
typedef struct __attribute__((packed, aligned(4))){
|
||||
uint32_t maxsteps[MOTORSNO]; // maximal amount of steps
|
||||
uint16_t userconf_sz; // "magick number"
|
||||
uint16_t CANspeed; // default CAN speed
|
||||
uint16_t CANID; // identifier
|
||||
@ -70,11 +71,9 @@ typedef struct __attribute__((packed, aligned(4))){
|
||||
uint16_t accel[MOTORSNO]; // acceleration/deceleration (steps/s^2)
|
||||
uint16_t maxspd[MOTORSNO]; // max motor speed (steps per second)
|
||||
uint16_t minspd[MOTORSNO]; // min motor speed (steps per second)
|
||||
uint32_t maxsteps[MOTORSNO]; // maximal amount of steps
|
||||
motflags_t motflags[MOTORSNO]; // motor's flags
|
||||
uint8_t ESW_reaction[MOTORSNO]; // end-switches reaction (esw_react)
|
||||
uint8_t motcurrent[MOTORSNO]; // IRUN as fraction of max current (1..32)
|
||||
uint8_t isSPI; // ==1 if there's SPI drivers instead of UART
|
||||
} user_conf;
|
||||
|
||||
extern user_conf the_conf; // global user config (read from FLASH to RAM)
|
||||
|
||||
@ -76,7 +76,7 @@ static IRQn_Type motirqs[MOTORSNO] = {
|
||||
// return two bits: 0 - ESW0, 1 - ESW1 (if inactive -> 1; if active -> 0)
|
||||
uint8_t ESW_state(uint8_t MOTno){
|
||||
uint8_t val = 0;
|
||||
if(the_conf.isSPI){ // only ESW0 used
|
||||
if(the_conf.motflags[MOTno].drvtype == DRVTYPE_SPI){ // only ESW0 used
|
||||
val = ((ESWports[MOTno][0]->IDR & ESWpins[MOTno][0]) ? 1 : 0);
|
||||
if(the_conf.motflags[MOTno].eswinv) val ^= 1;
|
||||
return val;
|
||||
|
||||
@ -170,14 +170,13 @@ static char *fnname(const char *cmd){
|
||||
|
||||
static const char *fhdr =
|
||||
"int parsecmd(const char *str){\n\
|
||||
char cmd[CMD_MAXLEN + 1];\n\
|
||||
if(!str || !*str) return RET_CMDNOTFOUND;\n\
|
||||
int i = 0;\n\
|
||||
while(*str > '@' && i < CMD_MAXLEN){ cmd[i++] = *str++; }\n\
|
||||
cmd[i] = 0;\n\
|
||||
while(*str > '@' && i < CMD_MAXLEN){ lastcmd[i++] = *str++; }\n\
|
||||
lastcmd[i] = 0;\n\
|
||||
while(*str && *str <= ' ') ++str;\n\
|
||||
char *args = (char*) str;\n\
|
||||
uint32_t h = hashf(cmd);\n\
|
||||
uint32_t h = hashf(lastcmd);\n\
|
||||
switch(h){\n\n"
|
||||
;
|
||||
static const char *ffooter =
|
||||
@ -195,12 +194,15 @@ static const char *headercontent =
|
||||
#endif\n\n\
|
||||
#define CMD_MAXLEN (32)\n\n\
|
||||
enum{\n\
|
||||
RET_HELP = -3,\n\
|
||||
RET_CMDNOTFOUND = -2,\n\
|
||||
RET_WRONGCMD = -1,\n\
|
||||
RET_BAD = 0,\n\
|
||||
RET_GOOD = 1\n\
|
||||
RET_GOOD = 0,\n\
|
||||
RET_BAD = 1\n\
|
||||
};\n\n\
|
||||
int parsecmd(const char *cmdwargs);\n\n";
|
||||
int parsecmd(const char *cmdwargs);\n\n\
|
||||
extern char lastcmd[];\n\n";
|
||||
|
||||
static const char *sw =
|
||||
" case CMD_%s:\n\
|
||||
return fn_%s(h, args);\n\
|
||||
@ -213,7 +215,8 @@ static const char *srchdr =
|
||||
#include \"%s\"\n\n\
|
||||
#ifndef WAL\n\
|
||||
#define WAL __attribute__ ((weak, alias (\"__f1\")))\n\
|
||||
#endif\n\nstatic int __f1(uint32_t _U_ h, char _U_ *a){return 1;}\n\n"
|
||||
#endif\n\nstatic int __f1(uint32_t _U_ h, char _U_ *a){return 1;}\n\n\
|
||||
char lastcmd[CMD_MAXLEN + 1];\n\n"
|
||||
;
|
||||
|
||||
static void build(strhash *H, int hno, int hlen){
|
||||
|
||||
@ -8,10 +8,10 @@
|
||||
#define WAL __attribute__ ((weak, alias ("__f1")))
|
||||
#endif
|
||||
|
||||
char lastcmd[CMD_MAXLEN + 1];
|
||||
|
||||
static int __f1(uint32_t _U_ h, char _U_ *a){return 1;}
|
||||
|
||||
char lastcmd[CMD_MAXLEN + 1];
|
||||
|
||||
int fn_abspos(uint32_t _U_ hash, char _U_ *args) WAL; // "abspos" (3056382221)
|
||||
|
||||
int fn_accel(uint32_t _U_ hash, char _U_ *args) WAL; // "accel" (1490521981)
|
||||
@ -76,6 +76,8 @@ int fn_gpio(uint32_t _U_ hash, char _U_ *args) WAL; // "gpio" (4286324660)
|
||||
|
||||
int fn_gpioconf(uint32_t _U_ hash, char _U_ *args) WAL; // "gpioconf" (1309721562)
|
||||
|
||||
int fn_help(uint32_t _U_ hash, char _U_ *args) WAL; // "help" (4288288686)
|
||||
|
||||
int fn_maxspeed(uint32_t _U_ hash, char _U_ *args) WAL; // "maxspeed" (1498078812)
|
||||
|
||||
int fn_maxsteps(uint32_t _U_ hash, char _U_ *args) WAL; // "maxsteps" (1506667002)
|
||||
@ -244,6 +246,9 @@ int parsecmd(const char *str){
|
||||
case CMD_GPIOCONF:
|
||||
return fn_gpioconf(h, args);
|
||||
break;
|
||||
case CMD_HELP:
|
||||
return fn_help(h, args);
|
||||
break;
|
||||
case CMD_MAXSPEED:
|
||||
return fn_maxspeed(h, args);
|
||||
break;
|
||||
|
||||
@ -5,10 +5,11 @@
|
||||
#define CMD_MAXLEN (32)
|
||||
|
||||
enum{
|
||||
RET_HELP = -3,
|
||||
RET_CMDNOTFOUND = -2,
|
||||
RET_WRONGCMD = -1,
|
||||
RET_BAD = 0,
|
||||
RET_GOOD = 1
|
||||
RET_GOOD = 0,
|
||||
RET_BAD = 1
|
||||
};
|
||||
|
||||
int parsecmd(const char *cmdwargs);
|
||||
@ -47,6 +48,7 @@ extern char lastcmd[];
|
||||
#define CMD_GOTOZ (3178103736)
|
||||
#define CMD_GPIO (4286324660)
|
||||
#define CMD_GPIOCONF (1309721562)
|
||||
#define CMD_HELP (4288288686)
|
||||
#define CMD_MAXSPEED (1498078812)
|
||||
#define CMD_MAXSTEPS (1506667002)
|
||||
#define CMD_MCUT (4022718)
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
"gotozN - find zero position & refresh counters\n"
|
||||
"gpioconfN* - GS GPIO configuration (0 - PUin, 1 - PPout, 2 - ODout), N=0..2\n"
|
||||
"gpioN* - GS GPIO values, N=0..2\n"
|
||||
"help - print this help\n"
|
||||
"maxspeedN - GS max speed (steps per sec)\n"
|
||||
"maxstepsN - GS max steps (from zero ESW)\n"
|
||||
"mcut - G MCU T\n"
|
||||
|
||||
@ -8,3 +8,5 @@ gcc hdr.c test.c strfunc.c -o test
|
||||
./test "esw45 = some text"
|
||||
./test "goto 55 = "
|
||||
./test "stop 3256"
|
||||
./test "mcut"
|
||||
|
||||
|
||||
BIN
F3:F303/Multistepper/hashgen/test
Executable file
BIN
F3:F303/Multistepper/hashgen/test
Executable file
Binary file not shown.
@ -7,9 +7,9 @@
|
||||
|
||||
static int noargs(uint32_t hash){
|
||||
switch(hash){
|
||||
case CMD_REBOOT: printf("REBOOT\n"); break;
|
||||
case CMD_RESET: printf("REBOOT\n"); break;
|
||||
case CMD_TIME: printf("TIME!\n"); break;
|
||||
case CMD_TEMP: printf("Temp\n"); break;
|
||||
case CMD_MCUT: printf("Temp\n"); break;
|
||||
default: printf("Unknown hash 0x%x\n", hash); return 0;
|
||||
}
|
||||
return 1;
|
||||
@ -30,7 +30,7 @@ static int withparno(uint32_t hash, char *args){
|
||||
switch(hash){
|
||||
case CMD_ESW: fname = "ESW"; break;
|
||||
case CMD_GOTO: fname = "GOTO"; break;
|
||||
case CMD_POS: fname = "POS"; break;
|
||||
case CMD_ABSPOS: fname = "ABSPOS"; break;
|
||||
case CMD_STOP: fname = "STOP"; break;
|
||||
default: fname = "unknown";
|
||||
}
|
||||
|
||||
@ -30,6 +30,7 @@ goto
|
||||
gotoz
|
||||
gpioconf
|
||||
gpio
|
||||
help
|
||||
maxspeed
|
||||
maxsteps
|
||||
mcut
|
||||
|
||||
Binary file not shown.
@ -288,6 +288,7 @@ int fn_canfilter(uint32_t _U_ hash, char *args){
|
||||
|
||||
int fn_canflood(uint32_t _U_ hash, char *args){
|
||||
CAN_flood(parseCANmsg(args), 0);
|
||||
USB_sendstr("Simple flooding is ON (send with empty ID to stop)\n");
|
||||
return RET_GOOD;
|
||||
}
|
||||
|
||||
@ -333,8 +334,8 @@ int fn_canerrcodes(uint32_t _U_ hash, char _U_ *args){
|
||||
}
|
||||
|
||||
int fn_canincrflood(uint32_t _U_ hash, char _U_ *args){
|
||||
CAN_flood(NULL, 1);
|
||||
USB_sendstr("Incremental flooding is ON ('F' to off)\n");
|
||||
CAN_flood(parseCANmsg(args), 1);
|
||||
USB_sendstr("Incremental flooding is ON (send with empty ID to stop)\n");
|
||||
return RET_GOOD;
|
||||
}
|
||||
|
||||
@ -346,18 +347,17 @@ int fn_canspeed(uint32_t _U_ hash, char _U_ *args){
|
||||
return RET_GOOD;
|
||||
}
|
||||
if(N < 50){
|
||||
USB_sendstr("canspeed=");
|
||||
USB_sendstr(u2str(CAN_speed()));
|
||||
newline();
|
||||
USND("Lower speed is 50kbps");
|
||||
return RET_GOOD;
|
||||
}else if(N > 3000){
|
||||
USB_sendstr("Highest speed is 3000kbps");
|
||||
}else if(N > 1500){
|
||||
USND("Highest speed is 1500kbps");
|
||||
return RET_GOOD;
|
||||
}
|
||||
CAN_reinit((uint16_t)N);
|
||||
// theconf.canspeed = N;
|
||||
uint32_t regval = 4500 / N;
|
||||
the_conf.CANspeed = 4500 * regval;
|
||||
USB_sendstr("Reinit CAN bus with speed ");
|
||||
printu(N); USB_sendstr("kbps"); newline();
|
||||
printu(the_conf.CANspeed); USB_sendstr("kbps"); newline();
|
||||
return RET_GOOD;
|
||||
}
|
||||
|
||||
@ -529,7 +529,8 @@ static int canusb_function(uint32_t hash, char *args){
|
||||
}
|
||||
USB_sendstr("button"); USB_putbyte('0'+PARBASE(par));
|
||||
USB_putbyte('='); USB_sendstr(kstate);
|
||||
USB_sendstr("\nbuttontm="); USB_sendstr(u2str(val));
|
||||
USB_sendstr("\nbuttontm"); USB_putbyte('0'+PARBASE(par));
|
||||
USB_putbyte('='); USB_sendstr(u2str(val));
|
||||
newline();
|
||||
return RET_GOOD;
|
||||
break;
|
||||
@ -552,7 +553,9 @@ static int canusb_function(uint32_t hash, char *args){
|
||||
e = cu_drvtype(par, &val);
|
||||
break;
|
||||
case CMD_EMSTOP:
|
||||
e = cu_emstop(par, &val);
|
||||
if(par == CANMESG_NOPAR) e = cu_emstopall(par, &val);
|
||||
else e = cu_emstop(par, &val);
|
||||
if(e == ERR_OK){ USND("OK"); return RET_GOOD;}
|
||||
break;
|
||||
case CMD_ESWREACT:
|
||||
e = cu_eswreact(par, &val);
|
||||
@ -682,6 +685,7 @@ int fn_goto(uint32_t _U_ hash, char _U_ *args) AL; //* "goto" (4286309438)
|
||||
int fn_gotoz(uint32_t _U_ hash, char _U_ *args) AL; //* "gotoz" (3178103736)
|
||||
int fn_gpio(uint32_t _U_ hash, char _U_ *args) AL; //* "gpio" (4286324660)
|
||||
int fn_gpioconf(uint32_t _U_ hash, char _U_ *args) AL; //* "gpioconf" (1309721562)
|
||||
int fn_help(uint32_t _U_ hash, char _U_ *args){return RET_HELP;} // "help" (4288288686)
|
||||
int fn_maxspeed(uint32_t _U_ hash, char _U_ *args) AL; //* "maxspeed" (1498078812)
|
||||
int fn_maxsteps(uint32_t _U_ hash, char _U_ *args) AL; //* "maxsteps" (1506667002)
|
||||
int fn_mcut(uint32_t _U_ hash, char _U_ *args) AL; // "mcut" (4022718)
|
||||
@ -717,8 +721,9 @@ int fn_vfive(uint32_t _U_ hash, char _U_ *args) AL; // "vfive" (3017477285)
|
||||
const char *cmd_parser(const char *txt){
|
||||
int ret = parsecmd(txt);
|
||||
switch(ret){
|
||||
case RET_CMDNOTFOUND: return helpstring; break;
|
||||
case RET_WRONGCMD: return "Wrong command parameters\n"; break;
|
||||
case RET_HELP: return helpstring; break;
|
||||
case RET_CMDNOTFOUND: return "BADCMD\n"; break;
|
||||
case RET_WRONGCMD: return "BADARGS\n"; break;
|
||||
case RET_GOOD: return NULL; break;
|
||||
default: return "FAIL\n"; break;
|
||||
}
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
#define BUILD_NUMBER "114"
|
||||
#define BUILD_DATE "2024-08-15"
|
||||
#define BUILD_NUMBER "119"
|
||||
#define BUILD_DATE "2024-08-16"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user