diff --git a/Inc/stepper.h b/Inc/stepper.h new file mode 100644 index 0000000..39f2fdc --- /dev/null +++ b/Inc/stepper.h @@ -0,0 +1,22 @@ +#include "stm32g0b1xx.h" + +typedef struct { + GPIO_TypeDef* en_port; + uint8_t en_pin; + GPIO_TypeDef* dir_port; + uint8_t dir_pin; + GPIO_TypeDef* step_port; + uint8_t step_pin; + GPIO_TypeDef* home_port; + uint8_t home_pin; + uint8_t homed:1; + uint8_t moving:1; + int16_t pos; + int16_t speed; + int16_t ramp_to_speed; + uint32_t next_step; +} stepper_T; + +void Timer1_Init(void); +void stepper_gpio_init(); +void do_steps(); diff --git a/Inc/uart_dmx.h b/Inc/uart_dmx.h new file mode 100644 index 0000000..95a505c --- /dev/null +++ b/Inc/uart_dmx.h @@ -0,0 +1,9 @@ +#include "stm32g0b1xx.h" + +#define BUFFER_SIZE 515 + +extern uint8_t rxBuffer[BUFFER_SIZE]; +extern uint16_t rxBufferPos; + +void init_UART1_it(); +void init_UART1_dma(); diff --git a/Makefile b/Makefile index a2f03af..4270395 100644 --- a/Makefile +++ b/Makefile @@ -37,6 +37,8 @@ BUILD_DIR = build # C sources C_SOURCES = \ Src/main.c \ +Src/uart_dmx.c \ +Src/stepper.c \ Src/stm32g0xx_it.c \ Src/stm32g0xx_hal_msp.c \ Drivers/STM32G0xx_HAL_Driver/Src/stm32g0xx_hal_tim.c \ @@ -59,7 +61,7 @@ Drivers/RTT/RTT/SEGGER_RTT.c \ Drivers/RTT/RTT/SEGGER_RTT_printf.c \ Drivers/RTT/Syscalls/SEGGER_RTT_Syscalls_GCC.c \ Drivers/SystemView/SYSVIEW/SEGGER_SYSVIEW.c \ -Drivers/SystemView/Sample/NoOS/Config/Cortex-M0/SEGGER_SYSVIEW_Config_NoOS_CM0.c\ +Drivers/SystemView/Sample/NoOS/Config/Cortex-M0/SEGGER_SYSVIEW_Config_NoOS_CM0.c \ Src/system_stm32g0xx.c # ASM sources diff --git a/Src/main.c b/Src/main.c index 7ab808f..135a44b 100644 --- a/Src/main.c +++ b/Src/main.c @@ -27,6 +27,9 @@ #include "stm32g0xx_hal_cortex.h" #include #include + +#include "uart_dmx.h" +#include "stepper.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -59,151 +62,7 @@ static void MX_GPIO_Init(void); /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ -#define BUFFER_SIZE 515 -uint8_t rxBuffer[BUFFER_SIZE]; -uint16_t rxBufferPos = 0; - -void init_UART1_it(){ - RCC->APBENR2 |= RCC_APBENR2_USART1EN; - RCC->IOPENR |= RCC_IOPENR_GPIOCEN; - - GPIOC->MODER &= ~GPIO_MODER_MODE5; // Alternate function mode on RX pin - GPIOC->MODER |= GPIO_MODER_MODE5_1; - GPIOC->AFR[0] &= GPIO_AFRL_AFSEL5; - GPIOC->AFR[0] |= 1 << GPIO_AFRL_AFSEL5_Pos; // AF1 -> USART1 RX - - USART1->BRR = 128; // 32000000÷250000 - USART1->CR1 = USART_CR1_RE; - - USART1->CR3 |= USART_CR3_EIE; // Interrupt on BREAK (and other errors) - USART1->CR1 |= USART_CR1_RXNEIE_RXFNEIE; // RX Interrupt - - USART1->CR1 |= USART_CR1_UE; - - HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(USART1_IRQn); -} - -void init_UART1_dma(){ - RCC->IOPENR |= RCC_IOPENR_GPIOCEN; - RCC->APBENR2 |= RCC_APBENR2_USART1EN; - RCC->AHBENR |= RCC_AHBENR_DMA1EN; - - GPIOC->MODER &= ~GPIO_MODER_MODE5; // Alternate function mode on RX pin - GPIOC->MODER |= GPIO_MODER_MODE5_1; - GPIOC->AFR[0] &= GPIO_AFRL_AFSEL5; - GPIOC->AFR[0] |= 1 << GPIO_AFRL_AFSEL5_Pos; // AF1 -> USART1 RX - - USART1->BRR = 256; // 64000000÷250000 - USART1->CR1 = USART_CR1_RE; - - USART1->CR3 |= USART_CR3_EIE; // Interrupt on BREAK (and other errors) - USART1->CR3 |= USART_CR3_DMAR; // DMA Receiver mode - - DMA1_Channel1->CCR = (0x02 << DMA_CCR_PL_Pos) | DMA_CCR_MINC | DMA_CCR_TCIE; - - DMA1_Channel1->CMAR = ( uint32_t )&rxBuffer[0]; - DMA1_Channel1->CPAR = ( uint32_t )&(USART1->RDR); - DMA1_Channel1->CNDTR = 5; - - DMAMUX1_Channel0->CCR &= ~( DMAMUX_CxCR_DMAREQ_ID ); - DMAMUX1_Channel0->CCR |= ( 50 << DMAMUX_CxCR_DMAREQ_ID_Pos ); // 50 -> USART1 RX - - USART1->CR1 |= USART_CR1_UE; - - HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(USART1_IRQn); - HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn); -} - -void Reset_DMA(void) { - // Disable the DMA channel - DMA1_Channel1->CCR &= ~DMA_CCR_EN; // Disable DMA Channel 1 - - // Clear the transfer complete flag - DMA1->IFCR |= DMA_IFCR_CTCIF1; // Clear transfer complete flag for Channel 1 - - // Reconfigure the DMA - DMA1_Channel1->CMAR = (uint32_t)rxBuffer; // Set memory address to the start of the buffer - DMA1_Channel1->CNDTR = BUFFER_SIZE; // Set number of data items to transfer - - // Enable the DMA channel again - DMA1_Channel1->CCR |= DMA_CCR_EN; // Enable DMA Channel 1 -} - -void USART1_IRQHandler(){ - SEGGER_SYSVIEW_RecordEnterISR(); - if(USART1->ISR & USART_ISR_RXNE_RXFNE){ - //SEGGER_SYSVIEW_PrintfHost("RXNE"); - //printf("%x ", USART1->RDR); - rxBuffer[rxBufferPos++] = USART1->RDR; - if(rxBufferPos >= BUFFER_SIZE){ - rxBufferPos = 0; - } - } - - if(USART1->ISR & USART_ISR_FE){ - //TODO read rx==0 - USART1->ICR = USART_ICR_FECF; - //if(rxBufferPos != 514) - // printf("FE after %d\n",rxBufferPos); - //rxBufferPos = 0; - //DMA1_Channel1->CNDTR = 1; - SEGGER_SYSVIEW_PrintfHost("FE"); - Reset_DMA(); - //DMA1_Channel1->CCR &= ~( DMA_CCR_EN ); - //DMA1_Channel1->CNDTR = 512; - //DMA1_Channel1->CMAR = ( uint32_t )&rxBuffer[0]; - //DMA1_Channel1->CCR |= ( DMA_CCR_EN ); - ////DMA1_Channel1->CCR |= ( DMA_CCR_EN ); - } - if(USART1->ISR & USART_ISR_ORE){ - USART1->ICR = USART_ICR_ORECF; - //printf("ORE\n"); - //SEGGER_SYSVIEW_PrintfHost("ORE"); - } - if(USART1->ISR & USART_ISR_NE){ - USART1->ICR = USART_ICR_NECF; - printf("NE\n"); - } - if(USART1->ISR & USART_ISR_UDR){ - USART1->ICR = USART_ICR_UDRCF; - printf("UDR\n"); - } - SEGGER_SYSVIEW_RecordExitISR(); -} - -void DMA1_Channel1_IRQHandler(){ - SEGGER_SYSVIEW_RecordEnterISR(); - if(DMA1->ISR & DMA_ISR_TCIF1){ - DMA1->IFCR = DMA_IFCR_CTCIF1; - } - SEGGER_SYSVIEW_PrintfHost("DMA"); - SEGGER_SYSVIEW_RecordExitISR(); -} - -void init_stepper(){ - RCC->IOPENR |= RCC_IOPENR_GPIOBEN; - RCC->IOPENR |= RCC_IOPENR_GPIOCEN; - RCC->IOPENR |= RCC_IOPENR_GPIOEEN; - - // Set to output (00: Input, 01: Output, 10: Alternate function, 11: Analog) - // PB4 Direction - GPIOB->MODER &= ~(0x3 << (4 * 2)); // Clear mode bits for PB4 - GPIOB->MODER |= (0x1 << (4 * 2)); // Set mode to output for PB4 - - // PC11 Enable - GPIOC->MODER &= ~(0x3 << (11 * 2)); // Clear mode bits for PC11 - GPIOC->MODER |= (0x1 << (11 * 2)); // Set mode to output for PC11 - - // PE2 Step - GPIOE->MODER &= ~(0x3 << (2 * 2)); // Clear mode bits for PE2 - GPIOE->MODER |= (0x1 << (2 * 2)); // Set mode to output for PE2 - - GPIOC->BSRR |= GPIO_BSRR_BS11; -} /* USER CODE END 0 */ /** @@ -239,24 +98,24 @@ int main(void) MX_GPIO_Init(); /* USER CODE BEGIN 2 */ init_UART1_dma(); - init_stepper(); + stepper_gpio_init(); + Timer1_Init(); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ - //HAL_UART_Receive_DMA(&huart1, rxBuffer, BUFFER_SIZE); - uint16_t cnt = 0; + //uint16_t cnt = 0; while (1) { - printf("buf: "); - for(uint16_t i=0; i<10; i++) - printf("0x%02X ", rxBuffer[i]); - printf("\n"); + //printf("buf: "); + //for(uint16_t i=0; i<10; i++) + // printf("0x%02X ", rxBuffer[i]); + //printf("\n"); SEGGER_SYSVIEW_OnIdle(); - if(cnt++ >= 260-rxBuffer[1]){ - cnt = 0; - GPIOE->ODR ^= GPIO_ODR_OD2; - } + //if(cnt++ >= 256-rxBuffer[1]){ + // cnt = 0; + // GPIOE->ODR ^= GPIO_ODR_OD2; + //} /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ diff --git a/Src/stepper.c b/Src/stepper.c new file mode 100644 index 0000000..9c6232f --- /dev/null +++ b/Src/stepper.c @@ -0,0 +1,136 @@ +#include "stm32g0b1xx.h" +#include "stepper.h" +#include +#include +#include + +#include "SEGGER_SYSVIEW.h" +#include "uart_dmx.h" + +stepper_T steppers[] = { + {.en_port=GPIOC, .en_pin=11, .dir_port=GPIOB, .dir_pin=4, .step_port=GPIOE, .step_pin=2, .home_port=GPIOF, .home_pin=3} +}; + +void set_pins(stepper_T* stp){ + // Set direction (00: Input, 01: Output, 10: Alternate function, 11: Analog) + + // enable + stp->en_port->MODER &= ~(0x3 << (stp->en_pin * 2)); + stp->en_port->MODER |= (0x1 << (stp->en_pin * 2)); + + // direction + stp->dir_port->MODER &= ~(0x3 << (stp->dir_pin * 2)); + stp->dir_port->MODER |= (0x1 << (stp->dir_pin * 2)); + + // step + stp->step_port->MODER &= ~(0x3 << (stp->step_pin * 2)); + stp->step_port->MODER |= (0x1 << (stp->step_pin * 2)); + + // home switch + stp->home_port->MODER &= ~(0x3 << (stp->home_pin * 2)); + + // make shure stepper is enabled (active low) + stp->en_port->BSRR |= (0x1 << (stp->en_pin + 16)); +} + +void stepper_gpio_init(){ + RCC->IOPENR |= RCC_IOPENR_GPIOBEN; + RCC->IOPENR |= RCC_IOPENR_GPIOCEN; + RCC->IOPENR |= RCC_IOPENR_GPIOEEN; + RCC->IOPENR |= RCC_IOPENR_GPIOFEN; + + for(uint8_t i=0; i<(sizeof(steppers)/sizeof(stepper_T)); i++){ + set_pins(&steppers[i]); + } +} + +void Timer1_Init(void) { + // Step 1: Enable the clock for Timer 1 + RCC->APBENR2 |= RCC_APBENR2_TIM1EN; // Enable TIM1 clock + + // Step 2: Configure Timer 1 + TIM1->PSC = 64; + TIM1->ARR = 100; + TIM1->DIER |= TIM_DIER_UIE; // Enable update interrupt + + // Step 3: Enable Timer 1 + TIM1->CR1 |= TIM_CR1_CEN; // Enable the timer + + // Step 4: Enable the interrupt in NVIC + NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn); // Enable Timer 1 interrupt in NVIC +} + +// Timer 1 Update Interrupt Handler +void TIM1_BRK_UP_TRG_COM_IRQHandler(void) { + SEGGER_SYSVIEW_RecordEnterISR(); + if (TIM1->SR & TIM_SR_UIF) { // Check if the update interrupt flag is set + TIM1->SR &= ~TIM_SR_UIF; // Clear the update interrupt flag + + //SEGGER_SYSVIEW_PrintfHost("do step"); + do_steps(); + } + SEGGER_SYSVIEW_RecordExitISR(); +} + +void do_steps(){ + static uint32_t timer = 0; + timer++; + + for(uint8_t i=0; i<(sizeof(steppers)/sizeof(stepper_T)); i++){ + if(steppers[i].ramp_to_speed != 0 && steppers[i].next_step == timer){ + /* ramp speed */ + if(steppers[i].speed < steppers[i].ramp_to_speed) + steppers[i].speed++; + if(steppers[i].speed > steppers[i].ramp_to_speed) + steppers[i].speed--; + + /* limit max speed */ + if(steppers[i].speed >= 100) + steppers[i].speed=100; + if(steppers[i].speed <= -100) + steppers[i].speed=-100; + + /* get direction from sign */ + if(steppers[i].speed>0) + steppers[i].dir_port->BSRR |= 1 << steppers[i].dir_pin; + if(steppers[i].speed<0) + steppers[i].dir_port->BSRR |= 1 << (steppers[i].dir_pin + 16); + + /* calculate next step time */ + steppers[i].next_step = timer + (1000/abs(steppers[i].speed)); // should be safe for 1 overflow + + /* step and count position */ + steppers[i].step_port->ODR ^= 1 << steppers[i].step_pin; + if(steppers[i].speed>0) + steppers[i].pos++; + if(steppers[i].speed<0) + steppers[i].pos--; + + printf("pos %d\tspeed %d\n", steppers[i].pos, steppers[i].speed); + } + + if(steppers[i].homed){ + int16_t old_ramp_to_speed = steppers[i].ramp_to_speed; + + steppers[i].ramp_to_speed = rxBuffer[1] - steppers[i].pos; + + if(steppers[i].ramp_to_speed != 0 && old_ramp_to_speed == 0) + steppers[i].next_step = timer+1; + } + else{ + if(~(steppers[i].home_port->IDR) & (1 << steppers[i].home_pin)){ + steppers[i].pos = 0; + steppers[i].homed = 1; + steppers[i].speed = 0; + steppers[i].ramp_to_speed = 0; + printf("homed %d\n", i); + } + else{ + if(steppers[i].ramp_to_speed == 0){ + steppers[i].ramp_to_speed=10; + steppers[i].next_step = timer+1; + } + } + } + } +} diff --git a/Src/uart_dmx.c b/Src/uart_dmx.c new file mode 100644 index 0000000..6ece8d7 --- /dev/null +++ b/Src/uart_dmx.c @@ -0,0 +1,129 @@ +#include "uart_dmx.h" +#include "SEGGER_SYSVIEW.h" +#include "stdio.h" +#include "stm32g0xx_hal.h" +#include "system_stm32g0xx.h" + +uint8_t rxBuffer[BUFFER_SIZE]; +uint16_t rxBufferPos = 0; + +void init_UART1_it(){ + RCC->APBENR2 |= RCC_APBENR2_USART1EN; + RCC->IOPENR |= RCC_IOPENR_GPIOCEN; + + GPIOC->MODER &= ~GPIO_MODER_MODE5; // Alternate function mode on RX pin + GPIOC->MODER |= GPIO_MODER_MODE5_1; + GPIOC->AFR[0] &= GPIO_AFRL_AFSEL5; + GPIOC->AFR[0] |= 1 << GPIO_AFRL_AFSEL5_Pos; // AF1 -> USART1 RX + + USART1->BRR = 128; // 32000000÷250000 + USART1->CR1 = USART_CR1_RE; + + USART1->CR3 |= USART_CR3_EIE; // Interrupt on BREAK (and other errors) + USART1->CR1 |= USART_CR1_RXNEIE_RXFNEIE; // RX Interrupt + + USART1->CR1 |= USART_CR1_UE; + + HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(USART1_IRQn); +} + +void init_UART1_dma(){ + RCC->IOPENR |= RCC_IOPENR_GPIOCEN; + RCC->APBENR2 |= RCC_APBENR2_USART1EN; + RCC->AHBENR |= RCC_AHBENR_DMA1EN; + + GPIOC->MODER &= ~GPIO_MODER_MODE5; // Alternate function mode on RX pin + GPIOC->MODER |= GPIO_MODER_MODE5_1; + GPIOC->AFR[0] &= GPIO_AFRL_AFSEL5; + GPIOC->AFR[0] |= 1 << GPIO_AFRL_AFSEL5_Pos; // AF1 -> USART1 RX + + USART1->BRR = SystemCoreClock / 250000; // 64000000÷250000 + USART1->CR1 = USART_CR1_RE; + + USART1->CR3 |= USART_CR3_EIE; // Interrupt on BREAK (and other errors) + USART1->CR3 |= USART_CR3_DMAR; // DMA Receiver mode + + DMA1_Channel1->CCR = (0x02 << DMA_CCR_PL_Pos) | DMA_CCR_MINC | DMA_CCR_TCIE; + + DMA1_Channel1->CMAR = ( uint32_t )&rxBuffer[0]; + DMA1_Channel1->CPAR = ( uint32_t )&(USART1->RDR); + DMA1_Channel1->CNDTR = 5; + + DMAMUX1_Channel0->CCR &= ~( DMAMUX_CxCR_DMAREQ_ID ); + DMAMUX1_Channel0->CCR |= ( 50 << DMAMUX_CxCR_DMAREQ_ID_Pos ); // 50 -> USART1 RX + + USART1->CR1 |= USART_CR1_UE; + + HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(USART1_IRQn); + + HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn); +} + +void Reset_DMA(void) { + // Disable the DMA channel + DMA1_Channel1->CCR &= ~DMA_CCR_EN; // Disable DMA Channel 1 + + // Clear the transfer complete flag + DMA1->IFCR |= DMA_IFCR_CTCIF1; // Clear transfer complete flag for Channel 1 + + // Reconfigure the DMA + DMA1_Channel1->CMAR = (uint32_t)rxBuffer; // Set memory address to the start of the buffer + DMA1_Channel1->CNDTR = BUFFER_SIZE; // Set number of data items to transfer + + // Enable the DMA channel again + DMA1_Channel1->CCR |= DMA_CCR_EN; // Enable DMA Channel 1 +} + +void USART1_IRQHandler(){ + SEGGER_SYSVIEW_RecordEnterISR(); + if(USART1->ISR & USART_ISR_RXNE_RXFNE){ + //SEGGER_SYSVIEW_PrintfHost("RXNE"); + //printf("%x ", USART1->RDR); + rxBuffer[rxBufferPos++] = USART1->RDR; + if(rxBufferPos >= BUFFER_SIZE){ + rxBufferPos = 0; + } + } + + if(USART1->ISR & USART_ISR_FE){ + //TODO read rx==0 + USART1->ICR = USART_ICR_FECF; + //if(rxBufferPos != 514) + // printf("FE after %d\n",rxBufferPos); + //rxBufferPos = 0; + //DMA1_Channel1->CNDTR = 1; + SEGGER_SYSVIEW_PrintfHost("FE"); + Reset_DMA(); + //DMA1_Channel1->CCR &= ~( DMA_CCR_EN ); + //DMA1_Channel1->CNDTR = 512; + //DMA1_Channel1->CMAR = ( uint32_t )&rxBuffer[0]; + //DMA1_Channel1->CCR |= ( DMA_CCR_EN ); + ////DMA1_Channel1->CCR |= ( DMA_CCR_EN ); + } + if(USART1->ISR & USART_ISR_ORE){ + USART1->ICR = USART_ICR_ORECF; + //printf("ORE\n"); + //SEGGER_SYSVIEW_PrintfHost("ORE"); + } + if(USART1->ISR & USART_ISR_NE){ + USART1->ICR = USART_ICR_NECF; + printf("NE\n"); + } + if(USART1->ISR & USART_ISR_UDR){ + USART1->ICR = USART_ICR_UDRCF; + printf("UDR\n"); + } + SEGGER_SYSVIEW_RecordExitISR(); +} + +void DMA1_Channel1_IRQHandler(){ + SEGGER_SYSVIEW_RecordEnterISR(); + if(DMA1->ISR & DMA_ISR_TCIF1){ + DMA1->IFCR = DMA_IFCR_CTCIF1; + } + SEGGER_SYSVIEW_PrintfHost("DMA"); + SEGGER_SYSVIEW_RecordExitISR(); +}