mirror of
https://github.com/eddyem/stm32samples.git
synced 2025-12-06 10:45:11 +03:00
add a little (ADC2 don't work - it's weird)
This commit is contained in:
parent
6902b60020
commit
6832befb4a
@ -202,3 +202,15 @@ Automated liquid nitrogen flooding machine
|
||||
| 10 | PF9 | - | - | |
|
||||
| 11 | PF10 | VadcON | slow out | turn ON ADC power|
|
||||
|---------|-------------|-------------|-------------|------------------|
|
||||
|
||||
|
||||
## DMA usage
|
||||
### DMA1
|
||||
|
||||
- Channel 1 - ADC1
|
||||
- Channel 6 - I2C1 Tx
|
||||
- Channel 7 - I2C1 Rx
|
||||
|
||||
### DMA2
|
||||
|
||||
- Channel 2 - ADC2
|
||||
|
||||
@ -25,9 +25,9 @@
|
||||
* @brief ADCx_array - arrays for ADC channels with median filtering:
|
||||
* ADC1:
|
||||
* 0..9 - AIN0..9 (ADC1_IN1..10)
|
||||
* 4 - internal Tsens - ADC1_IN16
|
||||
* 10 - internal Tsens - ADC1_IN16
|
||||
* ADC2:
|
||||
* 6 - AINext - (ADC2 in 1)
|
||||
* 11 - AINext - (ADC2 in 1)
|
||||
*/
|
||||
static uint16_t ADC_array[NUMBER_OF_ADC_CHANNELS*9];
|
||||
|
||||
@ -66,7 +66,7 @@ TRUE_INLINE void enADC(ADC_TypeDef *chnl){
|
||||
* ADC1 - DMA1_ch1
|
||||
* ADC2 - DMA2_ch1
|
||||
*/
|
||||
// Setup ADC and DAC
|
||||
// Setup ADC
|
||||
void adc_setup(){
|
||||
RCC->AHBENR |= RCC_AHBENR_ADC12EN; // Enable clocking
|
||||
ADC12_COMMON->CCR = ADC_CCR_TSEN | ADC_CCR_CKMODE; // enable Tsens, HCLK/4
|
||||
@ -83,7 +83,6 @@ void adc_setup(){
|
||||
ADC2->SMPR1 = ADC_SMPR1_SMP1;
|
||||
ADC2->SQR1 = (1<<6) | (NUMBER_OF_ADC2_CHANNELS-1);
|
||||
// configure DMA for ADC
|
||||
RCC->AHBENR |= RCC_AHBENR_DMA1EN | RCC_AHBENR_DMA2EN;
|
||||
ADC1->CFGR = ADC_CFGR_CONT | ADC_CFGR_DMAEN | ADC_CFGR_DMACFG;
|
||||
ADC2->CFGR = ADC_CFGR_CONT | ADC_CFGR_DMAEN | ADC_CFGR_DMACFG;
|
||||
DMA1_Channel1->CPAR = (uint32_t) (&(ADC1->DR));
|
||||
@ -112,8 +111,11 @@ uint16_t getADCval(int nch){
|
||||
#define PIX_SORT(a,b) { if ((a)>(b)) PIX_SWAP((a),(b)); }
|
||||
#define PIX_SWAP(a,b) { temp=(a);(a)=(b);(b)=temp; }
|
||||
uint16_t p[9];
|
||||
int adval = (nch >= NUMBER_OF_ADC1_CHANNELS) ? NUMBER_OF_ADC2_CHANNELS : NUMBER_OF_ADC1_CHANNELS;
|
||||
int addr = (nch >= NUMBER_OF_ADC1_CHANNELS) ? nch - NUMBER_OF_ADC2_CHANNELS + ADC2START: nch;
|
||||
int addr = nch, adval = NUMBER_OF_ADC1_CHANNELS;
|
||||
if(nch >= NUMBER_OF_ADC1_CHANNELS){
|
||||
adval = NUMBER_OF_ADC2_CHANNELS;
|
||||
addr += ADC2START;
|
||||
}
|
||||
for(int i = 0; i < 9; ++i, addr += adval) // first we should prepare array for optmed
|
||||
p[i] = ADC_array[addr];
|
||||
PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ;
|
||||
|
||||
@ -17,19 +17,23 @@
|
||||
*/
|
||||
|
||||
#include "hardware.h"
|
||||
#include "i2c.h"
|
||||
|
||||
int LEDsON = 0;
|
||||
|
||||
// setup here ALL GPIO pins (due to table in Readme.md)
|
||||
// leave SWD as default AF; high speed for CLK and some other AF; med speed for some another AF
|
||||
TRUE_INLINE void gpio_setup(){
|
||||
BUZZER_OFF();
|
||||
ADCON(0);
|
||||
pin_set(LEDs_port, 0xf<<8); // turn off LEDs
|
||||
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN | RCC_AHBENR_GPIODEN
|
||||
| RCC_AHBENR_GPIOEEN | RCC_AHBENR_GPIOFEN;
|
||||
// enable PWM timer TIM3
|
||||
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
|
||||
for(int i = 0; i < 10000; ++i) nop();
|
||||
// PORT A (PA13/14 - SWDIO/SWCLK - AF0)
|
||||
GPIOA->ODR = 0;
|
||||
//GPIOA->ODR = 0;
|
||||
GPIOA->AFR[0] = 0;
|
||||
GPIOA->AFR[1] = AFRf(4, 9) | AFRf(4, 10) | AFRf(14, 11) | AFRf(14,12);
|
||||
GPIOA->MODER = MODER_AI(0) | MODER_AI(1) | MODER_AI(2) | MODER_AI(3) | MODER_AI(4) |
|
||||
@ -39,7 +43,7 @@ TRUE_INLINE void gpio_setup(){
|
||||
GPIOA->PUPDR = PUPD_PU(13) | PUPD_PD(14); // SWDIO - pullup, SDCLK - pulldown
|
||||
|
||||
// PORT B
|
||||
GPIOB->ODR = 0;
|
||||
//GPIOB->ODR = 0;
|
||||
GPIOB->AFR[0] = AFRf(4, 6) | AFRf(4, 7);
|
||||
GPIOB->AFR[1] = AFRf(5, 13) | AFRf(5, 14) | AFRf(5, 15);
|
||||
GPIOB->MODER = MODER_O(0) | MODER_AF(6) | MODER_AF(7) | MODER_O(10) | MODER_O(11) | MODER_O(12) | MODER_AF(13)
|
||||
@ -49,7 +53,7 @@ TRUE_INLINE void gpio_setup(){
|
||||
GPIOB->PUPDR = 0;
|
||||
|
||||
// PORT C
|
||||
GPIOC->ODR = 0;
|
||||
//GPIOC->ODR = 0;
|
||||
GPIOC->AFR[0] = 0;
|
||||
GPIOC->AFR[1] = AFRf(7, 10) | AFRf(7, 11);
|
||||
GPIOC->MODER = MODER_AI(0) | MODER_AI(1) | MODER_AI(2) | MODER_AI(3) | MODER_O(9) | MODER_AF(10) | MODER_AF(11);
|
||||
@ -58,7 +62,7 @@ TRUE_INLINE void gpio_setup(){
|
||||
GPIOC->PUPDR = 0;
|
||||
|
||||
// PORT D
|
||||
GPIOD->ODR = 0;
|
||||
//GPIOD->ODR = 0;
|
||||
GPIOD->AFR[0] = AFRf(7, 0) | AFRf(7, 1) | AFRf(7, 5) | AFRf(7, 6);
|
||||
GPIOD->AFR[1] = 0;
|
||||
GPIOD->MODER = MODER_AF(0) | MODER_AF(1) | MODER_O(4) | MODER_AF(5) | MODER_AF(6) | MODER_I(9)
|
||||
@ -68,7 +72,7 @@ TRUE_INLINE void gpio_setup(){
|
||||
GPIOD->PUPDR = PUPD_PU(9) | PUPD_PU(10) | PUPD_PU(11) | PUPD_PU(12) | PUPD_PU(13) | PUPD_PU(14) | PUPD_PU(15);
|
||||
|
||||
// PORT E
|
||||
GPIOE->ODR = 0;
|
||||
//GPIOE->ODR = 0;
|
||||
GPIOE->AFR[0] = 0;
|
||||
GPIOE->AFR[1] = AFRf(2, 2) | AFRf(2, 3) | AFRf(2, 4) | AFRf(2, 5);
|
||||
GPIOE->MODER = MODER_AF(2) | MODER_AF(3) | MODER_AF(4) | MODER_AF(5) | MODER_O(8) | MODER_O(9) | MODER_O(10) | MODER_O(11);
|
||||
@ -77,7 +81,7 @@ TRUE_INLINE void gpio_setup(){
|
||||
GPIOE->PUPDR = 0;
|
||||
|
||||
// PORT F
|
||||
GPIOF->ODR = 0;
|
||||
//GPIOF->ODR = 0;
|
||||
GPIOF->AFR[0] = 0;
|
||||
GPIOF->AFR[1] = 0;
|
||||
GPIOF->MODER = MODER_AI(2) | MODER_O(10);
|
||||
@ -86,6 +90,19 @@ TRUE_INLINE void gpio_setup(){
|
||||
GPIOF->PUPDR = 0;
|
||||
}
|
||||
|
||||
TRUE_INLINE void pwm_setup(){
|
||||
TIM3->CR1 = TIM_CR1_ARPE;
|
||||
TIM3->PSC = 1999; // 48M/2000 = 24kHz
|
||||
// PWM mode 1 (active -> inactive)
|
||||
TIM3->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1;
|
||||
TIM3->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1;
|
||||
TIM3->CCR1 = 0;
|
||||
TIM3->ARR = 255; // 8bit PWM
|
||||
TIM3->BDTR |= TIM_BDTR_MOE; // enable main output
|
||||
TIM3->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E | TIM_CCER_CC4E;
|
||||
TIM3->CR1 |= TIM_CR1_CEN;
|
||||
}
|
||||
|
||||
#ifndef EBUG
|
||||
TRUE_INLINE void iwdg_setup(){
|
||||
uint32_t tmout = 16000000;
|
||||
@ -112,9 +129,50 @@ TRUE_INLINE void iwdg_setup(){
|
||||
#endif
|
||||
|
||||
void hw_setup(){
|
||||
RCC->AHBENR |= RCC_AHBENR_DMA1EN | RCC_AHBENR_DMA2EN;
|
||||
gpio_setup();
|
||||
i2c_setup(HIGH_SPEED);
|
||||
pwm_setup();
|
||||
#ifndef EBUG
|
||||
iwdg_setup();
|
||||
#endif
|
||||
}
|
||||
|
||||
void setPWM(int nch, uint8_t val){
|
||||
switch(nch){
|
||||
case 0:
|
||||
TIM3->CCR1 = val;
|
||||
break;
|
||||
case 1:
|
||||
TIM3->CCR2 = val;
|
||||
break;
|
||||
case 2:
|
||||
TIM3->CCR3 = val;
|
||||
break;
|
||||
case 3:
|
||||
TIM3->CCR4 = val;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t getPWM(int nch){
|
||||
switch(nch){
|
||||
case 0:
|
||||
return TIM3->CCR1;
|
||||
break;
|
||||
case 1:
|
||||
return TIM3->CCR2;
|
||||
break;
|
||||
case 2:
|
||||
return TIM3->CCR3;
|
||||
break;
|
||||
case 3:
|
||||
return TIM3->CCR4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -60,8 +60,22 @@
|
||||
// state 0 - pressed, 1 - released
|
||||
#define BTN_state(x) (BTNs_port->IDR & 1<<(9+x) ? 0 : 1)
|
||||
|
||||
// buzzer, ADC voltage
|
||||
#define BUZZER_port GPIOB
|
||||
#define BUZZER_pin (1<<0)
|
||||
#define BUZZER_ON() do{pin_clear(BUZZER_port, BUZZER_pin);}while(0)
|
||||
#define BUZZER_OFF() do{pin_set(BUZZER_port, BUZZER_pin);}while(0)
|
||||
#define BUZZER_STATE() (BUZZER_port->IDR & BUZZER_pin ? 0 : 1)
|
||||
#define ADCON_port GPIOF
|
||||
#define ADCON_pin (1<<10)
|
||||
#define ADCON(x) do{if(x==0) pin_set(ADCON_port, ADCON_pin); else pin_clear(ADCON_port, ADCON_pin);}while(0)
|
||||
#define ADCONSTATE() (ADCON_port->IDR & ADCON_pin ? 0 : 1)
|
||||
|
||||
extern volatile uint32_t Tms;
|
||||
extern int LEDsON;
|
||||
|
||||
uint8_t MSB(uint16_t val);
|
||||
void hw_setup();
|
||||
|
||||
void setPWM(int nch, uint8_t val);
|
||||
uint8_t getPWM(int nch);
|
||||
|
||||
313
F3:F303/NitrogenFlooding/i2c.c
Normal file
313
F3:F303/NitrogenFlooding/i2c.c
Normal file
@ -0,0 +1,313 @@
|
||||
/*
|
||||
* This file is part of the nitrogen 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 <string.h>
|
||||
|
||||
#include "i2c.h"
|
||||
#include "strfunc.h" // hexdump
|
||||
#include "usb.h"
|
||||
|
||||
I2C_SPEED curI2Cspeed = LOW_SPEED;
|
||||
extern volatile uint32_t Tms;
|
||||
static uint32_t cntr;
|
||||
static uint8_t i2c_got_DMA_Rx = 0;
|
||||
volatile uint8_t I2C_scan_mode = 0; // == 1 when I2C is in scan mode
|
||||
static uint8_t i2caddr = I2C_ADDREND; // current address in scan mode
|
||||
static volatile int I2Cbusy = 0, goterr = 0; // busy==1 when DMA active, goterr==1 if 't was error @ last sent
|
||||
static uint8_t I2Cbuf[256], i2cbuflen = 0; // buffer for DMA tx/rx and its len
|
||||
|
||||
// macros for I2C rx/tx
|
||||
#define DMARXCCR (DMA_CCR_MINC | DMA_CCR_TCIE | DMA_CCR_TEIE)
|
||||
#define DMATXCCR (DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE | DMA_CCR_TEIE)
|
||||
// macro for I2CCR1
|
||||
#define I2CCR1 (I2C_CR1_PE | I2C_CR1_RXDMAEN | I2C_CR1_TXDMAEN)
|
||||
|
||||
// return 1 if I2Cbusy is set & timeout reached
|
||||
static inline int isI2Cbusy(){
|
||||
cntr = Tms;
|
||||
do{
|
||||
if(Tms - cntr > I2C_TIMEOUT){ USND("Timeout, DMA transfer in progress?\n"); return 1;}
|
||||
}while(I2Cbusy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// GPIO Resources: I2C1_SCL - PB6 (AF4), I2C1_SDA - PB7 (AF4)
|
||||
void i2c_setup(I2C_SPEED speed){
|
||||
if(speed >= CURRENT_SPEED){
|
||||
speed = curI2Cspeed;
|
||||
}else{
|
||||
curI2Cspeed = speed;
|
||||
}
|
||||
RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
|
||||
I2C1->CR1 = 0;
|
||||
I2C1->ICR = 0x3f38; // clear all errors
|
||||
GPIOB->AFR[0] = (GPIOB->AFR[0] & ~(GPIO_AFRL_AFRL6 | GPIO_AFRL_AFRL7)) |
|
||||
AFRf(4, 6) | AFRf(4, 7);
|
||||
GPIOB->MODER = (GPIOB->MODER & ~(GPIO_MODER_MODER6 | GPIO_MODER_MODER7)) |
|
||||
GPIO_MODER_MODER6_AF | GPIO_MODER_MODER7_AF;
|
||||
GPIOB->PUPDR = (GPIOB->PUPDR & !(GPIO_PUPDR_PUPDR6 | GPIO_PUPDR_PUPDR7)) |
|
||||
GPIO_PUPDR6_PU | GPIO_PUPDR7_PU; // pullup (what if there's no external pullup?)
|
||||
GPIOB->OTYPER |= GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_7; // both open-drain outputs
|
||||
// I2C (default timing from PCLK - 64MHz)
|
||||
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // clocking
|
||||
if(speed == LOW_SPEED){ // 10kHz
|
||||
// PRESC=F, SCLDEL=4, SDADEL=2, SCLH=0xC3, SCLL=0xC7
|
||||
I2C1->TIMINGR = (0xF<<28) | (4<<20) | (2<<16) | (0xC3<<8) | (0xC7);
|
||||
}else if(speed == HIGH_SPEED){ // 100kHz
|
||||
I2C1->TIMINGR = (0xF<<28) | (4<<20) | (2<<16) | (0xF<<8) | (0x13);
|
||||
}else{ // VERYLOW_SPEED - the lowest speed by STM register: ~7.7kHz
|
||||
I2C1->TIMINGR = (0xF<<28) | (4<<20) | (2<<16) | (0xff<<8) | (0xff);
|
||||
}
|
||||
I2C1->CR1 = I2CCR1;
|
||||
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
|
||||
NVIC_EnableIRQ(DMA1_Channel6_IRQn);
|
||||
NVIC_EnableIRQ(DMA1_Channel7_IRQn);
|
||||
I2Cbusy = 0;
|
||||
}
|
||||
|
||||
// setup DMA for rx (tx==0) or tx (tx==1)
|
||||
// DMA channels: 7 - I2C1_Rx, 6 - I2C1_Tx
|
||||
static void i2cDMAsetup(int tx, uint8_t len){
|
||||
if(tx){
|
||||
DMA1_Channel6->CCR = DMATXCCR;
|
||||
DMA1_Channel6->CPAR = (uint32_t) &I2C1->TXDR;
|
||||
DMA1_Channel6->CMAR = (uint32_t) I2Cbuf;
|
||||
DMA1_Channel6->CNDTR = i2cbuflen = len;
|
||||
}else{
|
||||
DMA1_Channel7->CCR = DMARXCCR;
|
||||
DMA1_Channel7->CPAR = (uint32_t) &I2C1->RXDR;
|
||||
DMA1_Channel7->CMAR = (uint32_t) I2Cbuf;
|
||||
DMA1_Channel7->CNDTR = i2cbuflen = len;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t i2c_start(uint8_t busychk){
|
||||
if(busychk){
|
||||
cntr = Tms;
|
||||
while(I2C1->ISR & I2C_ISR_BUSY){
|
||||
IWDG->KR = IWDG_REFRESH;
|
||||
if(Tms - cntr > I2C_TIMEOUT){
|
||||
USND("Line busy\n");
|
||||
return 0; // check busy
|
||||
}}
|
||||
}
|
||||
cntr = Tms;
|
||||
while(I2C1->CR2 & I2C_CR2_START){
|
||||
IWDG->KR = IWDG_REFRESH;
|
||||
if(Tms - cntr > I2C_TIMEOUT){
|
||||
USND("No start\n");
|
||||
return 0; // check start
|
||||
}}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// start writing
|
||||
static uint8_t i2c_startw(uint8_t addr, uint8_t nbytes, uint8_t stop){
|
||||
if(!i2c_start(1)) return 0;
|
||||
I2C1->CR2 = nbytes << 16 | addr;
|
||||
if(stop) I2C1->CR2 |= I2C_CR2_AUTOEND; // autoend
|
||||
// now start transfer
|
||||
I2C1->CR2 |= I2C_CR2_START;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* write command byte to I2C
|
||||
* @param addr - device address (TSYS01_ADDR0 or TSYS01_ADDR1)
|
||||
* @param data - bytes to write
|
||||
* @param nbytes - amount of bytes to write
|
||||
* @param stop - to set STOP
|
||||
* @return 0 if error
|
||||
*/
|
||||
static uint8_t write_i2cs(uint8_t addr, uint8_t *data, uint8_t nbytes, uint8_t stop){
|
||||
if(!i2c_startw(addr, nbytes, stop)) return 0;
|
||||
for(int i = 0; i < nbytes; ++i){
|
||||
cntr = Tms;
|
||||
while(!(I2C1->ISR & I2C_ISR_TXIS)){ // ready to transmit
|
||||
IWDG->KR = IWDG_REFRESH;
|
||||
if(I2C1->ISR & I2C_ISR_NACKF){
|
||||
I2C1->ICR |= I2C_ICR_NACKCF;
|
||||
//USND("NAK\n");
|
||||
return 0;
|
||||
}
|
||||
if(Tms - cntr > I2C_TIMEOUT){
|
||||
//USND("Timeout\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
I2C1->TXDR = data[i]; // send data
|
||||
}
|
||||
cntr = Tms;
|
||||
// wait for data gone
|
||||
while(I2C1->ISR & I2C_ISR_BUSY){
|
||||
IWDG->KR = IWDG_REFRESH;
|
||||
if(Tms - cntr > I2C_TIMEOUT){break;}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t write_i2c(uint8_t addr, uint8_t *data, uint8_t nbytes){
|
||||
if(isI2Cbusy()) return 0;
|
||||
return write_i2cs(addr, data, nbytes, 1);
|
||||
}
|
||||
|
||||
uint8_t write_i2c_dma(uint8_t addr, uint8_t *data, uint8_t nbytes){
|
||||
if(!data || nbytes < 1) return 0;
|
||||
if(isI2Cbusy()) return 0;
|
||||
memcpy((char*)I2Cbuf, (char*)data, nbytes);
|
||||
i2cDMAsetup(1, nbytes);
|
||||
goterr = 0;
|
||||
if(!i2c_startw(addr, nbytes, 1)) return 0;
|
||||
I2Cbusy = 1;
|
||||
DMA1_Channel6->CCR = DMATXCCR | DMA_CCR_EN; // start transfer
|
||||
return 1;
|
||||
}
|
||||
|
||||
// start reading
|
||||
static uint8_t i2c_startr(uint8_t addr, uint8_t nbytes, uint8_t busychk){
|
||||
if(!i2c_start(busychk)) return 0;
|
||||
// read N bytes
|
||||
I2C1->CR2 = (nbytes<<16) | addr | 1 | I2C_CR2_AUTOEND | I2C_CR2_RD_WRN;
|
||||
I2C1->CR2 |= I2C_CR2_START;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* read nbytes of data from I2C line
|
||||
* all functions with `addr` should have addr = address << 1
|
||||
* `data` should be an array with at least `nbytes` length
|
||||
* @return 1 if all OK, 0 if NACK or no device found
|
||||
*/
|
||||
static uint8_t read_i2cb(uint8_t addr, uint8_t *data, uint8_t nbytes, uint8_t busychk){
|
||||
if(!i2c_startr(addr, nbytes, busychk)) return 0;
|
||||
uint8_t i;
|
||||
for(i = 0; i < nbytes; ++i){
|
||||
cntr = Tms;
|
||||
while(!(I2C1->ISR & I2C_ISR_RXNE)){ // wait for data
|
||||
IWDG->KR = IWDG_REFRESH;
|
||||
if(I2C1->ISR & I2C_ISR_NACKF){
|
||||
I2C1->ICR |= I2C_ICR_NACKCF;
|
||||
//USND("NAK\n");
|
||||
return 0;
|
||||
}
|
||||
if(Tms - cntr > I2C_TIMEOUT){
|
||||
//USND("Timeout\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*data++ = I2C1->RXDR;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t read_i2c(uint8_t addr, uint8_t *data, uint8_t nbytes){
|
||||
if(isI2Cbusy()) return 0;
|
||||
return read_i2cb(addr, data, nbytes, 1);
|
||||
}
|
||||
|
||||
uint8_t read_i2c_dma(uint8_t addr, uint8_t nbytes){
|
||||
if(nbytes < 1) return 0;
|
||||
if(isI2Cbusy()) return 0;
|
||||
i2cDMAsetup(0, nbytes);
|
||||
goterr = 0;
|
||||
if(!i2c_startr(addr, nbytes, 1)) return 0;
|
||||
I2Cbusy = 1;
|
||||
DMA1_Channel7->CCR = DMARXCCR | DMA_CCR_EN; // start transfer
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// read register reg
|
||||
uint8_t read_i2c_reg(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t nbytes){
|
||||
if(isI2Cbusy()) return 0;
|
||||
if(!write_i2cs(addr, ®, 1, 0)) return 0;
|
||||
return read_i2cb(addr, data, nbytes, 0);
|
||||
}
|
||||
|
||||
// read 16bit register reg
|
||||
uint8_t read_i2c_reg16(uint8_t addr, uint16_t reg16, uint8_t *data, uint8_t nbytes){
|
||||
if(isI2Cbusy()) return 0;
|
||||
if(!write_i2cs(addr, (uint8_t*)®16, 2, 0)) return 0;
|
||||
return read_i2cb(addr, data, nbytes, 0);
|
||||
}
|
||||
|
||||
void i2c_init_scan_mode(){
|
||||
i2caddr = 1; // start from 1 as 0 is a broadcast address
|
||||
I2C_scan_mode = 1;
|
||||
}
|
||||
|
||||
// return 1 if next addr is active & return in as `addr`
|
||||
// if addresses are over, return 1 and set addr to I2C_NOADDR
|
||||
// if scan mode inactive, return 0 and set addr to I2C_NOADDR
|
||||
int i2c_scan_next_addr(uint8_t *addr){
|
||||
if(isI2Cbusy()) return 0;
|
||||
*addr = i2caddr;
|
||||
if(i2caddr == I2C_ADDREND){
|
||||
*addr = I2C_ADDREND;
|
||||
I2C_scan_mode = 0;
|
||||
return 0;
|
||||
}
|
||||
/*while(!u3txrdy);
|
||||
USND("Addr: "); USND(uhex2str(i2caddr)); USND("\n");
|
||||
usart3_sendbuf();*/
|
||||
uint8_t byte;
|
||||
if(!read_i2c((i2caddr++)<<1, &byte, 1)) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// dump I2Cbuf
|
||||
void i2c_bufdudump(){
|
||||
if(goterr){
|
||||
USND("Last transfer ends with error!\n");
|
||||
goterr = 0;
|
||||
}
|
||||
USND("I2C buffer:\n");
|
||||
hexdump(USB_sendstr, I2Cbuf, i2cbuflen);
|
||||
}
|
||||
|
||||
void i2c_have_DMA_Rx(){
|
||||
if(!i2c_got_DMA_Rx) return;
|
||||
i2c_got_DMA_Rx = 0;
|
||||
i2c_bufdudump();
|
||||
}
|
||||
|
||||
int i2cdma_haderr(){
|
||||
int r = goterr;
|
||||
goterr = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
// Rx (7) /Tx (6) interrupts
|
||||
static void I2C_isr(int rx){
|
||||
uint32_t isr = DMA1->ISR;
|
||||
DMA_Channel_TypeDef *ch = (rx) ? DMA1_Channel7 : DMA1_Channel6;
|
||||
if(isr & (DMA_ISR_TEIF6 | DMA_ISR_TEIF6)) goterr = 1;
|
||||
if(rx) i2c_got_DMA_Rx = 1; // last transfer was Rx
|
||||
ch->CCR = 0;
|
||||
I2Cbusy = 0;
|
||||
DMA1->IFCR = 0x0ff00000; // clear all flags for channel6/7
|
||||
}
|
||||
|
||||
void dma1_channel6_isr(){
|
||||
I2C_isr(0);
|
||||
}
|
||||
|
||||
void dma1_channel7_isr(){
|
||||
I2C_isr(1);
|
||||
}
|
||||
50
F3:F303/NitrogenFlooding/i2c.h
Normal file
50
F3:F303/NitrogenFlooding/i2c.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of the nitrogen 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>
|
||||
|
||||
#define I2C_ADDREND (0x80)
|
||||
|
||||
typedef enum{
|
||||
VERYLOW_SPEED,
|
||||
LOW_SPEED,
|
||||
HIGH_SPEED,
|
||||
CURRENT_SPEED
|
||||
} I2C_SPEED;
|
||||
|
||||
extern I2C_SPEED curI2Cspeed;
|
||||
extern volatile uint8_t I2C_scan_mode;
|
||||
|
||||
// timeout of I2C bus in ms
|
||||
#define I2C_TIMEOUT (100)
|
||||
|
||||
void i2c_setup(I2C_SPEED speed);
|
||||
uint8_t read_i2c(uint8_t addr, uint8_t *data, uint8_t nbytes);
|
||||
uint8_t read_i2c_reg(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t nbytes);
|
||||
uint8_t read_i2c_reg16(uint8_t addr, uint16_t reg16, uint8_t *data, uint8_t nbytes);
|
||||
uint8_t write_i2c(uint8_t addr, uint8_t *data, uint8_t nbytes);
|
||||
uint8_t write_i2c_dma(uint8_t addr, uint8_t *data, uint8_t nbytes);
|
||||
uint8_t read_i2c_dma(uint8_t addr, uint8_t nbytes);
|
||||
|
||||
void i2c_bufdudump();
|
||||
void i2c_have_DMA_Rx();
|
||||
int i2cdma_haderr();
|
||||
|
||||
void i2c_init_scan_mode();
|
||||
int i2c_scan_next_addr(uint8_t *addr);
|
||||
@ -21,6 +21,7 @@
|
||||
//#include "can.h"
|
||||
//#include "flash.h"
|
||||
#include "hardware.h"
|
||||
#include "i2c.h"
|
||||
#include "proto.h"
|
||||
#include "usb.h"
|
||||
|
||||
@ -75,6 +76,17 @@ int main(void){
|
||||
}
|
||||
}
|
||||
}*/
|
||||
if(I2C_scan_mode){
|
||||
uint8_t addr;
|
||||
int ok = i2c_scan_next_addr(&addr);
|
||||
if(addr == I2C_ADDREND) USND("Scan ends");
|
||||
else if(ok){
|
||||
USB_sendstr(uhex2str(addr));
|
||||
USB_sendstr(" ("); USB_sendstr(u2str(addr));
|
||||
USB_sendstr(") - found device\n");
|
||||
}
|
||||
}
|
||||
i2c_have_DMA_Rx(); // check if there's DMA Rx complete
|
||||
USB_proc();
|
||||
int l = USB_receivestr(inbuff, MAXSTRLEN);
|
||||
if(l < 0) USB_sendstr("ERROR: USB buffer overflow or string was too long\n");
|
||||
|
||||
Binary file not shown.
@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 8.0.2, 2023-03-22T12:09:09. -->
|
||||
<!-- Written by QtCreator 8.0.2, 2023-03-22T23:42:03. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{cf63021e-ef53-49b0-b03b-2f2570cdf3b6}</value>
|
||||
<value type="QByteArray">{7bd84e39-ca37-46d3-be9d-99ebea85bc0d}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
@ -38,32 +38,43 @@
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">false</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">1</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">2</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">false</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">true</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
|
||||
<value type="bool" key="AutoTest.Framework.Boost">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.CTest">false</value>
|
||||
<value type="bool" key="AutoTest.Framework.Catch">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.GTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
|
||||
<value type="int" key="AutoTest.RunAfterBuild">0</value>
|
||||
<value type="bool" key="AutoTest.UseGlobal">true</value>
|
||||
<valuemap type="QVariantMap" key="ClangTools">
|
||||
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
|
||||
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
|
||||
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
|
||||
<value type="int" key="ClangTools.ParallelJobs">4</value>
|
||||
<value type="int" key="ClangTools.ParallelJobs">2</value>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
|
||||
@ -77,12 +88,12 @@
|
||||
<value type="QString" key="DeviceType">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{91347f2c-5221-46a7-80b1-0a054ca02f79}</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{65a14f9e-e008-4c1b-89df-4eaa4774b6e3}</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/eddy/Docs/SAO/ELECTRONICS/STM32/F3-srcs/NitrogenFlooding</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/Big/Data/00__Electronics/STM32/F303-nolib/NitrogenFlooding</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
|
||||
|
||||
@ -14,6 +14,8 @@ hashgen/hashgen.c
|
||||
hashgen/hdr.c
|
||||
hashgen/hdr.h
|
||||
hashgen/test.c
|
||||
i2c.c
|
||||
i2c.h
|
||||
main.c
|
||||
pdnuart.c
|
||||
pdnuart.h
|
||||
|
||||
@ -16,7 +16,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "adc.h"
|
||||
#include "hardware.h"
|
||||
#include "i2c.h"
|
||||
#include "proto.h"
|
||||
#include "strfunc.h"
|
||||
#include "version.inc"
|
||||
@ -24,15 +26,36 @@
|
||||
#include <stm32f3.h>
|
||||
#include <string.h>
|
||||
|
||||
static uint8_t I2Caddress = 0;
|
||||
|
||||
// parno - number of parameter (or -1); cargs - string with arguments (after '=') (==NULL for getter), iarg - integer argument
|
||||
static int goodstub(int _U_ parno, const char _U_ *carg, int32_t _U_ iarg){
|
||||
static int goodstub(const char _U_ *cmd, int _U_ parno, const char _U_ *carg, int32_t _U_ iarg){
|
||||
return RET_GOOD;
|
||||
}
|
||||
|
||||
static int leds(int parno, const char *c, int32_t i){
|
||||
static void sendkey(const char *cmd, int parno, int32_t i){
|
||||
USB_sendstr(cmd);
|
||||
if(parno > -1) USB_sendstr(u2str((uint32_t)parno));
|
||||
USB_putbyte('='); USB_sendstr(i2str(i)); newline();
|
||||
}
|
||||
static void sendkeyf(const char *cmd, int parno, float f){
|
||||
USB_sendstr(cmd);
|
||||
if(parno > -1) USB_sendstr(u2str((uint32_t)parno));
|
||||
USB_putbyte('='); USB_sendstr(float2str(f, 2)); newline();
|
||||
}
|
||||
static void sendkeyu(const char *cmd, int parno, uint32_t u){
|
||||
USB_sendstr(cmd);
|
||||
if(parno > -1) USB_sendstr(u2str((uint32_t)parno));
|
||||
USB_putbyte('='); USB_sendstr(u2str(u)); newline();
|
||||
}
|
||||
|
||||
static int leds(const char *cmd, int parno, const char *c, int32_t i){
|
||||
if(parno < 0){ // enable/disable all
|
||||
if(c){ LEDsON = i ? 1 : 0;}
|
||||
USB_sendstr("LED="); USB_sendstr(u2str(LEDsON));
|
||||
if(c){
|
||||
LEDsON = (i ? 1 : 0);
|
||||
if(!LEDsON) for(int _ = 0; _ < 4; ++_) LED_off(_);
|
||||
}
|
||||
sendkey("LEDon", -1, LEDsON);
|
||||
}else{
|
||||
if(parno >= LEDS_AMOUNT) return RET_WRONGARG;
|
||||
if(c) switch(i){
|
||||
@ -40,32 +63,116 @@ static int leds(int parno, const char *c, int32_t i){
|
||||
case 1: LED_on(parno); break;
|
||||
default: LED_off(parno);
|
||||
}
|
||||
USB_sendstr("LED"); USB_putbyte('0' + parno);
|
||||
USB_putbyte('='); USB_sendstr(u2str(LED_get(parno))); newline();
|
||||
sendkey(cmd, parno, LED_get(parno));
|
||||
}
|
||||
newline();
|
||||
return RET_GOOD;
|
||||
}
|
||||
|
||||
static int buzzer(const char *cmd, int _U_ parno, const char _U_ *c, int32_t i){
|
||||
if(c){
|
||||
if(i > 0) BUZZER_ON();
|
||||
else BUZZER_OFF();
|
||||
}
|
||||
sendkey(cmd, -1, BUZZER_STATE());
|
||||
return RET_GOOD;
|
||||
}
|
||||
|
||||
static int i2scan(const char _U_ *cmd, int _U_ parno, const char _U_ *c, int32_t _U_ i){
|
||||
i2c_init_scan_mode();
|
||||
return RET_GOOD;
|
||||
}
|
||||
static int i2addr(const char *cmd, int _U_ parno, const char *c, int32_t i){
|
||||
if(c){
|
||||
if(i < 0 || i>= I2C_ADDREND) return RET_WRONGARG;
|
||||
I2Caddress = (uint8_t) i;
|
||||
}
|
||||
sendkey(cmd, -1, I2Caddress);
|
||||
return RET_GOOD;
|
||||
}
|
||||
|
||||
static int adcon(const char *cmd, int _U_ parno, const char *c, int32_t i){
|
||||
if(c) ADCON(i);
|
||||
sendkey(cmd, -1, ADCONSTATE());
|
||||
return RET_GOOD;
|
||||
}
|
||||
static int adcval(const char *cmd, int parno, const char _U_ *c, int32_t i){
|
||||
if(parno >= NUMBER_OF_ADC_CHANNELS) return RET_WRONGPARNO;
|
||||
if(parno < 0){ // all channels
|
||||
for(i = 0; i < NUMBER_OF_ADC_CHANNELS; ++i) sendkey(cmd, i, getADCval(i));
|
||||
}else
|
||||
sendkey(cmd, parno, getADCval(parno));
|
||||
return RET_GOOD;
|
||||
}
|
||||
static int adcvoltage(const char *cmd, int parno, const char _U_ *c, int32_t i){
|
||||
if(parno >= NUMBER_OF_ADC_CHANNELS) return RET_WRONGPARNO;
|
||||
if(parno < 0){ // all channels
|
||||
for(i = 0; i < NUMBER_OF_ADC_CHANNELS; ++i) sendkeyf(cmd, i, getADCvoltage(i));
|
||||
}else
|
||||
sendkeyf(cmd, parno, getADCvoltage(parno));
|
||||
return RET_GOOD;
|
||||
}
|
||||
static int mcut(const char *cmd, int _U_ parno, const char _U_ *c, int32_t _U_ i){
|
||||
sendkeyf(cmd, -1, getMCUtemp());
|
||||
return RET_GOOD;
|
||||
}
|
||||
|
||||
static int reset(const char _U_ *cmd, int _U_ parno, const char _U_ *c, int32_t _U_ i){
|
||||
USB_sendstr("RESET!!!\n");
|
||||
USB_sendall();
|
||||
NVIC_SystemReset();
|
||||
return RET_GOOD; // never reached
|
||||
}
|
||||
|
||||
static int tms(const char _U_ *cmd, int _U_ parno, const char _U_ *c, int32_t _U_ i){
|
||||
sendkeyu(cmd, -1, Tms);
|
||||
return RET_GOOD;
|
||||
}
|
||||
|
||||
static int pwm(const char *cmd, int parno, const char *c, int32_t i){
|
||||
if(parno < 0 || parno > 3) return RET_WRONGPARNO;
|
||||
if(c) setPWM(parno, (uint8_t)i);
|
||||
sendkeyu(cmd, -1, getPWM(parno));
|
||||
return RET_GOOD;
|
||||
}
|
||||
|
||||
typedef struct{
|
||||
int (*fn)(int, const char*, int32_t);
|
||||
int (*fn)(const char*, int, const char*, int32_t);
|
||||
const char *cmd;
|
||||
const char *help;
|
||||
} commands;
|
||||
|
||||
commands cmdlist[] = {
|
||||
{goodstub, "stub", "simple stub"},
|
||||
{NULL, "Different commands", NULL},
|
||||
{buzzer, "buzzer", "get/set (0 - off, 1 - on) buzzer"},
|
||||
{leds, "LED", "LEDx=y; where x=0..3 to work with single LED (then y=1-set, 0-reset, 2-toggle), absent to work with all (y=0 - disable, 1-enable)"},
|
||||
{pwm, "pwm", "set/get x channel (0..3) pwm value (0..255)"},
|
||||
{reset, "reset", "reset MCU"},
|
||||
{tms, "tms", "print Tms"},
|
||||
{NULL, "I2C commands", NULL},
|
||||
{i2addr, "iicaddr", "set/get I2C address"},
|
||||
{i2scan, "iicscan", "scan I2C bus"},
|
||||
{NULL, "ADC commands", NULL},
|
||||
{adcval, "ADC", "get ADCx value (without x - for all)"},
|
||||
{adcvoltage, "ADCv", "get ADCx voltage (without x - for all)"},
|
||||
{mcut, "mcut", "get MCU temperature"},
|
||||
{adcon, "sensv", "turn on (1) or off (0) Tsens voltage"},
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static void printhelp(){
|
||||
commands *c = cmdlist;
|
||||
USB_sendstr("https://github.com/eddyem/stm32samples/tree/master/F3:F303/NitrogenFlooding build#" BUILD_NUMBER " @ " BUILD_DATE "\n");
|
||||
while(c->fn){
|
||||
while(c->cmd){
|
||||
if(!c->fn){ // header
|
||||
USB_sendstr("\n ");
|
||||
USB_sendstr(c->cmd);
|
||||
USB_putbyte(':');
|
||||
}else{
|
||||
USB_sendstr(c->cmd);
|
||||
USB_sendstr(" - ");
|
||||
USB_sendstr(c->help);
|
||||
}
|
||||
newline();
|
||||
++c;
|
||||
}
|
||||
@ -73,6 +180,7 @@ static void printhelp(){
|
||||
|
||||
static int parsecmd(const char *str){
|
||||
char cmd[CMD_MAXLEN + 1];
|
||||
//USB_sendstr("cmd="); USB_sendstr(str); USB_sendstr("__\n");
|
||||
if(!str || !*str) return RET_CMDNOTFOUND;
|
||||
int i = 0;
|
||||
while(*str > '@' && i < CMD_MAXLEN){ cmd[i++] = *str++; }
|
||||
@ -88,10 +196,13 @@ static int parsecmd(const char *str){
|
||||
str = omit_spaces(++str);
|
||||
getint(str, &iarg);
|
||||
}
|
||||
}
|
||||
}else str = NULL;
|
||||
commands *c = cmdlist;
|
||||
while(c->fn){
|
||||
if(strcmp(c->cmd, cmd) == 0) return c->fn(parno, str, iarg);
|
||||
while(c->cmd){
|
||||
if(strcmp(c->cmd, cmd) == 0){
|
||||
if(!c->fn) return RET_CMDNOTFOUND;
|
||||
return c->fn(cmd, parno, str, iarg);
|
||||
}
|
||||
++c;
|
||||
}
|
||||
return RET_CMDNOTFOUND;
|
||||
@ -105,6 +216,7 @@ static int parsecmd(const char *str){
|
||||
const char *cmd_parser(const char *txt){
|
||||
int ret = parsecmd(txt);
|
||||
switch(ret){
|
||||
case RET_WRONGPARNO: return "Wrong parameter number\n"; break;
|
||||
case RET_CMDNOTFOUND: printhelp(); return NULL; break;
|
||||
case RET_WRONGARG: return "Wrong command parameters\n"; break;
|
||||
case RET_GOOD: return NULL; break;
|
||||
|
||||
@ -30,10 +30,11 @@
|
||||
#define CMD_MAXLEN (32)
|
||||
|
||||
enum{
|
||||
RET_CMDNOTFOUND = -2,
|
||||
RET_WRONGARG = -1,
|
||||
RET_GOOD = 0,
|
||||
RET_BAD = 1
|
||||
RET_WRONGPARNO = -3, // wrong parameter number
|
||||
RET_CMDNOTFOUND = -2, // command not found
|
||||
RET_WRONGARG = -1, // wrong argument
|
||||
RET_GOOD = 0, // all OK
|
||||
RET_BAD = 1 // something wrong
|
||||
};
|
||||
|
||||
#define printu(x) do{USB_sendstr(u2str(x));}while(0)
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
#define BUILD_NUMBER "2"
|
||||
#define BUILD_NUMBER "24"
|
||||
#define BUILD_DATE "2023-03-22"
|
||||
|
||||
@ -2,6 +2,7 @@ MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 40K
|
||||
ccmram (rwx) : ORIGIN = 0x10000000, LENGTH = 0
|
||||
}
|
||||
|
||||
PROVIDE(_BLOCKSIZE = 2048);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user