From ffd68b990c984512b1f04df8ec03b9edbbc710ca Mon Sep 17 00:00:00 2001 From: Kizarm Date: Sat, 19 Oct 2024 14:58:36 +0200 Subject: [PATCH] add usb adc test --- V203/usb/adc/Makefile | 52 ++++++++++++++++ V203/usb/adc/ch32v203 | 1 + V203/usb/adc/common | 1 + V203/usb/adc/hack.c | 21 +++++++ V203/usb/adc/main.cpp | 72 +++++++++++++++++++++ V203/usb/adc/usb_desc.cpp | 83 +++++++++++++++++++++++++ V203/usb/adc/usb_desc.h | 66 ++++++++++++++++++++ V203/usb/ch32v203/adcdma1k.cpp | 110 +++++++++++++++++++++++++++++++++ V203/usb/common/adcdma.h | 21 +++++++ V203/usb/common/oneway.h | 10 +++ 10 files changed, 437 insertions(+) create mode 100644 V203/usb/adc/Makefile create mode 120000 V203/usb/adc/ch32v203 create mode 120000 V203/usb/adc/common create mode 100644 V203/usb/adc/hack.c create mode 100644 V203/usb/adc/main.cpp create mode 100644 V203/usb/adc/usb_desc.cpp create mode 100644 V203/usb/adc/usb_desc.h create mode 100644 V203/usb/ch32v203/adcdma1k.cpp create mode 100644 V203/usb/common/adcdma.h create mode 100644 V203/usb/common/oneway.h diff --git a/V203/usb/adc/Makefile b/V203/usb/adc/Makefile new file mode 100644 index 0000000..48ffe5a --- /dev/null +++ b/V203/usb/adc/Makefile @@ -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 diff --git a/V203/usb/adc/ch32v203 b/V203/usb/adc/ch32v203 new file mode 120000 index 0000000..7650c85 --- /dev/null +++ b/V203/usb/adc/ch32v203 @@ -0,0 +1 @@ +../ch32v203/ \ No newline at end of file diff --git a/V203/usb/adc/common b/V203/usb/adc/common new file mode 120000 index 0000000..8332399 --- /dev/null +++ b/V203/usb/adc/common @@ -0,0 +1 @@ +../common/ \ No newline at end of file diff --git a/V203/usb/adc/hack.c b/V203/usb/adc/hack.c new file mode 100644 index 0000000..391b7bf --- /dev/null +++ b/V203/usb/adc/hack.c @@ -0,0 +1,21 @@ +#include +#include +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 4u * HALF_LEN + 4u, "buffer len is too small"); + GpioClass led; // indikace DMA + volatile bool toggle; + FIFO 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>= 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; +} diff --git a/V203/usb/adc/usb_desc.cpp b/V203/usb/adc/usb_desc.cpp new file mode 100644 index 0000000..d03cd77 --- /dev/null +++ b/V203/usb/adc/usb_desc.cpp @@ -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 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 (&str_1), + reinterpret_cast (&str_2), + reinterpret_cast (&str_3), +}; + + diff --git a/V203/usb/adc/usb_desc.h b/V203/usb/adc/usb_desc.h new file mode 100644 index 0000000..9b578b9 --- /dev/null +++ b/V203/usb/adc/usb_desc.h @@ -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 + +/******************************************************************************/ +/* 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_ */ diff --git a/V203/usb/ch32v203/adcdma1k.cpp b/V203/usb/ch32v203/adcdma1k.cpp new file mode 100644 index 0000000..b8d24ee --- /dev/null +++ b/V203/usb/ch32v203/adcdma1k.cpp @@ -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 (& ADC1.RDATAR_DR_ACT_DCG); + // Configure the memory address + DMA1.MADDR1.R = reinterpret_cast (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); +} diff --git a/V203/usb/common/adcdma.h b/V203/usb/common/adcdma.h new file mode 100644 index 0000000..a8f15ac --- /dev/null +++ b/V203/usb/common/adcdma.h @@ -0,0 +1,21 @@ +#ifndef ADCDMA_H +#define ADCDMA_H +#include + +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 diff --git a/V203/usb/common/oneway.h b/V203/usb/common/oneway.h new file mode 100644 index 0000000..f06cd6b --- /dev/null +++ b/V203/usb/common/oneway.h @@ -0,0 +1,10 @@ +#ifndef ONEWAY_H +#define ONEWAY_H +#include +/* C++ interface (jako callback v C) */ +class OneWay { + public: + virtual unsigned Send (uint16_t * const ptr, const unsigned len) = 0; +}; + +#endif // ONEWAY_H