Sammy C21 support for 2 TMC2209 drivers with UART com
-
@DC42 Might be of interest.
I have now temporarily replaced the Sammy C21 with a Seeduino XIAO extending Klipper.It has no problem communicating via UART with the TMC2209 without any pullup resistor (and with the 20k pulldown intact).
I'm going to look at the UART signal later. The Duet UART transmission without the pullup is shifted somehow. I can see that it's transmitted but it's sort of shifted so that the startbits comes last in the start byte instead of first. I'll add some pictures from the logic analyzer tomorrow.
22:00:07 SG_RESULT: 00000000 22:00:07 PWM_AUTO: 000e0024 pwm_ofs_auto=36 pwm_grad_auto=14 22:00:07 PWM_SCALE: 0000001d pwm_scale_sum=29 22:00:07 PWMCONF: c80d0e24 pwm_ofs=36 pwm_grad=14 pwm_freq=1 pwm_autoscale=1 pwm_autograd=1 pwm_reg=8 pwm_lim=12 22:00:07 DRV_STATUS: c0190000 cs_actual=25 stealth=1 stst=1 22:00:07 CHOPCONF: 34030053 toff=3 hstrt=5 tbl=2 vsense=1 mres=4(16usteps) intpol=1 dedge=1 22:00:07 MSCURACT: 00f7000c cur_a=12 cur_b=247 22:00:07 MSCNT: 00000008 mscnt=8 22:00:07 TSTEP: 000fffff tstep=1048575 22:00:07 FACTORY_CONF: 0000000c fclktrim=12 22:00:07 IOIN: 21000041 enn=1 pdn_uart=1 version=0x21 22:00:07 OTP_READ: 0000000c otp_fclktrim=12 22:00:07 IFCNT: 00000008 ifcnt=8 22:00:07 GSTAT: 00000001 reset=1(Reset) 22:00:07 GCONF: 000001c0 pdn_disable=1 mstep_reg_select=1 multistep_filt=1 22:00:07 ========== Queried registers ========== 22:00:07 SGTHRS: 00000000 22:00:07 TPOWERDOWN: 00000014 tpowerdown=20 22:00:07 TPWMTHRS: 00000003 tpwmthrs=3 22:00:07 IHOLD_IRUN: 00081919 ihold=25 irun=25 iholddelay=8 22:00:07 SLAVECONF: 00000200 senddelay=2 22:00:07 ========== Write-only registers ========== 22:00:07 DUMP_TMC STEPPER=gear_stepper
With Duet and Sammy C21 and no pullup on UART-line:
With Klipper and Seeeduino XIAO and no pullup:
-
@gixxerfast I think the reason is that in the TMC22xx driver on the SAMC21 we disable the transmitter for a short while in function TmcDriverState::StartTransfer. My guess is that this sets the output to high impedance. You could probably rewrite it to just reset the receiver, if you also defer enabling the transmit DMA until the very end.
-
@dc42 Thanks (very appreciated as always), yes I've been looking at this for a while as I suspect it could "drop the line" for a short moment:
#if TMC22xx_USES_SERCOM sercom->USART.CTRLB.reg &= ~(SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN); // disable transmitter and receiver, reset receiver while (sercom->USART.SYNCBUSY.bit.CTRLB) { } #else
Not sure if it's exactly there but I was thinking of trying to alter it a bit. Not that I know what I'm doing but it's per usual
-
OK, so far so good! It's been stable for a while now so maybe I can trust it
I don't totally trust it. I had to change in a few more places.@dc42 Well, that look promising
So now (I really hope it lasts):
Driver 0: pos 80000, 80.0 steps/mm,standstill, SG min 16, read errors 0, write errors 0, ifcnt 70, reads 13761, writes 1, timeouts 0, DMA errors 0, CC errors 0, steps req 0 done 0 Driver 1: pos 574280, 574.3 steps/mm,standstill, SG min 16, read errors 0, write errors 0, ifcnt 68, reads 13762, writes 1, timeouts 0, DMA errors 0, CC errors 0, steps req 0 done 0
$ git diff src/Movement/StepperDrivers/TMC22xx.cpp diff --git a/src/Movement/StepperDrivers/TMC22xx.cpp b/src/Movement/StepperDrivers/TMC22xx.cpp index 4b8a1acb..b301af8e 100644 --- a/src/Movement/StepperDrivers/TMC22xx.cpp +++ b/src/Movement/StepperDrivers/TMC22xx.cpp @@ -1441,7 +1441,7 @@ void TmcDriverState::AbortTransfer() noexcept #if TMC22xx_USES_SERCOM DmacManager::DisableChannel(DmacChanTmcTx); DmacManager::DisableChannel(DmacChanTmcRx); - sercom->USART.CTRLB.reg &= ~(SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN); + sercom->USART.CTRLB.reg &= ~(SERCOM_USART_CTRLB_RXEN/* | SERCOM_USART_CTRLB_TXEN*/); //UER while (sercom->USART.SYNCBUSY.bit.CTRLB) { } #else uart->UART_IDR = UART_IDR_ENDRX; // disable end-of-receive interrupt @@ -1497,17 +1497,18 @@ inline void TmcDriverState::StartTransfer() noexcept regnumBeingUpdated = regNum; #if TMC22xx_USES_SERCOM - sercom->USART.CTRLB.reg &= ~(SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN); // disable transmitter and receiver, reset receiver + sercom->USART.CTRLB.reg &= ~(SERCOM_USART_CTRLB_RXEN /*| SERCOM_USART_CTRLB_TXEN*/); // disable /*transmitter <--- UER*/ and receiver, reset receiver while (sercom->USART.SYNCBUSY.bit.CTRLB) { } #else uart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX; // reset transmitter and receiver #endif const uint8_t regNumber = (regNum < WriteSpecial) ? WriteRegNumbers[regNum] : specialWriteRegisterNumber; - SetupDMASend(regNumber, writeRegisters[regNum]); // set up the DMAC + //SetupDMASend(regNumber, writeRegisters[regNum]); // set up the DMAC <---UER #if TMC22xx_USES_SERCOM dmaFinishedReason = DmaCallbackReason::none; DmacManager::EnableCompletedInterrupt(DmacChanTmcRx); - sercom->USART.CTRLB.reg |= (SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN); // enable transmitter and receiver + sercom->USART.CTRLB.reg |= (SERCOM_USART_CTRLB_RXEN /*| SERCOM_USART_CTRLB_TXEN*/); // enable transmitter and receiver <--- UER + SetupDMASend(regNumber, writeRegisters[regNum]); #else uart->UART_IER = UART_IER_ENDRX; // enable end-of-transfer interrupt uart->UART_CR = UART_CR_RXEN | UART_CR_TXEN; // enable transmitter and receiver @@ -1520,19 +1521,20 @@ inline void TmcDriverState::StartTransfer() noexcept AtomicCriticalSectionLocker lock; #if TMC22xx_USES_SERCOM - sercom->USART.CTRLB.reg &= ~(SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN); // disable transmitter and receiver, reset receiver + sercom->USART.CTRLB.reg &= ~(SERCOM_USART_CTRLB_RXEN/* | SERCOM_USART_CTRLB_TXEN*/); // disable transmitter and receiver, reset receiver while (sercom->USART.SYNCBUSY.bit.CTRLB) { } #else uart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX; // reset transmitter and receiver #endif const uint8_t readRegNumber = (registerToRead < NumReadRegisters) ? ReadRegNumbers[registerToRead] : specialReadRegisterNumber; - SetupDMARead(readRegNumber); // set up the DMAC + //SetupDMARead(readRegNumber); // set up the DMAC #if TMC22xx_USES_SERCOM dmaFinishedReason = DmaCallbackReason::none; DmacManager::EnableCompletedInterrupt(DmacChanTmcRx); - sercom->USART.CTRLB.reg |= (SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN); // enable transmitter and receiver + sercom->USART.CTRLB.reg |= (SERCOM_USART_CTRLB_RXEN/* | SERCOM_USART_CTRLB_TXEN*/); // enable transmitter and receiver + SetupDMARead(readRegNumber); #else uart->UART_IER = UART_IER_ENDRX; // enable end-of-receive interrupt uart->UART_CR = UART_CR_RXEN | UART_CR_TXEN; // enable transmitter and rec
-
-
-