add usb adc test
This commit is contained in:
parent
4ec412bf43
commit
ffd68b990c
10 changed files with 437 additions and 0 deletions
52
V203/usb/adc/Makefile
Normal file
52
V203/usb/adc/Makefile
Normal file
|
@ -0,0 +1,52 @@
|
|||
TARGET?= ch32v203
|
||||
TOOL ?= gcc
|
||||
#TOOL ?= clang
|
||||
|
||||
PRJ = example
|
||||
|
||||
VPATH = . ./$(TARGET) ./common
|
||||
BLD = ./build/
|
||||
DFLAGS = -d
|
||||
LFLAGS = -g
|
||||
LDLIBS =
|
||||
BFLAGS = --strip-unneeded
|
||||
|
||||
CFLAGS = -MMD -Wall -Wno-parentheses -ggdb -fno-exceptions -ffunction-sections -fdata-sections
|
||||
CFLAGS+= -I. -I./$(TARGET) -I./common
|
||||
DEL = rm -f
|
||||
|
||||
# zdrojaky
|
||||
OBJS = main.o hack.o
|
||||
OBJS += usb_desc.o cdc_class.o adcdma1k.o
|
||||
|
||||
include $(TARGET)/$(TOOL).mk
|
||||
BOBJS = $(addprefix $(BLD),$(OBJS))
|
||||
|
||||
all: $(BLD) $(PRJ).elf
|
||||
# ... atd.
|
||||
-include $(BLD)*.d
|
||||
# linker
|
||||
$(PRJ).elf: $(BOBJS)
|
||||
-@echo [LD $(TOOL),$(TARGET)] $@
|
||||
@$(LD) $(LFLAGS) -o $(PRJ).elf $(BOBJS) $(LDLIBS)
|
||||
-@echo "size:"
|
||||
@$(SIZE) $(PRJ).elf
|
||||
-@echo "listing:"
|
||||
$(DUMP) $(DFLAGS) $(PRJ).elf > $(PRJ).lst
|
||||
-@echo "OK."
|
||||
$(COPY) $(BFLAGS) -O binary $(PRJ).elf $(PRJ).bin
|
||||
# preloz co je potreba
|
||||
$(BLD)%.o: %.c
|
||||
-@echo [CC $(TOOL),$(TARGET)] $@
|
||||
@$(CC) -std=gnu99 -c $(CFLAGS) $< -o $@
|
||||
$(BLD)%.o: %.cpp
|
||||
-@echo [CX $(TOOL),$(TARGET)] $@
|
||||
@$(CXX) -std=c++17 -fno-rtti -c $(CFLAGS) $< -o $@
|
||||
$(BLD):
|
||||
mkdir $(BLD)
|
||||
flash: $(PRJ).elf
|
||||
minichlink -w $(PRJ).bin flash -b
|
||||
# vycisti
|
||||
clean:
|
||||
$(DEL) $(BLD)* *.lst *.bin *.elf *.map *~
|
||||
.PHONY: all clean flash run
|
1
V203/usb/adc/ch32v203
Symbolic link
1
V203/usb/adc/ch32v203
Symbolic link
|
@ -0,0 +1 @@
|
|||
../ch32v203/
|
1
V203/usb/adc/common
Symbolic link
1
V203/usb/adc/common
Symbolic link
|
@ -0,0 +1 @@
|
|||
../common/
|
21
V203/usb/adc/hack.c
Normal file
21
V203/usb/adc/hack.c
Normal file
|
@ -0,0 +1,21 @@
|
|||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
size_t strlen (const char *s) {
|
||||
size_t l = 0;
|
||||
while (*s++) l++;
|
||||
return l;
|
||||
}
|
||||
void *memcpy (void *dest, const void *src, size_t n) {
|
||||
const char *s = (const char *) src;
|
||||
char *d = (char *) dest;
|
||||
int i;
|
||||
for (i=0; i<n; i++) d[i] = s[i];
|
||||
return dest;
|
||||
}
|
||||
void *memset (void *s, int c, size_t n) {
|
||||
char *p = (char *) s;
|
||||
int i;
|
||||
for (i=0; i<n; i++) p[i] = c;
|
||||
return s;
|
||||
}
|
72
V203/usb/adc/main.cpp
Normal file
72
V203/usb/adc/main.cpp
Normal file
|
@ -0,0 +1,72 @@
|
|||
#include "cdc_class.h"
|
||||
#include "adcdma.h"
|
||||
#include "oneway.h"
|
||||
/** Test ADC.
|
||||
* Jednoduchý test ADC převodníku se vzorkovací frekvencí 1kHz.
|
||||
* Data se čtou na PA2 a vypisují pomocí USB_CDC v hex formátu.
|
||||
* Převodník je lehce přetaktovaný (18 MHz místo max.14), ale
|
||||
* zřejmě to moc nevadí. Žádný závěr o kvalitě se z toho dělat
|
||||
* nedá, šum může být způsoben vývojovou deskou, linearitu nemám
|
||||
* jak měřit (resp. mě to nebaví).
|
||||
* */
|
||||
class Transport : public BaseLayer, public OneWay {
|
||||
static constexpr const char * hexStr = "0123456789abcdef";
|
||||
static constexpr const char * eol = "\r\n ";
|
||||
static constexpr unsigned max = 128;
|
||||
static_assert (max > 4u * HALF_LEN + 4u, "buffer len is too small");
|
||||
GpioClass led; // indikace DMA
|
||||
volatile bool toggle;
|
||||
FIFO<char, max> ring;
|
||||
char buffer [max];
|
||||
public:
|
||||
explicit Transport () noexcept : BaseLayer(), OneWay(),
|
||||
led(GPIOA, 1), toggle(false), ring() {}
|
||||
// Toto je voláno v přerušení DMA1_Channel1_IRQHandler od ADC.
|
||||
unsigned int Send(uint16_t * const ptr, const unsigned int len) override {
|
||||
led << toggle; // indikace
|
||||
toggle = ! toggle;
|
||||
for (unsigned n=0u; n<len; n++) { // pro test vypisuji v hexu
|
||||
put_u16 (ptr [n]);
|
||||
}
|
||||
for (unsigned n=0u; n<2u; n++) ring.Write(eol [n]); // new line
|
||||
return len;
|
||||
}
|
||||
void pass () {
|
||||
unsigned n = 0u;
|
||||
for (n=0u; n<max; n++) {
|
||||
if (!ring.Read (buffer [n])) break;
|
||||
}
|
||||
if (n) block (n);
|
||||
}
|
||||
void put_u16 (const uint16_t p) {
|
||||
uint16_t e = p; // max 0xFFF (12 bit)
|
||||
const char c1 = hexStr [e & 0x0f]; e >>= 4;
|
||||
const char c2 = hexStr [e & 0x0f]; e >>= 4;
|
||||
const char c3 = hexStr [e & 0x0f];
|
||||
ring.Write (c3);
|
||||
ring.Write (c2);
|
||||
ring.Write (c1);
|
||||
ring.Write (eol [2]); // space
|
||||
}
|
||||
protected:
|
||||
void block (const unsigned len) {
|
||||
unsigned ofs = 0u, rem = len;
|
||||
while (rem) {
|
||||
const unsigned res = Down (buffer + ofs, rem);
|
||||
rem -= res;
|
||||
ofs += res;
|
||||
}
|
||||
}
|
||||
};
|
||||
static cdc_class cdc;
|
||||
static AdcDma adc;
|
||||
static Transport tra;
|
||||
int main () {
|
||||
cdc.init();
|
||||
tra += cdc;
|
||||
adc.attach(tra);
|
||||
for (;;) {
|
||||
tra.pass();
|
||||
}
|
||||
return 0;
|
||||
}
|
83
V203/usb/adc/usb_desc.cpp
Normal file
83
V203/usb/adc/usb_desc.cpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : usb_desc.c
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2022/08/20
|
||||
* Description : usb device descriptor,configuration descriptor,
|
||||
* string descriptors and other descriptors.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
|
||||
#include "usb_desc.h"
|
||||
|
||||
/* Device Descriptor */
|
||||
const uint8_t MyDevDescr[] =
|
||||
{
|
||||
0x12, // bLength
|
||||
0x01, // bDescriptorType (Device)
|
||||
0x10, 0x01, // bcdUSB 1.10
|
||||
0x02, // bDeviceClass
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
DEF_USBD_UEP0_SIZE, // bMaxPacketSize0 64
|
||||
(uint8_t)DEF_USB_VID, (uint8_t)(DEF_USB_VID >> 8), // idVendor 0x1A86
|
||||
(uint8_t)DEF_USB_PID, (uint8_t)(DEF_USB_PID >> 8), // idProduct 0x5537
|
||||
DEF_IC_PRG_VER, 0x00, // bcdDevice 0.01
|
||||
0x01, // iManufacturer (String Index)
|
||||
0x02, // iProduct (String Index)
|
||||
0x03, // iSerialNumber (String Index)
|
||||
0x01, // bNumConfigurations 1
|
||||
};
|
||||
|
||||
/* Configuration Descriptor */
|
||||
const uint8_t MyCfgDescr[] =
|
||||
{
|
||||
/* Configure descriptor */
|
||||
0x09, 0x02, 0x43, 0x00, 0x02, 0x01, 0x00, 0x80, 0x32,
|
||||
|
||||
/* Interface 0 (CDC) descriptor */
|
||||
0x09, 0x04, 0x00, 0x00, 0x01, 0x02, 0x02, 0x01, 0x00,
|
||||
|
||||
/* Functional Descriptors */
|
||||
0x05, 0x24, 0x00, 0x10, 0x01,
|
||||
|
||||
/* Length/management descriptor (data class interface 1) */
|
||||
0x05, 0x24, 0x01, 0x00, 0x01,
|
||||
0x04, 0x24, 0x02, 0x02,
|
||||
0x05, 0x24, 0x06, 0x00, 0x01,
|
||||
|
||||
/* Interrupt upload endpoint descriptor */
|
||||
0x07, 0x05, 0x81, 0x03, (uint8_t)DEF_USBD_ENDP1_SIZE, (uint8_t)( DEF_USBD_ENDP1_SIZE >> 8 ), 0x01,
|
||||
|
||||
/* Interface 1 (data interface) descriptor */
|
||||
0x09, 0x04, 0x01, 0x00, 0x02, 0x0A, 0x00, 0x00, 0x00,
|
||||
|
||||
/* Endpoint descriptor */
|
||||
0x07, 0x05, 0x02, 0x02, (uint8_t)DEF_USBD_ENDP2_SIZE, (uint8_t)( DEF_USBD_ENDP2_SIZE >> 8 ), 0x00,
|
||||
|
||||
/* Endpoint descriptor */
|
||||
0x07, 0x05, 0x83, 0x02, (uint8_t)DEF_USBD_ENDP3_SIZE, (uint8_t)( DEF_USBD_ENDP3_SIZE >> 8 ), 0x00,
|
||||
};
|
||||
#define DEF_STRDESC(p,n) w_text<(sizeof(p)>>1)>n={sizeof(n)-2u,3u,{p}}
|
||||
template<const unsigned N> struct w_text {
|
||||
uint8_t len, typ;
|
||||
const char16_t str [N];
|
||||
};
|
||||
static const DEF_STRDESC((u"Kizarm Labs."), str_1);
|
||||
static const DEF_STRDESC((u"USB <=> USART"),str_2);
|
||||
static const DEF_STRDESC((u"0003"), str_3);
|
||||
/* Language Descriptor */
|
||||
static const uint8_t LangDescr[] = {
|
||||
0x04, 0x03, 0x09, 0x04
|
||||
};
|
||||
const uint8_t * StringDescArray [DEF_MAX_STRINGS] = {
|
||||
LangDescr,
|
||||
reinterpret_cast<const uint8_t*> (&str_1),
|
||||
reinterpret_cast<const uint8_t*> (&str_2),
|
||||
reinterpret_cast<const uint8_t*> (&str_3),
|
||||
};
|
||||
|
||||
|
66
V203/usb/adc/usb_desc.h
Normal file
66
V203/usb/adc/usb_desc.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : usb_desc.h
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2022/08/20
|
||||
* Description : header file of usb_desc.c
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef USER_USB_DESC_H_
|
||||
#define USER_USB_DESC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/******************************************************************************/
|
||||
/* global define */
|
||||
/* file version */
|
||||
#define DEF_FILE_VERSION 0x01
|
||||
/* usb device info define */
|
||||
#define DEF_USB_VID 0x1A86
|
||||
#define DEF_USB_PID 0xFE0C
|
||||
/* USB device descriptor, device serial number(bcdDevice) */
|
||||
#define DEF_IC_PRG_VER DEF_FILE_VERSION
|
||||
|
||||
/******************************************************************************/
|
||||
/* usb device endpoint size define */
|
||||
#define DEF_USBD_UEP0_SIZE 64 /* usb hs/fs device end-point 0 size */
|
||||
/* FS */
|
||||
#define DEF_USBD_FS_PACK_SIZE 64 /* usb fs device max bluk/int pack size */
|
||||
#define DEF_USBD_FS_ISO_PACK_SIZE 1023 /* usb fs device max iso pack size */
|
||||
/* LS */
|
||||
#define DEF_USBD_LS_UEP0_SIZE 8 /* usb ls device end-point 0 size */
|
||||
#define DEF_USBD_LS_PACK_SIZE 64 /* usb ls device max int pack size */
|
||||
|
||||
/* Pack size */
|
||||
#define DEF_USBD_ENDP1_SIZE DEF_USBD_FS_PACK_SIZE
|
||||
#define DEF_USBD_ENDP2_SIZE DEF_USBD_FS_PACK_SIZE
|
||||
#define DEF_USBD_ENDP3_SIZE DEF_USBD_FS_PACK_SIZE
|
||||
#define DEF_USBD_ENDP4_SIZE DEF_USBD_FS_PACK_SIZE
|
||||
#define DEF_USBD_ENDP5_SIZE DEF_USBD_FS_PACK_SIZE
|
||||
#define DEF_USBD_ENDP6_SIZE DEF_USBD_FS_PACK_SIZE
|
||||
#define DEF_USBD_ENDP7_SIZE DEF_USBD_FS_PACK_SIZE
|
||||
|
||||
/******************************************************************************/
|
||||
/* usb device Descriptor length, length of usb descriptors, if one descriptor not
|
||||
* exists , set the length to 0 */
|
||||
#define DEF_USBD_DEVICE_DESC_LEN ((uint8_t)MyDevDescr[0])
|
||||
#define DEF_USBD_CONFIG_DESC_LEN ((uint16_t)MyCfgDescr[2] + (uint16_t)(MyCfgDescr[3] << 8))
|
||||
#define DEF_USBD_REPORT_DESC_LEN 0
|
||||
|
||||
#define DEF_MAX_STRINGS (4)
|
||||
/******************************************************************************/
|
||||
/* external variables */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
extern const uint8_t MyDevDescr[ ];
|
||||
extern const uint8_t MyCfgDescr[ ];
|
||||
extern const uint8_t * StringDescArray [DEF_MAX_STRINGS];
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif // __cplusplus
|
||||
#endif /* USER_USB_DESC_H_ */
|
110
V203/usb/ch32v203/adcdma1k.cpp
Normal file
110
V203/usb/ch32v203/adcdma1k.cpp
Normal file
|
@ -0,0 +1,110 @@
|
|||
#include "system.h"
|
||||
#include "oneway.h"
|
||||
#include "adcdma.h"
|
||||
|
||||
static AdcDma * pInstance = nullptr;
|
||||
|
||||
extern "C" {
|
||||
[[gnu::interrupt]] extern void DMA1_Channel1_IRQHandler();
|
||||
}
|
||||
void DMA1_Channel1_IRQHandler( void ) {
|
||||
DMA1_Type::INTFR_DEF state (DMA1.INTFR);
|
||||
DMA1.INTFCR.R = state.R; // clear all
|
||||
if (!pInstance) return;
|
||||
if (state.B.HTIF1 != RESET) pInstance->send (false);
|
||||
else if (state.B.TCIF1 != RESET) pInstance->send (true);
|
||||
}
|
||||
|
||||
static inline void EnableClock (void) noexcept {
|
||||
// Enable DMA
|
||||
RCC.AHBPCENR.modify([](RCC_Type::AHBPCENR_DEF & r) -> auto {
|
||||
r.B.SRAMEN = SET;
|
||||
r.B.DMA1EN = SET;
|
||||
return r.R;
|
||||
});
|
||||
// Enable ADC + GPIOC
|
||||
RCC.APB2PCENR.modify([](RCC_Type::APB2PCENR_DEF & r) -> auto {
|
||||
r.B.ADC1EN = SET;
|
||||
r.B.IOPAEN = SET;
|
||||
return r.R;
|
||||
});
|
||||
RCC.APB1PCENR.B.TIM3EN = SET; // Enable TIM3
|
||||
RCC.CFGR0.B.ADCPRE = 3u; // PCLK2 divided by 8 as ADC clock (18 MHz, ! pretaktovano 14 MHz max).
|
||||
// PIN PA2 / A2
|
||||
GPIOA.CFGLR.modify([](GPIOA_Type::CFGLR_DEF & r) -> auto {
|
||||
r.B.MODE2 = 0u;
|
||||
r.B.CNF2 = 0u;
|
||||
return r.R;
|
||||
});
|
||||
}
|
||||
static inline void Timer3Init (uint32_t us) noexcept {
|
||||
TIM3.PSC.R = 143u; // 1 MHz Fs
|
||||
TIM3.ATRLR.R = us - 1u;
|
||||
// TRGO update for ADC
|
||||
TIM3.CTLR2.B.MMS = 2u;
|
||||
}
|
||||
static inline void AdcCalibrate (void) noexcept {
|
||||
// RESET
|
||||
RCC.APB2PRSTR.B.ADC1RST = SET;
|
||||
RCC.APB2PRSTR.B.ADC1RST = RESET;
|
||||
// set channels
|
||||
ADC1.RSQR3__CHANNEL.B.SQ1__CHSEL = 2u; // CH2
|
||||
ADC1.RSQR1.B.L = 0u; // 1 regular conversion
|
||||
ADC1.SAMPTR2_CHARGE2.B.SMP2_TKCG2 = 7u;
|
||||
ADC1.CTLR1.B.SCAN = SET;
|
||||
|
||||
ADC1.CTLR2.B.ADON = SET;
|
||||
ADC1.CTLR2.B.RSTCAL = SET; // Launch the calibration by setting RSTCAL
|
||||
while (ADC1.CTLR2.B.RSTCAL != RESET); // Wait until RSTCAL=0
|
||||
ADC1.CTLR2.B.CAL = SET; // Launch the calibration by setting CAL
|
||||
while (ADC1.CTLR2.B.CAL != RESET); // Wait until CAL=0
|
||||
}
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
static inline void Dma1Ch1Init (void * ptr) noexcept {
|
||||
// Configure the peripheral data register address
|
||||
DMA1.PADDR1.R = reinterpret_cast<size_t> (& ADC1.RDATAR_DR_ACT_DCG);
|
||||
// Configure the memory address
|
||||
DMA1.MADDR1.R = reinterpret_cast<size_t> (ptr);
|
||||
// Configure the number of DMA tranfer to be performs on DMA channel 1
|
||||
DMA1.CNTR1 .R = FULL_LEN;
|
||||
// Configure increment, size, interrupts and circular mode
|
||||
DMA1.CFGR1.modify([] (DMA1_Type::CFGR1_DEF & r) -> auto {
|
||||
r.B.PL = 3u; // highest priority
|
||||
r.B.MEM2MEM = RESET; // periferal -> memory
|
||||
r.B.MINC = SET; // memory increment
|
||||
r.B.MSIZE = 1u; // 16-bit
|
||||
r.B.PSIZE = 1u; // 16-bit
|
||||
r.B.HTIE = SET; // INT Enable HALF
|
||||
r.B.TCIE = SET; // INT Enable FULL
|
||||
r.B.CIRC = SET; // Circular MODE
|
||||
// Enable DMA Channel 1
|
||||
r.B.EN = SET;
|
||||
return r.R;
|
||||
});
|
||||
}
|
||||
static inline void AdcPostInit (void) noexcept {
|
||||
ADC1.CTLR2.modify([](ADC1_Type::CTLR2_DEF & r) -> auto {
|
||||
r.B.DMA = SET;
|
||||
r.B.EXTTRIG = SET;
|
||||
r.B.EXTSEL = 4u; // TRGO event of timer 3
|
||||
r.B.SWSTART = SET;
|
||||
return r.R;
|
||||
});
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
AdcDma::AdcDma() noexcept : pL (buffer), pH (buffer + HALF_LEN), dst (nullptr) {
|
||||
pInstance = this;
|
||||
EnableClock ();
|
||||
Timer3Init (1000u);
|
||||
NVIC.EnableIRQ (DMA1_Channel1_IRQn);
|
||||
AdcCalibrate();
|
||||
Dma1Ch1Init (buffer);
|
||||
AdcPostInit ();
|
||||
// start timer
|
||||
TIM3.CTLR1.B.CEN = SET;
|
||||
}
|
||||
inline void AdcDma::send(const bool b) {
|
||||
if (!dst) return;
|
||||
if (b) dst->Send (pH, HALF_LEN);
|
||||
else dst->Send (pL, HALF_LEN);
|
||||
}
|
21
V203/usb/common/adcdma.h
Normal file
21
V203/usb/common/adcdma.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#ifndef ADCDMA_H
|
||||
#define ADCDMA_H
|
||||
#include <stdint.h>
|
||||
|
||||
class OneWay;
|
||||
static constexpr unsigned HALF_LEN = 20u;
|
||||
static constexpr unsigned FULL_LEN = HALF_LEN * 2u;
|
||||
|
||||
class AdcDma {
|
||||
uint16_t * pL;
|
||||
uint16_t * pH;
|
||||
uint16_t buffer [FULL_LEN];
|
||||
OneWay * dst;
|
||||
public:
|
||||
explicit AdcDma () noexcept;
|
||||
void attach (OneWay & d) { dst = & d; }
|
||||
void send (const bool b);
|
||||
|
||||
};
|
||||
|
||||
#endif // ADCDMA_H
|
10
V203/usb/common/oneway.h
Normal file
10
V203/usb/common/oneway.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef ONEWAY_H
|
||||
#define ONEWAY_H
|
||||
#include <stdint.h>
|
||||
/* C++ interface (jako callback v C) */
|
||||
class OneWay {
|
||||
public:
|
||||
virtual unsigned Send (uint16_t * const ptr, const unsigned len) = 0;
|
||||
};
|
||||
|
||||
#endif // ONEWAY_H
|
Loading…
Reference in a new issue