diff --git a/F3:F303/Multistepper/Readme.md b/F3:F303/Multistepper/Readme.md index 64abe75..d3f5790 100644 --- a/F3:F303/Multistepper/Readme.md +++ b/F3:F303/Multistepper/Readme.md @@ -221,4 +221,13 @@ _SW_ used as debugging/sewing; also (I remember about USB pullup only after end * 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. + +Microstepping selection produced by soldering H2 (bit0), G2 (bit1) and/or C (bit2). \ No newline at end of file diff --git a/F3:F303/Multistepper/hardware.c b/F3:F303/Multistepper/hardware.c index 832826b..ae1433e 100644 --- a/F3:F303/Multistepper/hardware.c +++ b/F3:F303/Multistepper/hardware.c @@ -124,7 +124,8 @@ TRUE_INLINE void gpio_setup(){ | MODER_AF(14) | MODER_AF(15); GPIOB->OSPEEDR = OSPEED_HI(0) | OSPEED_HI(5) | OSPEED_HI(8) | OSPEED_MED(13) | OSPEED_MED(14) | OSPEED_MED(15); GPIOB->OTYPER = 0; - GPIOB->PUPDR = PUPD_PU(7) | PUPD_PU(9) | PUPD_PU(11); + // USART2_Tx (PB3) and USART3_Tx (PB10) are also pullup + GPIOB->PUPDR = PUPD_PU(3) | PUPD_PU(7) | PUPD_PU(9) | PUPD_PU(7) | PUPD_PU(11); GPIOC->ODR = 0; GPIOC->AFR[0] = AFRf(7, 4) | AFRf(7, 5) | AFRf(4, 6); diff --git a/F3:F303/Multistepper/main.c b/F3:F303/Multistepper/main.c index 9570776..5ab68e5 100644 --- a/F3:F303/Multistepper/main.c +++ b/F3:F303/Multistepper/main.c @@ -21,6 +21,7 @@ #include "can.h" #include "flash.h" #include "hardware.h" +#include "pdnuart.h" #include "proto.h" #include "steppers.h" #include "usb.h" @@ -86,5 +87,6 @@ int main(void){ if(ans) USB_sendstr(ans); } process_keys(); + pdnuart_poll(); } } diff --git a/F3:F303/Multistepper/multistepper.bin b/F3:F303/Multistepper/multistepper.bin index 3864bcf..36b0a98 100755 Binary files a/F3:F303/Multistepper/multistepper.bin and b/F3:F303/Multistepper/multistepper.bin differ diff --git a/F3:F303/Multistepper/multistepper.files b/F3:F303/Multistepper/multistepper.files index 2e2b09c..0202d6d 100644 --- a/F3:F303/Multistepper/multistepper.files +++ b/F3:F303/Multistepper/multistepper.files @@ -15,6 +15,8 @@ hashgen/hdr.c hashgen/hdr.h hashgen/test.c main.c +pdnuart.c +pdnuart.h proto.c proto.h ringbuffer.c diff --git a/F3:F303/Multistepper/pdnuart.c b/F3:F303/Multistepper/pdnuart.c new file mode 100644 index 0000000..4621c47 --- /dev/null +++ b/F3:F303/Multistepper/pdnuart.c @@ -0,0 +1,230 @@ +/* + * This file is part of the multistepper project. + * Copyright 2023 Edward V. Emelianov . + * + * 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 . + */ + +#include + +#include "hardware.h" +#include "proto.h" + +extern volatile uint32_t Tms; + +#define MAXBUFLEN (8) +// Rx timeout, ms +#define PDNUART_TIMEOUT (20) + +// buffers format: 0 - sync+reserved, 1 - address (0..3 - slave, 0xff - master) +// 2 - register<<1 | RW, 3 - CRC (r) or [ 3..6 - MSB data, 7 - CRC ] +// buf[0] - USART2, buf[1] - USART3 +static uint8_t inbuf[2][MAXBUFLEN], outbuf[2][MAXBUFLEN]; +static uint8_t Taccess[2] = {0}; // last access time +static int curslaveaddr[2] = {-1, -1}; // current slave address for each USART (0..3) +static uint8_t notfound = 0; // not found mask (LSB - 0, MSB - 7) +static uint8_t readrq[2] = {0}; // ==1 for read request (after send wait to read) + +// UART states +typedef enum{ + PDU_IDLE, + PDU_TX, + PDU_TXREADY, + PDU_RX, + PDU_RXREADY +} pdnuart_state; +static pdnuart_state state[2] = {PDU_IDLE, PDU_IDLE}; + +// datalen == 3 for read request or 7 for writing +static void calcCRC(int no, int datalen){ + uint8_t crc = 0; + for(int i = 0; i < datalen; ++i){ + uint8_t currentByte = outbuf[no][i]; + for(int j = 0; j < 8; ++j){ + if((crc >> 7) ^ (currentByte & 0x01)) crc = (crc << 1) ^ 0x07; + else crc <<= 1; + currentByte = currentByte >> 1; + } + } + outbuf[no][datalen] = crc; +} + +static volatile DMA_Channel_TypeDef *TxDMA[2] = {DMA1_Channel7, DMA1_Channel2}; +static volatile DMA_Channel_TypeDef *RxDMA[2] = {DMA1_Channel6, DMA1_Channel3}; +static volatile USART_TypeDef *USART[2] = {USART2, USART3}; + +static void setup_usart(int no){ + USART[no]->ICR = 0xffffffff; // clear all flags + TxDMA[no]->CCR = 0; + TxDMA[no]->CPAR = (uint32_t) &USART[no]->TDR; // periph + TxDMA[no]->CCR |= DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE; // 8bit, mem++, mem->per, transcompl irq + RxDMA[no]->CCR = 0; + RxDMA[no]->CPAR = (uint32_t) &USART[no]->RDR; // periph + RxDMA[no]->CCR |= DMA_CCR_MINC | DMA_CCR_TCIE; // 8bit, mem++, per->mem, transcompl irq + USART[no]->BRR = 72000000 / 256000; // 256 kbaud + USART[no]->CR3 = USART_CR3_DMAT | USART_CR3_DMAR; // enable DMA Tx/Rx + USART[no]->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; // 1start,8data,nstop; enable Rx,Tx,USART + uint32_t tmout = 16000000; + while(!(USART[no]->ISR & USART_ISR_TC)){if(--tmout == 0) break;} // polling idle frame Transmission + USART[no]->ICR = 0xffffffff; // clear all flags again +} + +// USART2 (ch0..3): DMA1ch6 (Rx), DMA1_ch7 (Tx) +// USART3 (ch4..7): DMA1ch3 (Rx), DMA1_ch2 (Tx) +// pins are setting up in `hardware.c` +void pdnuart_setup(){ + RCC->APB1ENR |= RCC_APB1ENR_USART2EN | RCC_APB1ENR_USART3EN; + RCC->AHBENR |= RCC_AHBENR_DMA1EN; + setup_usart(0); + setup_usart(1); + NVIC_EnableIRQ(DMA1_Channel2_IRQn); + NVIC_EnableIRQ(DMA1_Channel3_IRQn); + NVIC_EnableIRQ(DMA1_Channel6_IRQn); + NVIC_EnableIRQ(DMA1_Channel7_IRQn); +} + +static int rwreg(uint8_t motorno, uint8_t reg, uint32_t data, int w){ + if(motorno >= MOTORSNO || reg & 0x80) return FALSE; + int no = motorno >> 2; + if(state[no] != PDU_IDLE) return FALSE; + outbuf[no][0] = 0xa0; + outbuf[no][1] = curslaveaddr[no] = motorno - (no << 2); + outbuf[no][2] = reg << 1; + int nbytes = 3; + if(w){ + outbuf[no][2] |= 1; + for(int i = 6; i > 2; --i){ + outbuf[no][i] = data & 0xff; + data >>= 8; + } + nbytes = 7; + readrq[no] = 0; + }else{ + readrq[no] = 1; + } + calcCRC(no, nbytes); + TxDMA[no]->CMAR = (uint32_t) outbuf[no]; + TxDMA[no]->CNDTR = nbytes + 1; + TxDMA[no]->CCR |= DMA_CCR_EN; // start transmission + state[no] = PDU_TX; + Taccess[no] = Tms; + return TRUE; +} + +// return FALSE if failed +int pdnuart_writereg(uint8_t motorno, uint8_t reg, uint32_t data){ + return rwreg(motorno, reg, data, 1); +} + +// return FALSE if failed +int pdnuart_readreg(uint8_t motorno, uint8_t reg){ + return rwreg(motorno, reg, 0, 0); +} + +static void disableDMA(int no){ + TxDMA[no]->CCR &= ~DMA_CCR_EN; + RxDMA[no]->CCR &= ~DMA_CCR_EN; + readrq[no] = 0; + state[no] = PDU_IDLE; +} + +static void parseRx(int no){ + USB_sendstr("Got from "); + USB_putbyte('#'); printu(curslaveaddr[no] + no*4); USB_sendstr(": "); + for(int i = 0; i < 8; ++i){ + printuhex(inbuf[no][i]); USB_putbyte(' '); + } + newline(); +} + +void pdnuart_poll(){ + for(int i = 0; i < 2; ++i){ + int showno = 0; + uint32_t time = Tms - Taccess[i]; + switch(state[i]){ + case PDU_TX: + if(time > PDNUART_TIMEOUT){ + USB_sendstr("PDN/UART timeout: Tx problem "); + showno = 1; + disableDMA(i); + } + break; + case PDU_TXREADY: + USB_sendstr("Tx ready "); + showno = 1; + break; + case PDU_RX: + if(time > PDNUART_TIMEOUT){ + USB_sendstr("PDN/UART timeout: no answer "); + notfound |= 1 << (curslaveaddr[i] + 4*i); + showno = 1; + disableDMA(i); + } + break; + case PDU_RXREADY: + parseRx(i); + state[i] = PDU_IDLE; // DMA already turned off + break; + default: // IDLE + return; + } + if(showno){ + USB_putbyte('#'); printu(curslaveaddr[i] + 4*i); newline(); + } + } +} + +// USART2 Tx complete -> prepare Rx +void dma1_channel7_isr(){ + DMA1_Channel7->CCR &= ~DMA_CCR_EN; + DMA1->IFCR |= DMA_IFCR_CTCIF7; + if(!readrq[0]){ // there was a setter + state[0] = PDU_TXREADY; + return; + } + DMA1_Channel6->CMAR = (uint32_t) inbuf[0]; + DMA1_Channel6->CCR |= DMA_CCR_EN; + DMA1_Channel6->CNDTR = MAXBUFLEN; + state[0] = PDU_RX; + Taccess[0] = Tms; +} + +// USART3 Tx complete -> prepare Rx +void dma1_channel2_isr(){ + DMA1_Channel2->CCR &= ~DMA_CCR_EN; + DMA1->IFCR |= DMA_IFCR_CTCIF2; + if(!readrq[1]){ // there was a setter + state[1] = PDU_TXREADY; + return; + } + DMA1_Channel3->CMAR = (uint32_t) inbuf[1]; + DMA1_Channel3->CCR |= DMA_CCR_EN; + DMA1_Channel3->CNDTR = MAXBUFLEN; + state[1] = PDU_RX; + Taccess[1] = Tms; +} + +// USART2 Rx complete -> set flag +void dma1_channel6_isr(){ + DMA1_Channel6->CCR &= ~DMA_CCR_EN; + DMA1->IFCR |= DMA_IFCR_CTCIF6; + state[0] = PDU_RXREADY; +} + +// USART3 Rx complete -> set flag +void dma1_channel3_isr(){ + DMA1_Channel3->CCR &= ~DMA_CCR_EN; + DMA1->IFCR |= DMA_IFCR_CTCIF3; + state[1] = PDU_RXREADY; +} diff --git a/F3:F303/Multistepper/pdnuart.h b/F3:F303/Multistepper/pdnuart.h new file mode 100644 index 0000000..8934025 --- /dev/null +++ b/F3:F303/Multistepper/pdnuart.h @@ -0,0 +1,26 @@ +/* + * This file is part of the multistepper project. + * Copyright 2023 Edward V. Emelianov . + * + * 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 . + */ + +#pragma once + +#include + +void pdnuart_poll(); +void pdnuart_setup(); +int pdnuart_writereg(uint8_t motorno, uint8_t reg, uint32_t data); +int pdnuart_readreg(uint8_t motorno, uint8_t reg); diff --git a/F3:F303/Multistepper/version.inc b/F3:F303/Multistepper/version.inc index e4c2362..7a4469e 100644 --- a/F3:F303/Multistepper/version.inc +++ b/F3:F303/Multistepper/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "80" -#define BUILD_DATE "2023-02-24" +#define BUILD_NUMBER "82" +#define BUILD_DATE "2023-02-25"