diff --git a/IOSTM.cpp b/IOSTM.cpp index 12265ad..bb27e20 100644 --- a/IOSTM.cpp +++ b/IOSTM.cpp @@ -40,6 +40,8 @@ P25 PD11 output RX PA0 analog input RSSI PA1 analog input TX PA4 analog output + +EXT_CLK PA15 input */ #define PIN_COS GPIO_Pin_5 @@ -97,6 +99,8 @@ P25 PC9 output RX PA0 analog input RSSI PA7 analog input TX PA4 analog output + +EXT_CLK PA15 input */ #define PIN_COS GPIO_Pin_0 @@ -137,13 +141,74 @@ TX PA4 analog output #define PIN_RSSI GPIO_Pin_7 #define PIN_RSSI_CH ADC_Channel_7 +#elif defined(STM32F4_NUCLEO) +/* +Pin definitions for STM32F4 Nucleo boards: + +PTT PB13 output +COSLED PB14 output +LED PA5 output +COS PB15 input + +DSTAR PB10 output +DMR PB4 output +YSF PB5 output +P25 PB3 output + +RX PA0 analog input +RSSI PA1 analog input +TX PA4 analog output + +EXT_CLK PA15 input +*/ + +#define PIN_COS GPIO_Pin_15 +#define PORT_COS GPIOB +#define RCC_Per_COS RCC_AHB1Periph_GPIOB + +#define PIN_PTT GPIO_Pin_13 +#define PORT_PTT GPIOB +#define RCC_Per_PTT RCC_AHB1Periph_GPIOB + +#define PIN_COSLED GPIO_Pin_14 +#define PORT_COSLED GPIOB +#define RCC_Per_COSLED RCC_AHB1Periph_GPIOB + +#define PIN_LED GPIO_Pin_5 +#define PORT_LED GPIOA +#define RCC_Per_LED RCC_AHB1Periph_GPIOA + +#define PIN_P25 GPIO_Pin_3 +#define PORT_P25 GPIOB +#define RCC_Per_P25 RCC_AHB1Periph_GPIOB + +#define PIN_DSTAR GPIO_Pin_10 +#define PORT_DSTAR GPIOB +#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOB + +#define PIN_DMR GPIO_Pin_4 +#define PORT_DMR GPIOB +#define RCC_Per_DMR RCC_AHB1Periph_GPIOB + +#define PIN_YSF GPIO_Pin_5 +#define PORT_YSF GPIOB +#define RCC_Per_YSF RCC_AHB1Periph_GPIOB + +#define PIN_RX GPIO_Pin_0 +#define PIN_RX_CH ADC_Channel_0 + +#define PIN_RSSI GPIO_Pin_1 +#define PIN_RSSI_CH ADC_Channel_1 + #else -#error "Either STM32F4_DISCOVERY or STM32F4_PI need to be defined" +#error "Either STM32F4_DISCOVERY, STM32F4_PI or STM32F4_NUCLEO need to be defined" #endif - const uint16_t DC_OFFSET = 2048U; +// Sampling frequency +#define SAMP_FREQ 24000 + extern "C" { void TIM2_IRQHandler() { if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { @@ -307,19 +372,42 @@ void CIO::startInt() // Init the timer RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); - + +#if defined(EXTERNAL_OSC) + // Configure GPIO PA15 as external TIM2 clock source + GPIO_PinAFConfig(GPIOA, GPIO_PinSource15, GPIO_AF_TIM2); + GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; + GPIO_Init(GPIOA, &GPIO_InitStruct); +#endif + TIM_TimeBaseInitTypeDef timerInitStructure; TIM_TimeBaseStructInit (&timerInitStructure); - // TIM2 at 24 kHz - timerInitStructure.TIM_Prescaler = (uint16_t) ((SystemCoreClock/(4*24000)) - 1); + // TIM2 output frequency +#if defined(EXTERNAL_OSC) + timerInitStructure.TIM_Prescaler = (uint16_t) ((EXTERNAL_OSC/(2*SAMP_FREQ)) - 1); +#else + timerInitStructure.TIM_Prescaler = (uint16_t) ((SystemCoreClock/(4*SAMP_FREQ)) - 1); +#endif timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up; timerInitStructure.TIM_Period = 1; timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; timerInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM2, &timerInitStructure); + +#if defined(EXTERNAL_OSC) + // Enable external clock (PA15) + TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x00); +#else + // Enable internal clock + TIM_InternalClockConfig(TIM2); +#endif + + // Enable TIM2 TIM_Cmd(TIM2, ENABLE); + // Enable TIM2 interrupt TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); NVIC_InitTypeDef nvicStructure; diff --git a/Makefile b/Makefile index d23d1e8..a97316d 100644 --- a/Makefile +++ b/Makefile @@ -87,7 +87,10 @@ MCFLAGS=-mcpu=cortex-m4 -mthumb -mlittle-endian \ # STM32F4 Discovery board: DEFS_DIS=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F40_41xxx -DSTM32F4_DISCOVERY -DHSE_VALUE=$(OSC) # Pi board: -DEFS_PI=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_PI -DHSE_VALUE=$(OSC) +DEFS_PI=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_PI -DARDUINO_MODE_PINS -DSEND_RSSI_DATA -DSERIAL_REPEATER -DHSE_VALUE=$(OSC) +# STM32F4 Nucleo 446 board: +DEFS_NUCLEO=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_NUCLEO -DHSE_VALUE=$(OSC) + CFLAGS=-c $(MCFLAGS) $(INCLUDES) CXXFLAGS=-c $(MCFLAGS) $(INCLUDES) @@ -96,7 +99,7 @@ LDSCRIPT=stm32f4xx_link.ld LDFLAGS =-T $(LDSCRIPT) $(MCFLAGS) --specs=nosys.specs $(INCLUDES_LIBS) $(LINK_LIBS) # Build Rules -.PHONY: all release dis pi debug clean +.PHONY: all release dis pi nucleo debug clean # Default target: STM32F4 Discovery board all: dis @@ -106,6 +109,11 @@ pi: CXXFLAGS+=$(DEFS_PI) -Os -fno-exceptions -ffunction-sections -fdata-sections pi: LDFLAGS+=-Os --specs=nano.specs pi: release +nucleo: CFLAGS+=$(DEFS_NUCLEO) -Os -ffunction-sections -fdata-sections -fno-builtin -Wno-implicit -DCUSTOM_NEW -DNO_EXCEPTIONS +nucleo: CXXFLAGS+=$(DEFS_NUCLEO) -Os -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin -fno-rtti -DCUSTOM_NEW -DNO_EXCEPTIONS +nucleo: LDFLAGS+=-Os --specs=nano.specs +nucleo: release + dis: CFLAGS+=$(DEFS_DIS) -Os -ffunction-sections -fdata-sections -fno-builtin -Wno-implicit -DCUSTOM_NEW -DNO_EXCEPTIONS dis: CXXFLAGS+=$(DEFS_DIS) -Os -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin -fno-rtti -DCUSTOM_NEW -DNO_EXCEPTIONS dis: LDFLAGS+=-Os --specs=nano.specs diff --git a/SerialSTM.cpp b/SerialSTM.cpp index 2955508..904ec10 100644 --- a/SerialSTM.cpp +++ b/SerialSTM.cpp @@ -22,35 +22,39 @@ #include "SerialPort.h" -#if defined(STM32F4XX) || defined(STM32F4) +/* +Pin definitions: -volatile uint32_t intcount1, intcount3, intcount5; +- Host communication: +USART1 - TXD PA9 - RXD PA10 (Pi board) +USART2 - TXD PA2 - RXD PA3 (Nucleo board) +USART3 - TXD PC10 - RXD PC11 (Discovery board) + +- Serial repeater: +UART5 - TXD PC12 - RXD PD2 + +*/ + +#if defined(STM32F4XX) || defined(STM32F4) #define TX_SERIAL_FIFO_SIZE 256U #define RX_SERIAL_FIFO_SIZE 256U -volatile uint8_t TXSerialfifo1[TX_SERIAL_FIFO_SIZE]; -volatile uint8_t RXSerialfifo1[RX_SERIAL_FIFO_SIZE]; -volatile uint16_t TXSerialfifohead1, TXSerialfifotail1; -volatile uint16_t RXSerialfifohead1, RXSerialfifotail1; - -volatile uint8_t TXSerialfifo3[TX_SERIAL_FIFO_SIZE]; -volatile uint8_t RXSerialfifo3[RX_SERIAL_FIFO_SIZE]; -volatile uint16_t TXSerialfifohead3, TXSerialfifotail3; -volatile uint16_t RXSerialfifohead3, RXSerialfifotail3; - -volatile uint8_t TXSerialfifo5[TX_SERIAL_FIFO_SIZE]; -volatile uint8_t RXSerialfifo5[RX_SERIAL_FIFO_SIZE]; -volatile uint16_t TXSerialfifohead5, TXSerialfifotail5; -volatile uint16_t RXSerialfifohead5, RXSerialfifotail5; - extern "C" { void USART1_IRQHandler(); + void USART2_IRQHandler(); void USART3_IRQHandler(); void UART5_IRQHandler(); } /* ************* USART1 ***************** */ +#if defined(STM32F4_PI) + +volatile uint32_t intcount1; +volatile uint8_t TXSerialfifo1[TX_SERIAL_FIFO_SIZE]; +volatile uint8_t RXSerialfifo1[RX_SERIAL_FIFO_SIZE]; +volatile uint16_t TXSerialfifohead1, TXSerialfifotail1; +volatile uint16_t RXSerialfifohead1, RXSerialfifotail1; // Init queues void TXSerialfifoinit1() @@ -229,7 +233,204 @@ void WriteUSART1(const uint8_t* data, uint16_t length) USART_ITConfig(USART1, USART_IT_TXE, ENABLE); } +#endif + +/* ************* USART2 ***************** */ +#if defined(STM32F4_NUCLEO) + +volatile uint32_t intcount2; +volatile uint8_t TXSerialfifo2[TX_SERIAL_FIFO_SIZE]; +volatile uint8_t RXSerialfifo2[RX_SERIAL_FIFO_SIZE]; +volatile uint16_t TXSerialfifohead2, TXSerialfifotail2; +volatile uint16_t RXSerialfifohead2, RXSerialfifotail2; + +// Init queues +void TXSerialfifoinit2() +{ + TXSerialfifohead2 = 0U; + TXSerialfifotail2 = 0U; +} + +void RXSerialfifoinit2() +{ + RXSerialfifohead2 = 0U; + RXSerialfifotail2 = 0U; +} + +// How full is queue +// TODO decide if how full or how empty is preferred info to return +uint16_t TXSerialfifolevel2() +{ + uint32_t tail = TXSerialfifotail2; + uint32_t head = TXSerialfifohead2; + + if (tail > head) + return TX_SERIAL_FIFO_SIZE + head - tail; + else + return head - tail; +} + +uint16_t RXSerialfifolevel2() +{ + uint32_t tail = RXSerialfifotail2; + uint32_t head = RXSerialfifohead2; + + if (tail > head) + return RX_SERIAL_FIFO_SIZE + head - tail; + else + return head - tail; +} + +// Flushes the transmit shift register +// warning: this call is blocking +void TXSerialFlush2() +{ + // wait until the TXE shows the shift register is empty + while (USART_GetITStatus(USART2, USART_FLAG_TXE)) + ; +} + +uint8_t TXSerialfifoput2(uint8_t next) +{ + if (TXSerialfifolevel2() < TX_SERIAL_FIFO_SIZE) { + TXSerialfifo2[TXSerialfifohead2] = next; + + TXSerialfifohead2++; + if (TXSerialfifohead2 >= TX_SERIAL_FIFO_SIZE) + TXSerialfifohead2 = 0U; + + // make sure transmit interrupts are enabled as long as there is data to send + USART_ITConfig(USART2, USART_IT_TXE, ENABLE); + return 1U; + } else { + return 0U; // signal an overflow occurred by returning a zero count + } +} + +void USART2_IRQHandler() +{ + uint8_t c; + + if (USART_GetITStatus(USART2, USART_IT_RXNE)) { + c = (uint8_t) USART_ReceiveData(USART2); + + if (RXSerialfifolevel2() < RX_SERIAL_FIFO_SIZE) { + RXSerialfifo2[RXSerialfifohead2] = c; + + RXSerialfifohead2++; + if (RXSerialfifohead2 >= RX_SERIAL_FIFO_SIZE) + RXSerialfifohead2 = 0U; + } else { + // TODO - do something if rx fifo is full? + } + + USART_ClearITPendingBit(USART2, USART_IT_RXNE); + intcount2++; + } + + if (USART_GetITStatus(USART2, USART_IT_TXE)) { + c = 0U; + + if (TXSerialfifohead2 != TXSerialfifotail2) { // if the fifo is not empty + c = TXSerialfifo2[TXSerialfifotail2]; + + TXSerialfifotail2++; + if (TXSerialfifotail2 >= TX_SERIAL_FIFO_SIZE) + TXSerialfifotail2 = 0U; + + USART_SendData(USART2, c); + } else { // if there's no more data to transmit then turn off TX interrupts + USART_ITConfig(USART2, USART_IT_TXE, DISABLE); + } + + USART_ClearITPendingBit(USART2, USART_IT_TXE); + } +} + +void InitUSART2(int speed) +{ + // USART2 - TXD PA2 - RXD PA3 + GPIO_InitTypeDef GPIO_InitStructure; + USART_InitTypeDef USART_InitStructure; + NVIC_InitTypeDef NVIC_InitStructure; + + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); + RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); + GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2); + GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2); + + // USART IRQ init + NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; + NVIC_Init(&NVIC_InitStructure); + + // Configure USART as alternate function + GPIO_StructInit(&GPIO_InitStructure); + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; // Tx | Rx + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + // Configure USART baud rate + USART_StructInit(&USART_InitStructure); + USART_InitStructure.USART_BaudRate = speed; + USART_InitStructure.USART_WordLength = USART_WordLength_8b; + USART_InitStructure.USART_StopBits = USART_StopBits_1; + USART_InitStructure.USART_Parity = USART_Parity_No; + USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; + USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; + USART_Init(USART2, &USART_InitStructure); + + USART_Cmd(USART2, ENABLE); + + USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); + + // initialize the fifos + TXSerialfifoinit2(); + RXSerialfifoinit2(); +} + +uint8_t AvailUSART2(void) +{ + if (RXSerialfifolevel2() > 0U) + return 1U; + else + return 0U; +} + +uint8_t ReadUSART2(void) +{ + uint8_t data_c = RXSerialfifo2[RXSerialfifotail2]; + + RXSerialfifotail2++; + if (RXSerialfifotail2 >= RX_SERIAL_FIFO_SIZE) + RXSerialfifotail2 = 0U; + + return data_c; +} + +void WriteUSART2(const uint8_t* data, uint16_t length) +{ + for (uint16_t i = 0U; i < length; i++) + TXSerialfifoput2(data[i]); + + USART_ITConfig(USART2, USART_IT_TXE, ENABLE); +} + +#endif + /* ************* USART3 ***************** */ +#if defined(STM32F4_DISCOVERY) || defined(STM32F4_PI) + +volatile uint32_t intcount3; +volatile uint8_t TXSerialfifo3[TX_SERIAL_FIFO_SIZE]; +volatile uint8_t RXSerialfifo3[RX_SERIAL_FIFO_SIZE]; +volatile uint16_t TXSerialfifohead3, TXSerialfifotail3; +volatile uint16_t RXSerialfifohead3, RXSerialfifotail3; // Init queues void TXSerialfifoinit3() @@ -408,8 +609,16 @@ void WriteUSART3(const uint8_t* data, uint16_t length) USART_ITConfig(USART3, USART_IT_TXE, ENABLE); } +#endif + /* ************* UART5 ***************** */ +volatile uint32_t intcount5; +volatile uint8_t TXSerialfifo5[TX_SERIAL_FIFO_SIZE]; +volatile uint8_t RXSerialfifo5[RX_SERIAL_FIFO_SIZE]; +volatile uint16_t TXSerialfifohead5, TXSerialfifotail5; +volatile uint16_t RXSerialfifohead5, RXSerialfifotail5; + // Init queues void TXSerialfifoinit5() { @@ -515,7 +724,7 @@ void UART5_IRQHandler() void InitUART5(int speed) { - // USART5 - TXD PC12 - RXD PD2 + // UART5 - TXD PC12 - RXD PD2 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; @@ -601,6 +810,8 @@ void CSerialPort::beginInt(uint8_t n, int speed) InitUSART3(speed); #elif defined(STM32F4_PI) InitUSART1(speed); + #elif defined(STM32F4_NUCLEO) + InitUSART2(speed); #endif break; case 3U: @@ -619,6 +830,8 @@ int CSerialPort::availableInt(uint8_t n) return AvailUSART3(); #elif defined(STM32F4_PI) return AvailUSART1(); + #elif defined(STM32F4_NUCLEO) + return AvailUSART2(); #endif case 3U: return AvailUART5(); @@ -635,6 +848,8 @@ uint8_t CSerialPort::readInt(uint8_t n) return ReadUSART3(); #elif defined(STM32F4_PI) return ReadUSART1(); + #elif defined(STM32F4_NUCLEO) + return ReadUSART2(); #endif case 3U: return ReadUART5(); @@ -655,6 +870,10 @@ void CSerialPort::writeInt(uint8_t n, const uint8_t* data, uint16_t length, bool WriteUSART1(data, length); if (flush) TXSerialFlush1(); + #elif defined(STM32F4_NUCLEO) + WriteUSART2(data, length); + if (flush) + TXSerialFlush2(); #endif break; case 3U: