mirror of
https://github.com/eddyem/stm32samples.git
synced 2025-12-06 10:45:11 +03:00
Add PDNuart starting interface (not tested & not yet added to main proto)
This commit is contained in:
parent
59d8f8f515
commit
8b6a3e7c20
@ -221,4 +221,13 @@ _SW_ used as debugging/sewing; also (I remember about USB pullup only after end
|
|||||||
|
|
||||||
* ADC1 - DMA1_ch1
|
* ADC1 - DMA1_ch1
|
||||||
* ADC2 - DMA2_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).
|
||||||
@ -124,7 +124,8 @@ TRUE_INLINE void gpio_setup(){
|
|||||||
| MODER_AF(14) | MODER_AF(15);
|
| 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->OSPEEDR = OSPEED_HI(0) | OSPEED_HI(5) | OSPEED_HI(8) | OSPEED_MED(13) | OSPEED_MED(14) | OSPEED_MED(15);
|
||||||
GPIOB->OTYPER = 0;
|
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->ODR = 0;
|
||||||
GPIOC->AFR[0] = AFRf(7, 4) | AFRf(7, 5) | AFRf(4, 6);
|
GPIOC->AFR[0] = AFRf(7, 4) | AFRf(7, 5) | AFRf(4, 6);
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
#include "can.h"
|
#include "can.h"
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
|
#include "pdnuart.h"
|
||||||
#include "proto.h"
|
#include "proto.h"
|
||||||
#include "steppers.h"
|
#include "steppers.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
@ -86,5 +87,6 @@ int main(void){
|
|||||||
if(ans) USB_sendstr(ans);
|
if(ans) USB_sendstr(ans);
|
||||||
}
|
}
|
||||||
process_keys();
|
process_keys();
|
||||||
|
pdnuart_poll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@ -15,6 +15,8 @@ hashgen/hdr.c
|
|||||||
hashgen/hdr.h
|
hashgen/hdr.h
|
||||||
hashgen/test.c
|
hashgen/test.c
|
||||||
main.c
|
main.c
|
||||||
|
pdnuart.c
|
||||||
|
pdnuart.h
|
||||||
proto.c
|
proto.c
|
||||||
proto.h
|
proto.h
|
||||||
ringbuffer.c
|
ringbuffer.c
|
||||||
|
|||||||
230
F3:F303/Multistepper/pdnuart.c
Normal file
230
F3:F303/Multistepper/pdnuart.c
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the multistepper project.
|
||||||
|
* Copyright 2023 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 <stm32f3.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
26
F3:F303/Multistepper/pdnuart.h
Normal file
26
F3:F303/Multistepper/pdnuart.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the multistepper project.
|
||||||
|
* Copyright 2023 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
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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);
|
||||||
@ -1,2 +1,2 @@
|
|||||||
#define BUILD_NUMBER "80"
|
#define BUILD_NUMBER "82"
|
||||||
#define BUILD_DATE "2023-02-24"
|
#define BUILD_DATE "2023-02-25"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user