add firmware

This commit is contained in:
Dana Markova
2025-07-28 12:43:33 +03:00
parent 6cf2747ec9
commit 748830dfb7
84 changed files with 40709 additions and 0 deletions

37
drv/gpio.cpp Normal file
View File

@ -0,0 +1,37 @@
#include "stm32g4xx.h"
#include "gpio.h"
void GPIO_InitPin(unsigned long I_Pin)
{
unsigned long port = (I_Pin & 0x000000F0UL) >> 4;
GPIO_TypeDef* gpio = (GPIO_TypeDef*)(((unsigned char*)GPIOA) + (port * 0x0400));
unsigned long rcc = 1UL << port;
unsigned long pin = I_Pin & 0x0000000FUL;
unsigned long af = (I_Pin & 0x0F000000UL) >> 24;
unsigned long pupd = (I_Pin & 0x00F00000UL) >> 20;
unsigned long ospeed = (I_Pin & 0x000F0000UL) >> 16;
unsigned long mode = (I_Pin & 0x0000F000UL) >> 12;
unsigned long otype = (I_Pin & 0x00000100UL) >> 8;
unsigned long set = (I_Pin & 0x00000200UL) >> 9;
//---
if (!(RCC->AHB2ENR & rcc)) RCC->AHB2ENR |= rcc;
//---
gpio->AFR[pin >> 3] &= ~(0x0000000FUL << ((pin & 0x07) * 4));
gpio->AFR[pin >> 3] |= af << ((pin & 0x07) * 4);
//---
gpio->OSPEEDR &= ~(0x00000003UL << (pin * 2));
gpio->OSPEEDR |= ospeed << (pin * 2);
//---
gpio->OTYPER &= ~(0x00000001UL << pin);
gpio->OTYPER |= otype << pin;
//---
gpio->PUPDR &= ~(0x00000003UL << (pin * 2));
gpio->PUPDR |= pupd << (pin * 2);
//---
gpio->BSRR = 1 << (set ? pin : pin+16);
//---
gpio->MODER &= ~(0x00000003UL << (pin * 2));
gpio->MODER |= mode << (pin * 2);
}
//------------------------------------------------------------------------------

69
drv/gpio.h Normal file
View File

@ -0,0 +1,69 @@
#pragma once
#define GPIO_PIN_0 0x00000000UL
#define GPIO_PIN_1 0x00000001UL
#define GPIO_PIN_2 0x00000002UL
#define GPIO_PIN_3 0x00000003UL
#define GPIO_PIN_4 0x00000004UL
#define GPIO_PIN_5 0x00000005UL
#define GPIO_PIN_6 0x00000006UL
#define GPIO_PIN_7 0x00000007UL
#define GPIO_PIN_8 0x00000008UL
#define GPIO_PIN_9 0x00000009UL
#define GPIO_PIN_10 0x0000000AUL
#define GPIO_PIN_11 0x0000000BUL
#define GPIO_PIN_12 0x0000000CUL
#define GPIO_PIN_13 0x0000000DUL
#define GPIO_PIN_14 0x0000000EUL
#define GPIO_PIN_15 0x0000000FUL
#define GPIO_PORT_A 0x00000000UL
#define GPIO_PORT_B 0x00000010UL
#define GPIO_PORT_C 0x00000020UL
#define GPIO_PORT_D 0x00000030UL
#define GPIO_PORT_E 0x00000040UL
#define GPIO_PORT_F 0x00000070UL
#define GPIO_PORT_G 0x00000080UL
#define GPIO_PORT_H 0x00000090UL
#define GPIO_PORT_I 0x000000A0UL
#define GPIO_PORT_J 0x000000B0UL
#define GPIO_PORT_K 0x000000C0UL
#define GPIO_PUSHPULL 0x00000000UL
#define GPIO_OPENDRAIN 0x00000100UL
#define GPIO_RESET 0x00000000UL
#define GPIO_SET 0x00000200UL
#define GPIO_INPUT 0x00000000UL
#define GPIO_OUTPUT 0x00001000UL
#define GPIO_ALTER 0x00002000UL
#define GPIO_ANALOG 0x00003000UL
#define GPIO_OSPEED_LOW 0x00000000UL
#define GPIO_OSPEED_MEDIUM 0x00010000UL
#define GPIO_OSPEED_FAST 0x00020000UL
#define GPIO_OSPEED_HIGH 0x00030000UL
#define GPIO_NOPUPD 0x00000000UL
#define GPIO_PULLUP 0x00100000UL
#define GPIO_PULLDOWN 0x00200000UL
#define GPIO_AF0 0x00000000UL
#define GPIO_AF1 0x01000000UL
#define GPIO_AF2 0x02000000UL
#define GPIO_AF3 0x03000000UL
#define GPIO_AF4 0x04000000UL
#define GPIO_AF5 0x05000000UL
#define GPIO_AF6 0x06000000UL
#define GPIO_AF7 0x07000000UL
#define GPIO_AF8 0x08000000UL
#define GPIO_AF9 0x09000000UL
#define GPIO_AF10 0x0A000000UL
#define GPIO_AF11 0x0B000000UL
#define GPIO_AF12 0x0C000000UL
#define GPIO_AF13 0x0D000000UL
#define GPIO_AF14 0x0E000000UL
#define GPIO_AF15 0x0F000000UL
void GPIO_InitPin(unsigned long I_Pin);

201
drv/i2c.cpp Normal file
View File

@ -0,0 +1,201 @@
#include "stm32g4xx.h"
#include <string.h>
#include "gpio.h"
#include "i2c.h"
static void Init(I2C_TypeDef* I2C)
{
I2C->TIMINGR = 0x00303D5BUL; // 100kHz
//I2C->TIMINGR = 0x30108DFF;
I2C->CR1 = I2C_CR1_PE;
while(I2C->ISR & I2C_ISR_BUSY) { }
}
//------------------------------------------------------------------------------
void I2C2_Init()
{
if (RCC->APB1ENR1 & RCC_APB1ENR1_I2C2EN) return;
RCC->APB1ENR1 |= RCC_APB1ENR1_I2C2EN;
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;
GPIO_InitPin(GPIO_PIN_8 | GPIO_PORT_A | GPIO_ALTER | GPIO_AF4 | GPIO_OSPEED_HIGH | GPIO_OPENDRAIN | GPIO_PULLUP);
GPIO_InitPin(GPIO_PIN_9 | GPIO_PORT_A | GPIO_ALTER | GPIO_AF4 | GPIO_OSPEED_HIGH | GPIO_OPENDRAIN | GPIO_PULLUP);
Init(I2C2);
}
//------------------------------------------------------------------------------
void I2C1_Init()
{
if (RCC->APB1ENR1 & RCC_APB1ENR1_I2C1EN) return;
RCC->APB1ENR1 |= RCC_APB1ENR1_I2C1EN;
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOBEN;
GPIO_InitPin(GPIO_PIN_8 | GPIO_PORT_B | GPIO_ALTER | GPIO_AF4 | GPIO_OSPEED_HIGH | GPIO_OPENDRAIN | GPIO_PULLUP);
GPIO_InitPin(GPIO_PIN_9 | GPIO_PORT_B | GPIO_ALTER | GPIO_AF4 | GPIO_OSPEED_HIGH | GPIO_OPENDRAIN | GPIO_PULLUP);
Init(I2C1);
}
//------------------------------------------------------------------------------
static void Stop(I2C_TypeDef* I2C)
{
I2C->CR2 |= I2C_CR2_STOP;
while (!(I2C->ISR & I2C_ISR_STOPF)) { asm volatile("NOP"); }
I2C->ICR = I2C_ICR_STOPCF;
}
//------------------------------------------------------------------------------
static void Read(I2C_TypeDef* I2C, unsigned char Address, unsigned char* Data, unsigned char Size)
{
I2C->CR2 &= ~(I2C_CR2_SADD_Msk | I2C_CR2_NBYTES_Msk);
I2C->CR2 |= (Address << (I2C_CR2_SADD_Pos + 1)) | I2C_CR2_RD_WRN | (((unsigned long)Size)<<I2C_CR2_NBYTES_Pos);
I2C->CR2 |= I2C_CR2_START;
while (Size--)
{
while (!(I2C->ISR & I2C_ISR_RXNE)) { }
*Data++ = I2C->RXDR;
}
}
//------------------------------------------------------------------------------
static void Write(I2C_TypeDef* I2C, unsigned char Address, const unsigned char* Data, unsigned char Size)
{
I2C->CR2 &= ~(I2C_CR2_SADD_Msk | I2C_CR2_RD_WRN | I2C_CR2_NBYTES_Msk);
I2C->CR2 |= (Address << (I2C_CR2_SADD_Pos + 1)) | (((unsigned long)Size)<<I2C_CR2_NBYTES_Pos);
I2C->CR2 |= I2C_CR2_START;
while(I2C->CR2 & I2C_CR2_START) { asm volatile("NOP"); }
while (Size--)
{
while (!(I2C->ISR & I2C_ISR_TXE)) { asm volatile("NOP"); }
I2C->TXDR = *Data++;
}
while(!(I2C->ISR & I2C_ISR_TC)) { asm volatile("NOP"); }//???
}
//------------------------------------------------------------------------------
static void Write2(I2C_TypeDef* I2C, unsigned char Address, const unsigned char* Data1, unsigned char Size1, const unsigned char* Data2, unsigned char Size2)
{
I2C->CR2 &= ~(I2C_CR2_SADD_Msk | I2C_CR2_RD_WRN | I2C_CR2_NBYTES_Msk);
I2C->CR2 |= (Address << (I2C_CR2_SADD_Pos + 1)) | (((unsigned long)Size1+Size2)<<I2C_CR2_NBYTES_Pos);
I2C->CR2 |= I2C_CR2_START;
while (Size1--)
{
while (!(I2C->ISR & I2C_ISR_TXE)) { asm volatile("NOP"); }
I2C->TXDR = *Data1++;
}
while (Size2--)
{
while (!(I2C->ISR & I2C_ISR_TXE)) { asm volatile("NOP"); }
I2C->TXDR = *Data2++;
}
while(!(I2C->ISR & I2C_ISR_TC)) { asm volatile("NOP"); }
}
//------------------------------------------------------------------------------
void I2C2_Write(unsigned char Address, unsigned char Data)
{
Write(I2C2, Address, &Data, 1);
}
//------------------------------------------------------------------------------
void I2C2_Write(unsigned char Address, const void* Data, unsigned char Size)
{
Write(I2C2, Address, (unsigned char*)Data, Size);
}
//------------------------------------------------------------------------------
void I2C2_Read(unsigned char Address, void* Data, unsigned char Size)
{
Read(I2C2, Address, (unsigned char*)Data, Size);
}
//------------------------------------------------------------------------------
void I2C2_Stop()
{
Stop(I2C2);
}
//------------------------------------------------------------------------------
void I2C1_Write(unsigned char Address, unsigned char Data)
{
Write(I2C1, Address, &Data, 1);
}
//------------------------------------------------------------------------------
void I2C1_Write(unsigned char Address, const void* Data, unsigned char Size)
{
Write(I2C1, Address, (unsigned char*)Data, Size);
}
//------------------------------------------------------------------------------
void I2C1_Write2(unsigned char Address, const void* Data1, unsigned char Size1, const void* Data2, unsigned char Size2)
{
Write2(I2C1, Address, (unsigned char*)Data1, Size1, (unsigned char*)Data2, Size2);
}
//------------------------------------------------------------------------------
void I2C1_Read(unsigned char Address, void* Data, unsigned char Size)
{
Read(I2C1, Address, (unsigned char*)Data, Size);
}
//------------------------------------------------------------------------------
void I2C1_Stop()
{
Stop(I2C1);
}
//------------------------------------------------------------------------------
extern "C" {
int8_t I2C1_WriteBytes(uint8_t addr, const uint8_t *data, uint8_t size)
{
Write(I2C1, addr, (unsigned char*)data, size);
return 0;
}
int8_t I2C1_ReadBytes(uint8_t addr, uint8_t *data, uint8_t size)
{
Read(I2C1, addr,(unsigned char*)data, size);
return 0;
}
} // extern "C"

27
drv/i2c.h Normal file
View File

@ -0,0 +1,27 @@
#pragma once
struct I2C_Device
{
unsigned char* Buffer;
unsigned char Size;
void (*CallbackProc)(unsigned char Address, const unsigned char* Data, unsigned char Size);
unsigned char Address;
unsigned char Write;
unsigned char Read;
I2C_Device* Next;
};
void I2C2_Init();
void I2C2_Write(unsigned char Address, unsigned char Data);
void I2C2_Write(unsigned char Address, const void* Data, unsigned char Size);
void I2C2_Read(unsigned char Address, void* Data, unsigned char Size);
void I2C2_Stop();
void I2C1_Init();
void I2C1_Write(unsigned char Address, unsigned char Data);
void I2C1_Write(unsigned char Address, const void* Data, unsigned char Size);
void I2C1_Write2(unsigned char Address, const void* Data1, unsigned char Size1, const void* Data2, unsigned char Size2);
void I2C1_Read(unsigned char Address, void* Data, unsigned char Size);
void I2C1_Stop();

18
drv/iwdg.cpp Normal file
View File

@ -0,0 +1,18 @@
#include "stm32g4xx.h"
#include "iwdg.h"
void InitIWDG(unsigned short Reload)
{
IWDG->KR=0x0000CCCC;
IWDG->KR=0x00005555;
IWDG->PR=0;
IWDG->RLR=Reload;
while(IWDG->SR) { asm volatile("NOP"); }
IWDG->KR=0x0000AAAA;
}
void PingIWDG()
{
IWDG->KR=0x0000AAAA;
}

4
drv/iwdg.h Normal file
View File

@ -0,0 +1,4 @@
#pragma once
void InitIWDG(unsigned short Reload);
void PingIWDG();

85
drv/pwm.cpp Normal file
View File

@ -0,0 +1,85 @@
#include "stm32g4xx.h"
#include "gpio.h"
#include "pwm.h"
bool PWM_Enable=false;
short PWM_work_min = 1050;//???
inline static unsigned short Mid(unsigned short Val, unsigned short Min, unsigned short Max)
{
if(Val<Min) return Min;
if(Val>Max) return Max;
return Val;
}
void PWM_Init(unsigned long Freq)
{
GPIO_InitPin(GPIO_PIN_0 | GPIO_PORT_A | GPIO_ALTER | GPIO_AF1);
GPIO_InitPin(GPIO_PIN_1 | GPIO_PORT_A | GPIO_ALTER | GPIO_AF1);
GPIO_InitPin(GPIO_PIN_2 | GPIO_PORT_A | GPIO_ALTER | GPIO_AF1);
GPIO_InitPin(GPIO_PIN_3 | GPIO_PORT_A | GPIO_ALTER | GPIO_AF1);
RCC->APB1ENR1 |= RCC_APB1ENR1_TIM2EN;
TIM2->CR2 = 0;
TIM2->ARR = 1000 - 1; //The comparison range is 100
TIM2->PSC = (16'000'000/1000/16000)-1; // The divider is set to 16000Hz
TIM2->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1PE; //PWM mode 1 for CH1
TIM2->CCMR1|= TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2PE; // PWM mode 1 for CH2
TIM2->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3PE; // PWM mode 1 for CH3
TIM2->CCMR2|= TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4PE; // PWM mode 1 for CH4
TIM2->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E |TIM_CCER_CC4E; // CH1 and CH2 outputs are active
TIM2->BDTR = TIM_BDTR_MOE; // Allow active outputs to work
TIM2->CR1 = TIM_CR1_CEN; // Timer is running
for(int a=0; a<100000; a++) { asm volatile("NOP");}
}
//------------------------------------------------------------------------------
static void Stop()
{
PWM_Enable=false;
TIM2->CCER=0;
}
//------------------------------------------------------------------------------
void PWM_SetQuad(short Pow[4], unsigned short Min, unsigned short Max)
{
if(!Pow) { Stop(); return; }
TIM2->CCR1 = Mid(Pow[0], Min, Max); //M1
TIM2->CCR2 = Mid(Pow[1], Min, Max); //M2
TIM2->CCR3 = Mid(Pow[2], Min, Max); //M3
TIM2->CCR4 = Mid(Pow[3], Min, Max); //M4
bool en=false;
for(int a=0; a<4; a++) if(Pow[a]>PWM_work_min) en=true;
PWM_Enable=en;
}
//------------------------------------------------------------------------------
void PWM_SetAll(unsigned short Pow)
{
TIM2->CCR1 = Pow;
TIM2->CCR2 = Pow;
TIM2->CCR3 = Pow;
TIM2->CCR4 = Pow;
bool en=false;
if(Pow>PWM_work_min) en=true;
PWM_Enable=en;
}
//------------------------------------------------------------------------------

7
drv/pwm.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
extern bool PWM_Enable;
void PWM_Init(unsigned long Freq);
void PWM_SetQuad(short M[4], unsigned short Min, unsigned short Max);
void PWM_SetAll(unsigned short Pow);

138
drv/spi.cpp Normal file
View File

@ -0,0 +1,138 @@
#include "stm32g4xx.h"
#include "gpio.h"
#include "spi.h"
static void Init(SPI_TypeDef* SPI)
{
SPI->CR1 = SPI_CR1_CPHA | SPI_CR1_CPOL | SPI_CR1_SSI | SPI_CR1_SSM | (SPI_CR1_BR_0 | SPI_CR1_BR_1) | SPI_CR1_MSTR;
SPI->CR2 = SPI_CR2_DS_0 | SPI_CR2_DS_1 | SPI_CR2_DS_2 | SPI_CR2_FRXTH;
SPI->CR1 |= SPI_CR1_SPE;
}
//------------------------------------------------------------------------------
void SPI1_Init()
{
if(RCC->APB2ENR & RCC_APB2ENR_SPI1EN) return;
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;
GPIO_InitPin(GPIO_PIN_5 | GPIO_PORT_A | GPIO_ALTER | GPIO_AF5 | GPIO_OSPEED_HIGH); // SCK
GPIO_InitPin(GPIO_PIN_6 | GPIO_PORT_A | GPIO_ALTER | GPIO_AF5 | GPIO_OSPEED_HIGH); // MISO
GPIO_InitPin(GPIO_PIN_7 | GPIO_PORT_A | GPIO_ALTER | GPIO_AF5 | GPIO_OSPEED_HIGH); // MOSI
GPIO_InitPin(GPIO_PIN_4 | GPIO_PORT_A | GPIO_OUTPUT | GPIO_OSPEED_HIGH | GPIO_SET); // NCS -> PMW3901
Init(SPI1);
}
//------------------------------------------------------------------------------
static void Trans(SPI_TypeDef* SPI, const void* WriteData, void* ReadData, unsigned long Size)
{
unsigned char* dr=(unsigned char*)ReadData;
unsigned char* dw=(unsigned char*)WriteData;
volatile char& DR = *((volatile char*)&(SPI->DR));
while (Size--)
{
while (!(SPI->SR & SPI_SR_TXE)) { asm volatile("NOP"); }
if (dw) DR = *(dw++);
else DR = 0x00;
while (!(SPI->SR & SPI_SR_RXNE)) { asm volatile("NOP"); }
if (dr) *(dr++) = DR;
else volatile char t = DR;
}
while (SPI->SR & SPI_SR_BSY) { asm volatile("NOP"); }
}
//------------------------------------------------------------------------------
static inline void CS_IMU(bool En)
{
if(En) GPIOB->BSRR = GPIO_BSRR_BR_12;
else GPIOB->BSRR = GPIO_BSRR_BS_12;
for (unsigned long a = 0; a < 21; a++) { asm volatile("NOP"); }
}
//------------------------------------------------------------------------------
void SPI1_TransferCons(const void* WriteData, unsigned long WriteSize, void* ReadData, unsigned long ReadSize)
{
CS_IMU(true);
Trans(SPI1, WriteData, 0, WriteSize);
Trans(SPI1, 0, ReadData, ReadSize);
CS_IMU(false);
}
//------------------------------------------------------------------------------
void SPI1_TransferParallel(const void* WriteData, void* ReadData, unsigned long Size)
{
CS_IMU(true);
Trans(SPI1, WriteData, ReadData, Size);
CS_IMU(false);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void SPI2_Init()
{
if ( RCC->APB1ENR1&RCC_APB1ENR1_SPI2EN) return;
RCC->APB1ENR1 |= RCC_APB1ENR1_SPI2EN;
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOBEN;
GPIO_InitPin(GPIO_PIN_10 | GPIO_PORT_A | GPIO_ALTER | GPIO_AF5 | GPIO_OSPEED_HIGH | GPIO_OPENDRAIN | GPIO_PULLUP); // MISO
GPIO_InitPin(GPIO_PIN_11 | GPIO_PORT_A | GPIO_ALTER | GPIO_AF5 | GPIO_OSPEED_HIGH | GPIO_OPENDRAIN | GPIO_PULLUP); // MOSI
GPIO_InitPin(GPIO_PIN_13 | GPIO_PORT_B | GPIO_ALTER | GPIO_AF5 | GPIO_OSPEED_HIGH| GPIO_OPENDRAIN | GPIO_PULLUP); // SCK
GPIO_InitPin(GPIO_PIN_12 | GPIO_PORT_B | GPIO_OUTPUT | GPIO_OSPEED_HIGH | GPIO_SET| GPIO_OPENDRAIN | GPIO_PULLUP); // NSS -> PMW3901
Init(SPI2);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void SPI2_TransferCons(const void* WriteData, unsigned long WriteSize, void* ReadData, unsigned long ReadSize)
{
CS_IMU(true);
Trans(SPI2, WriteData, 0, WriteSize);
Trans(SPI2, 0, ReadData, ReadSize);
CS_IMU(false);
}
//------------------------------------------------------------------------------
void SPI2_TransferParallel(const void* WriteData, void* ReadData, unsigned long Size)
{
CS_IMU(true);
Trans(SPI2, WriteData, ReadData, Size);
CS_IMU(false);
}
//-----------------------------------------------------------------------------

12
drv/spi.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
void SPI1_Init();
void SPI1_TransferCons(const void* WriteData, unsigned long WriteSize, void* ReadData, unsigned long ReadSize);
void SPI1_TransferParallel(const void* WriteData, void* ReadData, unsigned long Size);
void SPI2_Init();
void SPI2_TransferCons(const void* WriteData, unsigned long WriteSize, void* ReadData, unsigned long ReadSize);
void SPI2_TransferParallel(const void* WriteData, void* ReadData, unsigned long Size);

36
drv/tick.cpp Normal file
View File

@ -0,0 +1,36 @@
#include "stm32g4xx.h"
#include "tick.h"
static unsigned long Tick = 0;
extern "C" void SysTick_Handler()
{
Tick++;
}
//------------------------------------------------------------------------------
void TICK_Init()
{
SysTick->LOAD = SystemCoreClock / 1000;
SysTick->VAL = 0UL;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
NVIC_SetPriority(SysTick_IRQn, 0);
}
//------------------------------------------------------------------------------
unsigned long TICK_GetCount() // ms
{
return Tick;
}
//------------------------------------------------------------------------------
void Tick_Delay(unsigned long ms)
{
const unsigned long start = Tick;
while ((Tick - start) < ms) {
__NOP();
}
}

5
drv/tick.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
void TICK_Init();
unsigned long TICK_GetCount();
void Tick_Delay(unsigned long ms);

34
drv/tim.cpp Normal file
View File

@ -0,0 +1,34 @@
#include "stm32g4xx.h"
#include "tim.h"
static void (*TIM7_Proc)() = 0;
extern "C" void TIM7_IRQHandler()
{
TIM7->SR = 0;
TIM7_Proc();
}
//------------------------------------------------------------------------------
void TIM7_Init(long Priority)
{
RCC->APB1ENR1 |= RCC_APB1ENR1_TIM7EN;
TIM7->CR1 = 0;
TIM7->ARR = 1000 - 1;
TIM7->DIER = TIM_DIER_UIE;
NVIC_SetPriority(TIM7_IRQn, Priority);
NVIC_EnableIRQ(TIM7_IRQn);
}
//------------------------------------------------------------------------------
void TIM7_Update(unsigned long Freq, void (*Proc)())
{
TIM7->CR1 = 0;
TIM7->PSC = (SystemCoreClock / 1000 / Freq) - 1;
TIM7_Proc = Proc;
TIM7->CR1 = TIM_CR1_CEN;
}
//------------------------------------------------------------------------------

4
drv/tim.h Normal file
View File

@ -0,0 +1,4 @@
#pragma once
void TIM7_Init(long Priority);
void TIM7_Update(unsigned long Freq, void (*UpdateProc)());

237
drv/uart.cpp Normal file
View File

@ -0,0 +1,237 @@
#include "stm32g4xx.h"
#include <string.h>
#include "gpio.h"
#include "uart.h"
static const unsigned long UART_BuferSize=256;
struct UART_Data
{
USART_TypeDef* UART;
struct
{
unsigned long Size;
unsigned char* Buffer;
unsigned short Head;
unsigned short Tail;
unsigned short Push;
unsigned short Pull;
} Recv, Send;
};
static unsigned char UART3_BufferRecv[UART_BuferSize], UART3_BufferSend[UART_BuferSize];
static UART_Data UART3_Data{ USART3, {sizeof(UART3_BufferRecv), UART3_BufferRecv, 0, 0, 0, 0}, {sizeof(UART3_BufferSend), UART3_BufferSend, 0, 0, 0, 0} };
static unsigned char UART2_BufferRecv[UART_BuferSize], UART2_BufferSend[UART_BuferSize];
static UART_Data UART2_Data{ USART2, {sizeof(UART2_BufferRecv), UART2_BufferRecv, 0, 0, 0, 0}, {sizeof(UART2_BufferSend), UART2_BufferSend, 0, 0, 0, 0} };
static unsigned char UART1_BufferRecv[UART_BuferSize], UART1_BufferSend[UART_BuferSize];
static UART_Data UART1_Data{ USART1, {sizeof(UART1_BufferRecv), UART1_BufferRecv, 0, 0, 0, 0}, {sizeof(UART1_BufferSend), UART1_BufferSend, 0, 0, 0, 0} };
static void IRQHandler(UART_Data& Uart)
{
unsigned long isr = Uart.UART->ISR;
if(isr & USART_ISR_RXNE)
{
Uart.Recv.Buffer[Uart.Recv.Head] = Uart.UART->RDR;
if(Uart.Recv.Push-Uart.Recv.Pull<Uart.Recv.Size)
{
Uart.Recv.Head++;
Uart.Recv.Push++;
}
if(Uart.Recv.Head>=Uart.Recv.Size) Uart.Recv.Head=0;
}
if(isr & USART_ISR_TXE)
{
if(Uart.Send.Push != Uart.Send.Pull)
{
Uart.UART->TDR = Uart.Send.Buffer[Uart.Send.Tail++];
if(Uart.Send.Tail>=Uart.Send.Size) Uart.Send.Tail=0;
Uart.Send.Pull++;
}
else Uart.UART->CR1 &= ~USART_CR1_TXEIE;
}
}
//------------------------------------------------------------------------------
extern "C" void USART3_IRQHandler()
{
IRQHandler(UART3_Data);
}
//------------------------------------------------------------------------------
extern "C" void USART2_IRQHandler()
{
IRQHandler(UART2_Data);
}
//------------------------------------------------------------------------------
extern "C" void USART1_IRQHandler()
{
IRQHandler(UART1_Data);
}
//------------------------------------------------------------------------------
static void Init(USART_TypeDef* USART, unsigned long Baud)
{
USART->CR1 = 0;
USART->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE;
//USART->BRR = SystemCoreClock / 4 / Baud;
USART->BRR = SystemCoreClock / Baud;
USART->CR3 |= USART_CR3_OVRDIS;
USART->CR1 |= USART_CR1_UE;
}
//------------------------------------------------------------------------------
void UART3_Init(unsigned long Baud)
{
if (RCC->APB1ENR1 & RCC_APB1ENR1_USART3EN) return;
RCC->APB1ENR1 |= RCC_APB1ENR1_USART3EN;
GPIO_InitPin(GPIO_PIN_10 | GPIO_PORT_B | GPIO_ALTER | GPIO_AF7 | GPIO_OSPEED_HIGH);
GPIO_InitPin(GPIO_PIN_11 | GPIO_PORT_B | GPIO_ALTER | GPIO_AF7 | GPIO_OSPEED_HIGH);
Init(USART3, Baud);
NVIC_SetPriority(USART3_IRQn, 0);
NVIC_EnableIRQ(USART3_IRQn);
}
//------------------------------------------------------------------------------
void UART2_Init(unsigned long Baud)
{
if (RCC->APB1ENR1 & RCC_APB1ENR1_USART2EN) return;
RCC->APB1ENR1 |= RCC_APB1ENR1_USART2EN;
GPIO_InitPin(GPIO_PIN_3 | GPIO_PORT_B | GPIO_ALTER | GPIO_AF7 | GPIO_OSPEED_HIGH);
GPIO_InitPin(GPIO_PIN_4 | GPIO_PORT_B | GPIO_ALTER | GPIO_AF7 | GPIO_OSPEED_HIGH);
Init(USART2, Baud);
NVIC_SetPriority(USART2_IRQn, 0);
NVIC_EnableIRQ(USART2_IRQn);
}
//------------------------------------------------------------------------------
void UART1_Init(unsigned long Baud)
{
if (RCC->APB2ENR & RCC_APB2ENR_USART1EN) return;
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
GPIO_InitPin(GPIO_PIN_6 | GPIO_PORT_B | GPIO_ALTER | GPIO_AF7 | GPIO_OSPEED_HIGH);
GPIO_InitPin(GPIO_PIN_7 | GPIO_PORT_B | GPIO_ALTER | GPIO_AF7 | GPIO_OSPEED_HIGH);
Init(USART1, Baud);
NVIC_SetPriority(USART1_IRQn, 0);
NVIC_EnableIRQ(USART1_IRQn);
}
//------------------------------------------------------------------------------
static unsigned long Recv(UART_Data& Uart, void* Data, unsigned long Size)
{
if(!Data) return Uart.Recv.Push-Uart.Recv.Pull;
unsigned char* data=(unsigned char*)Data;
unsigned long size = 0;
while (size < Size)
{
if (Uart.Recv.Push == Uart.Recv.Pull) break;
data[size++] = Uart.Recv.Buffer[Uart.Recv.Tail++];
if(Uart.Recv.Tail>=Uart.Recv.Size) Uart.Recv.Tail=0;
Uart.Recv.Pull++;
}
return size;
}
//------------------------------------------------------------------------------
static unsigned long Send(UART_Data& Uart, const void* Data, unsigned long Size)
{
unsigned char* data=(unsigned char*)Data;
unsigned long size = 0;
while (size < Size)
{
if (Uart.Send.Push - Uart.Send.Pull >= Uart.Send.Size) break;
Uart.Send.Buffer[Uart.Send.Head++] = data[size++];
if(Uart.Send.Head>=Uart.Send.Size) Uart.Send.Head=0;
Uart.Send.Push++;
}
Uart.UART->CR1 |= USART_CR1_TXEIE;
return size;
}
//------------------------------------------------------------------------------
static inline void Flush(UART_Data& Uart)
{
Uart.Recv.Tail=Uart.Recv.Head;
Uart.Recv.Pull=Uart.Recv.Push;
}
//------------------------------------------------------------------------------
unsigned long UART3_Recv(void* Data, unsigned long Size)
{
return Recv(UART3_Data, Data, Size);
}
//------------------------------------------------------------------------------
void UART3_Flush()
{
Flush(UART3_Data);
}
//------------------------------------------------------------------------------
unsigned long UART3_Send(const void* Data, unsigned long Size)
{
return Send(UART3_Data, Data, Size);
}
//------------------------------------------------------------------------------
unsigned long UART2_Recv(void* Data, unsigned long Size)
{
return Recv(UART2_Data, Data, Size);
}
//------------------------------------------------------------------------------
void UART2_Flush()
{
Flush(UART2_Data);
}
//------------------------------------------------------------------------------
unsigned long UART2_Send(const void* Data, unsigned long Size)
{
return Send(UART2_Data, Data, Size);
}
//------------------------------------------------------------------------------
unsigned long UART1_Recv(void* Data, unsigned long Size)
{
return Recv(UART1_Data, Data, Size);
}
//------------------------------------------------------------------------------
void UART1_Flush()
{
Flush(UART1_Data);
}
//------------------------------------------------------------------------------
unsigned long UART1_Send(const void* Data, unsigned long Size)
{
return Send(UART1_Data, Data, Size);
}
//------------------------------------------------------------------------------

16
drv/uart.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
void UART3_Init(unsigned long Baud);
void UART3_Flush();
unsigned long UART3_Recv(void* Data, unsigned long Size);
unsigned long UART3_Send(const void* Data, unsigned long Size);
void UART2_Init(unsigned long Baud);
void UART2_Flush();
unsigned long UART2_Recv(void* Data, unsigned long Size);
unsigned long UART2_Send(const void* Data, unsigned long Size);
void UART1_Init(unsigned long Baud);
void UART1_Flush();
unsigned long UART1_Recv(void* Data, unsigned long Size);
unsigned long UART1_Send(const void* Data, unsigned long Size);

1053
drv/vl53l0x.cpp Normal file

File diff suppressed because it is too large Load Diff

186
drv/vl53l0x.h Normal file
View File

@ -0,0 +1,186 @@
#ifndef VL53L0X_h
#define VL53L0X_h
#include <cstdint>
#include "tick.h"
class VL53L0X
{
public:
// register addresses from API vl53l0x_device.h (ordered as listed there)
enum regAddr
{
SYSRANGE_START = 0x00,
SYSTEM_THRESH_HIGH = 0x0C,
SYSTEM_THRESH_LOW = 0x0E,
SYSTEM_SEQUENCE_CONFIG = 0x01,
SYSTEM_RANGE_CONFIG = 0x09,
SYSTEM_INTERMEASUREMENT_PERIOD = 0x04,
SYSTEM_INTERRUPT_CONFIG_GPIO = 0x0A,
GPIO_HV_MUX_ACTIVE_HIGH = 0x84,
SYSTEM_INTERRUPT_CLEAR = 0x0B,
RESULT_INTERRUPT_STATUS = 0x13,
RESULT_RANGE_STATUS = 0x14,
RESULT_CORE_AMBIENT_WINDOW_EVENTS_RTN = 0xBC,
RESULT_CORE_RANGING_TOTAL_EVENTS_RTN = 0xC0,
RESULT_CORE_AMBIENT_WINDOW_EVENTS_REF = 0xD0,
RESULT_CORE_RANGING_TOTAL_EVENTS_REF = 0xD4,
RESULT_PEAK_SIGNAL_RATE_REF = 0xB6,
ALGO_PART_TO_PART_RANGE_OFFSET_MM = 0x28,
I2C_SLAVE_DEVICE_ADDRESS = 0x8A,
MSRC_CONFIG_CONTROL = 0x60,
PRE_RANGE_CONFIG_MIN_SNR = 0x27,
PRE_RANGE_CONFIG_VALID_PHASE_LOW = 0x56,
PRE_RANGE_CONFIG_VALID_PHASE_HIGH = 0x57,
PRE_RANGE_MIN_COUNT_RATE_RTN_LIMIT = 0x64,
FINAL_RANGE_CONFIG_MIN_SNR = 0x67,
FINAL_RANGE_CONFIG_VALID_PHASE_LOW = 0x47,
FINAL_RANGE_CONFIG_VALID_PHASE_HIGH = 0x48,
FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT = 0x44,
PRE_RANGE_CONFIG_SIGMA_THRESH_HI = 0x61,
PRE_RANGE_CONFIG_SIGMA_THRESH_LO = 0x62,
PRE_RANGE_CONFIG_VCSEL_PERIOD = 0x50,
PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI = 0x51,
PRE_RANGE_CONFIG_TIMEOUT_MACROP_LO = 0x52,
SYSTEM_HISTOGRAM_BIN = 0x81,
HISTOGRAM_CONFIG_INITIAL_PHASE_SELECT = 0x33,
HISTOGRAM_CONFIG_READOUT_CTRL = 0x55,
FINAL_RANGE_CONFIG_VCSEL_PERIOD = 0x70,
FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI = 0x71,
FINAL_RANGE_CONFIG_TIMEOUT_MACROP_LO = 0x72,
CROSSTALK_COMPENSATION_PEAK_RATE_MCPS = 0x20,
MSRC_CONFIG_TIMEOUT_MACROP = 0x46,
SOFT_RESET_GO2_SOFT_RESET_N = 0xBF,
IDENTIFICATION_MODEL_ID = 0xC0,
IDENTIFICATION_REVISION_ID = 0xC2,
OSC_CALIBRATE_VAL = 0xF8,
GLOBAL_CONFIG_VCSEL_WIDTH = 0x32,
GLOBAL_CONFIG_SPAD_ENABLES_REF_0 = 0xB0,
GLOBAL_CONFIG_SPAD_ENABLES_REF_1 = 0xB1,
GLOBAL_CONFIG_SPAD_ENABLES_REF_2 = 0xB2,
GLOBAL_CONFIG_SPAD_ENABLES_REF_3 = 0xB3,
GLOBAL_CONFIG_SPAD_ENABLES_REF_4 = 0xB4,
GLOBAL_CONFIG_SPAD_ENABLES_REF_5 = 0xB5,
GLOBAL_CONFIG_REF_EN_START_SELECT = 0xB6,
DYNAMIC_SPAD_NUM_REQUESTED_REF_SPAD = 0x4E,
DYNAMIC_SPAD_REF_EN_START_OFFSET = 0x4F,
POWER_MANAGEMENT_GO1_POWER_FORCE = 0x80,
VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV = 0x89,
ALGO_PHASECAL_LIM = 0x30,
ALGO_PHASECAL_CONFIG_TIMEOUT = 0x30,
};
enum vcselPeriodType { VcselPeriodPreRange, VcselPeriodFinalRange };
uint8_t last_status; // status of last I2C transmission
VL53L0X();
void setAddress(uint8_t new_addr);
inline uint8_t getAddress() { return address; }
bool init(bool io_2v8 = true);
void writeReg(uint8_t reg, uint8_t value);
void writeReg16Bit(uint8_t reg, uint16_t value);
void writeReg32Bit(uint8_t reg, uint32_t value);
uint8_t readReg(uint8_t reg);
uint16_t readReg16Bit(uint8_t reg);
uint32_t readReg32Bit(uint8_t reg);
void writeMulti(uint8_t reg, uint8_t const * src, uint8_t count);
void readMulti(uint8_t reg, uint8_t * dst, uint8_t count);
bool setSignalRateLimit(float limit_Mcps);
float getSignalRateLimit();
bool setMeasurementTimingBudget(uint32_t budget_us);
uint32_t getMeasurementTimingBudget();
bool setVcselPulsePeriod(vcselPeriodType type, uint8_t period_pclks);
uint8_t getVcselPulsePeriod(vcselPeriodType type);
void startContinuous(uint32_t period_ms = 0);
void stopContinuous();
uint16_t readRangeContinuousMillimeters();
uint16_t readRangeSingleMillimeters();
bool isRangeReady();
uint16_t readRange();
inline void setTimeout(uint16_t timeout) { io_timeout = timeout; }
inline uint16_t getTimeout() { return io_timeout; }
bool timeoutOccurred();
private:
// TCC: Target CentreCheck
// MSRC: Minimum Signal Rate Check
// DSS: Dynamic Spad Selection
struct SequenceStepEnables
{
bool tcc, msrc, dss, pre_range, final_range;
};
struct SequenceStepTimeouts
{
uint16_t pre_range_vcsel_period_pclks, final_range_vcsel_period_pclks;
uint16_t msrc_dss_tcc_mclks, pre_range_mclks, final_range_mclks;
uint32_t msrc_dss_tcc_us, pre_range_us, final_range_us;
};
uint8_t address;
uint16_t io_timeout;
bool did_timeout;
uint16_t timeout_start_ms;
uint8_t stop_variable; // read by init and used when starting measurement; is StopVariable field of VL53L0X_DevData_t structure in API
uint32_t measurement_timing_budget_us;
bool getSpadInfo(uint8_t * count, bool * type_is_aperture);
void getSequenceStepEnables(SequenceStepEnables * enables);
void getSequenceStepTimeouts(SequenceStepEnables const * enables, SequenceStepTimeouts * timeouts);
bool performSingleRefCalibration(uint8_t vhv_init_byte);
static uint16_t decodeTimeout(uint16_t value);
static uint16_t encodeTimeout(uint32_t timeout_mclks);
static uint32_t timeoutMclksToMicroseconds(uint16_t timeout_period_mclks, uint8_t vcsel_period_pclks);
static uint32_t timeoutMicrosecondsToMclks(uint32_t timeout_period_us, uint8_t vcsel_period_pclks);
};
#endif