From 2a88a7569df4f0536284c735e39f09fc00367aef Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Fri, 3 Jan 2025 20:06:40 +0300 Subject: [PATCH] seems like it works, the rest is only CDC and composite; and then test on 072 and 303 --- F1:F103/USB_NEW_concept/someusb.bin | Bin 8416 -> 0 bytes .../USB_NEW_concept_HID}/Makefile | 0 .../USB_NEW_concept_HID/hardware.c | 50 +++ .../USB_NEW_concept_HID}/hardware.h | 0 .../USB_NEW_concept_HID/keycodes.c | 76 ++++ .../USB_NEW_concept_HID/keycodes.h | 140 ++++++ .../USB_NEW_concept_HID/main.c | 103 +++++ .../USB_NEW_concept_HID}/openocd.cfg | 0 .../USB_NEW_concept_HID}/ringbuffer.c | 0 .../USB_NEW_concept_HID}/ringbuffer.h | 0 .../USB_NEW_concept_HID/someusb.bin | Bin 0 -> 3056 bytes .../USB_NEW_concept_HID}/someusb.cflags | 0 .../USB_NEW_concept_HID}/someusb.config | 0 .../USB_NEW_concept_HID}/someusb.creator | 0 .../USB_NEW_concept_HID}/someusb.creator.user | 3 +- .../USB_NEW_concept_HID}/someusb.cxxflags | 0 .../USB_NEW_concept_HID/someusb.files | 14 + .../USB_NEW_concept_HID}/someusb.includes | 0 .../USB_NEW_concept_HID}/usart.c | 0 .../USB_NEW_concept_HID}/usart.h | 2 +- .../USB_NEW_concept_HID/usb_descr.c | 259 +++++++++++ .../USB_NEW_concept_HID/usb_descr.h | 63 +++ .../USB_NEW_concept_HID/usb_dev.c | 67 +++ .../USB_NEW_concept_HID/usb_dev.h | 22 + .../USB_NEW_concept_HID}/usb_lib.c | 139 +++--- .../USB_NEW_concept_HID}/usb_lib.h | 26 +- .../USB_NEW_concept_PL2303/Makefile | 9 + .../USB_NEW_concept_PL2303}/hardware.c | 0 .../USB_NEW_concept_PL2303/hardware.h | 37 ++ .../USB_NEW_concept_PL2303}/main.c | 0 .../USB_NEW_concept_PL2303/openocd.cfg | 4 + .../USB_NEW_concept_PL2303/ringbuffer.c | 166 +++++++ .../USB_NEW_concept_PL2303/ringbuffer.h | 41 ++ .../USB_NEW_concept_PL2303/someusb.bin | Bin 0 -> 3912 bytes .../USB_NEW_concept_PL2303/someusb.cflags | 1 + .../USB_NEW_concept_PL2303/someusb.config | 4 + .../USB_NEW_concept_PL2303/someusb.creator | 1 + .../someusb.creator.user | 183 ++++++++ .../USB_NEW_concept_PL2303/someusb.cxxflags | 1 + .../USB_NEW_concept_PL2303}/someusb.files | 0 .../USB_NEW_concept_PL2303/someusb.includes | 6 + .../USB_NEW_concept_PL2303/usart.c | 122 ++++++ .../USB_NEW_concept_PL2303/usart.h | 45 ++ .../USB_NEW_concept_PL2303}/usb_descr.c | 8 +- .../USB_NEW_concept_PL2303}/usb_descr.h | 0 .../USB_NEW_concept_PL2303}/usb_dev.c | 37 +- .../USB_NEW_concept_PL2303}/usb_dev.h | 0 .../USB_NEW_concept_PL2303/usb_lib.c | 413 ++++++++++++++++++ .../USB_NEW_concept_PL2303/usb_lib.h | 320 ++++++++++++++ 49 files changed, 2229 insertions(+), 133 deletions(-) delete mode 100755 F1:F103/USB_NEW_concept/someusb.bin rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_HID}/Makefile (100%) create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_HID/hardware.c rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_HID}/hardware.h (100%) create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_HID/keycodes.c create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_HID/keycodes.h create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_HID/main.c rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_HID}/openocd.cfg (100%) rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_HID}/ringbuffer.c (100%) rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_HID}/ringbuffer.h (100%) create mode 100755 F1:F103/USB_New_concept/USB_NEW_concept_HID/someusb.bin rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_HID}/someusb.cflags (100%) rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_HID}/someusb.config (100%) rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_HID}/someusb.creator (100%) rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_HID}/someusb.creator.user (98%) rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_HID}/someusb.cxxflags (100%) create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_HID/someusb.files rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_HID}/someusb.includes (100%) rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_HID}/usart.c (100%) rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_HID}/usart.h (98%) create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_descr.c create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_descr.h create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_dev.c create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_dev.h rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_HID}/usb_lib.c (78%) rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_HID}/usb_lib.h (95%) create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_PL2303/Makefile rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_PL2303}/hardware.c (100%) create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_PL2303/hardware.h rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_PL2303}/main.c (100%) create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_PL2303/openocd.cfg create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_PL2303/ringbuffer.c create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_PL2303/ringbuffer.h create mode 100755 F1:F103/USB_New_concept/USB_NEW_concept_PL2303/someusb.bin create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_PL2303/someusb.cflags create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_PL2303/someusb.config create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_PL2303/someusb.creator create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_PL2303/someusb.creator.user create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_PL2303/someusb.cxxflags rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_PL2303}/someusb.files (100%) create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_PL2303/someusb.includes create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usart.c create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usart.h rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_PL2303}/usb_descr.c (96%) rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_PL2303}/usb_descr.h (100%) rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_PL2303}/usb_dev.c (93%) rename F1:F103/{USB_NEW_concept => USB_New_concept/USB_NEW_concept_PL2303}/usb_dev.h (100%) create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_lib.c create mode 100644 F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_lib.h diff --git a/F1:F103/USB_NEW_concept/someusb.bin b/F1:F103/USB_NEW_concept/someusb.bin deleted file mode 100755 index b14a40c711dd35cfc50b92c57b209126fe08ee28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8416 zcmd5>eNbChcE3+gfFy*$$R8kKTOcQ~BPRjN-`Y(S0g92FI0bv11#kU?!Fi%yV}qRt z-ew}l*{q!HbiAgWG?2EL?RLhK+142xZxfV^GTF50OgbH5cIp`H_H{Db>~@+IJ2-$I zM*W?uCy?!=)Be$!wdeBgJ@?#m&(}TY+$*+@IfYfs6hdpfqp>^w5e_v1(|5b!?lpJP z_@?or#b3YnamUxgzlqN88a(zEJ6{|cidcg6lgq_{usO7QlJ&Gorcj$)6s(_mUu=;I z3D(>yvE+M!*t>@j#nI6xuWbD1zTc_S+=f%KwNjvt+Y*8(9 z7ms`8@nLI|)+bJuibij_aA~->!TyX{C3sO2VP#>bW|)g5ty}e7lI(M)vVUW0?BWZc z8I=@S@LsqcdtMk5T&1cdNaGf%w0iesrZzMEL8c(YY6c}^sHny+F;_*vM3mlR$ubo* zAg3|pkOhwzv@J@K+|QWv%*DS0edhXT##-kMFs$wd<`GCA^VlSBz#+F*c>{JS0;o8} zJj`7%N>Kle(w+hT7gr80z{9C9`Vw?mCfcOmNB?_4*QAJk8~Uw)8_?eu+81n-Tco|A zz5Lq(T{qKi2V0~k(cc|(P5r>uB0Y}&F2H|-eh}-Mus+sH91)K!*$9|8$$FW)i1Q{vxWm^96N zG-DJl&lu~NTO2Rj$tK4#AAXh{zn?0>_~VRsRYibJev~Q3=)=s#&p?m-(}@P(^i>Ls z)iNL1nfz5o9C!`w99q^_$*;y`MIMp|{RI=b{+PW;RpeF-{#HTG~+&P-p*%z!Ga6xQU5KpFSL*jqp1Yl;KfQAHjEU5e637BgiJHiJ5s+? zq>jifRS8Lxzgsmcl}GK6vUPR8#N0PVVUy&th5i0;Va*Kaek(K6u5~fDFv?utSJPe4 zfnR|1TDu1QYtX`&J<&eWrF9Wp>!N-RCjlG>q&f?UN4hElZ-d^&Om^Nqp6*Iu&3)Gr zT_bX;LX#_Hf{fYifz0$zGn#Djq~-p0FLu|$-Y&bWMeGguO4L`n+Q3KQM6Q3yPBSd2 zbvd9j@WMTF?OaU+^F+Sqd8O zm*0^|GhLY|{D-_qiBtqCZd=LITi6Rq!Z>qP!#`T9vYJysVTgN) zaa@DH^uv>saDT)L>58uHko)*fn=@jd&0nDQN3!DwF#g6J^EfWiIiBtJ%Ke^=dzEA9OYwpMgoUxKasyWYXM z%1kHcv-1|nRsoxh$fFhg_-1YV=Da3bVX1UDfwKZ@!8))-1HKaVHQiFV{v|uju%rUo z8=&no@5TO?minWwk$N$@8G=x=d` zRo{c}noMP=yvBZVWypWSWEebIpu$VM3V8;yb9u-S9~u@XeIg=hiexPz{l%=Iq0>Xd zRJS?Bq2Ym(rckVA@P!4*)=n{=2ay9w55{e%)zGL8GJzk;%FJDuDxge`+Rhk4O;U&F- zE79xXc=o_6vrB4+m_IFkIRR-(MQ^WHF}qElD2P@4;T=lt#?j$r!O=a)yE^2U{z5`V+pIf-%b5Soh_wg<5<$mtf z{c-JOM5h>GS(Ac`xriSn4#`I~g}LieRO1W{yWk-%ST1ogaoROii+)TzHCby|9t0bL@#vbEpYoj5q{b{1-@j$tiUplWd!`UKTt=tJXe#x|=K6N6g31s<-SeCX;Z_RH?ID&&Yx3^VtJ zQHS1JpQ_|Nd!V9;bda8-I+3~8OxSd|A`kctsU>u7jxM1Sd9*Y%l*cjo7I8H=Y!2a8 z0(tL@Rg#H0e}>k9=7XP-{bCo-!dJbke27&x?E70S+Myg~ZtLh$c$Cj=93`EKu>U{L zS$P~SQ)yltH}jDhqrqYCDnvTqd^jftmBTh^Cy!wpu*W$|E{>T)6P#NWUU`)3%7|DS z6UU^?^t+1@lJi6{v|N`ihmYvYbw>V5IwRa@v2)nyRC%`XBO;+SREs*)f~&b zfW?w;a~wo|%$D-m^c>w!uj*?J=gTl-;4`1k!F~hGWvLOX1#thDbC6}g=ORs$G(&SH zKJU{tKLASnX1Ru$evPwoq7-icXp7Z?4Sb=pi&FO1PEc>coH(I9C%BJ{q6&*Ty`np~ za0Y)}#!SnXGSdTSA+#oNc5#m6etj+hpJS6hgeTMYB)&z6F;wSvWPDuj4eBGn|1*vs zpDU{Qb`wR16WTV_3;0hs{0DQJIWG2&Q{5!tL~q9I3w-wba}RRcWu^~hR;jgsKf~eS zIpUS@=U`9zc5(RLIgL}fu0s!SXmGAhtyQTC*vH5IIqf-G^DjEqE)LzQuN~8&k8!AO?g8%Hom;B-=zOSLZi}owDyY112Gro@M z;P}oPFSQT&OHZGZ1hi>Wg*Uuq*nocnZrNOa@zZzF4M;x{tJS0{r#Q}PjdJhfKPCEqYl5o;eW1W zwY@`!p5xE~Z6WF>{}ZxWog{DeR=QoU9PIiDHKe@oBD!DQtF8clKjIX6G>1y{KSh}z zr)MM$I40Z(G}PT*jIxY)Xx2x?z!vn%G57gs!8s_*{qbdtG3X7xf~G3j2L*$ zZ^r#}2}bwot7%;cxGd(f6VHXjsh2cDah~qYeZug zXb_!IPK$EIR;Aepl{s}{CoxqH-2^ksRWEiXKFR9u!|J5>+&FftU_lc{X7H+plfc~7DOdp~Z4;;p(6qsA zN!e7o*|~$|(X+$rnuylmoLOB9*u5O);;^TXU2FKcT7eo%M5VyMRb^-bGCnU>1R!b@}Uw&-GK;$DowA}pf?v*qi$*zQ6n$voN5Nr z`x*GylV~Y4@;mNx{ADfs=4=ZjV(Gq`CR<>L*&2peaf8w0h>xJ&H(yEjRowwk#1e7A z(^jUP^dcUm`?M*Wk{kbRX5+r*J2Jbf%_Ofu9QSQ*ks$ zTXa1``R63v`)J2DlXkKgH$JM=psSSVI)qW1d1!czM?2{WRmL}gwnMNrR7wwlC-FLK z5pVihppCwYz=L@jtAPL9pEovoMxd#hkUgG&1cSp)#LsG-meGSeA~`_4N{5&{l@i{- z@1VaTkDkd>A(es}>0@x%3ToQvR}EHuy%p=zeU?0Yt7n8>v-BK&23C0r=ZAcU{E^!S zxzup}v5@1iA~n)U?P%b)%^2d;ij+T_L#M3uisTFV@Z#_-yfBP+Jj`ojUyXo@EHhn# z{LI{kMmI0qQ+K2`qMyCvYezjnElS$6!k^Mn^2=9;AKIBaonk}Q6T{pS)6w;}@sC*M zwx!Zh*KN=$&{>lQu}9e1(vM$%YOG-R^krb78!k@0fV zQqN}zlO0qf`t7K-!-)4KTL;B@dW)m{PWqx4L%KV?0>35dy35A@Wzc|q&W67$=T?L! zBFlsIQ%oESFQXjULGNTn(4rSb!9(vkrNIIJS6BGGt%Ki}I_cIn-hulCcE|5*Q?Yh? z2T{F@`YxAm_&W~xcm%&?6z{S=UZCC|*jwca?60C%c5~=8|5szCUASGkTt|gXMHtVH z%}@VvdY*m@0pBm8E~DQ+sQn7E&>PVFXY@Ds-XjKVGlHAluZ>pNg>5*$tg*Ryck>SC z-WI>J{luX|ojuO(XF7Wh9qxYC+1=ypJ>C;J^0f2WaIf=tcenF!_mQV9j5RmbH#U8z zv0;bv06Tzjxlkrxf1gq)x|k>!M2swjSr|>24fioYV6ly6BV%HQF=J7|NzuZDq5^}# z$5>IpDf%#@Xf|5KTJ|8LR>vyDPS%0{eQ@Po7G~Xm_OKIdgSZ!uT7LEb{&oTq!Q5fE zd_6FZu;YMqV|M&U`nF>KY$#{u^FP B=KBBu diff --git a/F1:F103/USB_NEW_concept/Makefile b/F1:F103/USB_New_concept/USB_NEW_concept_HID/Makefile similarity index 100% rename from F1:F103/USB_NEW_concept/Makefile rename to F1:F103/USB_New_concept/USB_NEW_concept_HID/Makefile diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_HID/hardware.c b/F1:F103/USB_New_concept/USB_NEW_concept_HID/hardware.c new file mode 100644 index 0000000..24bbf31 --- /dev/null +++ b/F1:F103/USB_New_concept/USB_NEW_concept_HID/hardware.c @@ -0,0 +1,50 @@ +/* + * Copyright 2024 Edward V. Emelianov . + * + * 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 . + */ + +#include "hardware.h" + +static inline void gpio_setup(){ + // Enable clocks to the GPIO subsystems (PB for ADC), turn on AFIO clocking to disable SWD/JTAG + RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN; + // turn off SWJ/JTAG +// AFIO->MAPR = AFIO_MAPR_SWJ_CFG_DISABLE; + AFIO->MAPR = AFIO_MAPR_SWJ_CFG_JTAGDISABLE; // for PA15 + // Set led as opendrain output + GPIOC->CRH = CRH(13, CNF_ODOUTPUT|MODE_SLOW); + // USB pullup (PA15) - pushpull output + GPIOA->CRH = CRH(15, CNF_PPOUTPUT|MODE_SLOW); +} + +void hw_setup(){ + gpio_setup(); +} + +#ifndef EBUG +void iwdg_setup(){ + uint32_t tmout = 16000000; + RCC->CSR |= RCC_CSR_LSION; + while((RCC->CSR & RCC_CSR_LSIRDY) != RCC_CSR_LSIRDY){if(--tmout == 0) break;} /* (2) */ + IWDG->KR = IWDG_START; + IWDG->KR = IWDG_WRITE_ACCESS; + IWDG->PR = IWDG_PR_PR_1; + IWDG->RLR = 1250; + tmout = 16000000; + while(IWDG->SR){if(--tmout == 0) break;} + IWDG->KR = IWDG_REFRESH; +} +#endif + diff --git a/F1:F103/USB_NEW_concept/hardware.h b/F1:F103/USB_New_concept/USB_NEW_concept_HID/hardware.h similarity index 100% rename from F1:F103/USB_NEW_concept/hardware.h rename to F1:F103/USB_New_concept/USB_NEW_concept_HID/hardware.h diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_HID/keycodes.c b/F1:F103/USB_New_concept/USB_NEW_concept_HID/keycodes.c new file mode 100644 index 0000000..34c575a --- /dev/null +++ b/F1:F103/USB_New_concept/USB_NEW_concept_HID/keycodes.c @@ -0,0 +1,76 @@ +/* + * keycodes.c + * + * Copyright 2015 Edward V. Emelianov + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "keycodes.h" +/* + * Keyboard buffer: + * buf[1]: MOD + * buf[2]: reserved + * buf[3]..buf[8] - keycodes 1..6 + */ +static uint8_t buf[USB_KEYBOARD_REPORT_SIZE] = {2,0,0,0,0,0,0,0}; + +#define _(x) (x|0x80) +// array for keycodes according to ASCII table; MSB is MOD_SHIFT flag +static const uint8_t keycodes[] = { + // space !"#$%&' + KEY_SPACE, _(KEY_1), _(KEY_QUOTE), _(KEY_3), _(KEY_4), _(KEY_5), _(KEY_7), KEY_QUOTE, + // ()*+,-./ + _(KEY_9), _(KEY_0), _(KEY_8), _(KEY_EQUAL), KEY_COMMA, KEY_MINUS, KEY_PERIOD, KEY_SLASH, + // 0..9 + 39, 30, 31, 32, 33, 34, 35, 36, 37, 38, + // :;<=>?@ + _(KEY_SEMICOLON), KEY_SEMICOLON, _(KEY_COMMA), KEY_EQUAL, _(KEY_PERIOD), _(KEY_SLASH), _(KEY_2), + // A..Z: for a in $(seq 0 25); do printf "$((a+132)),"; done + 132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157, + // [\]^_` + KEY_LEFT_BRACE, KEY_BACKSLASH, KEY_RIGHT_BRACE, _(KEY_6), _(KEY_MINUS), KEY_TILDE, + // a..z: for a in $(seq 0 25); do printf "$((a+4)),"; done + 4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29, + // {|}~ + _(KEY_LEFT_BRACE), _(KEY_BACKSLASH), _(KEY_RIGHT_BRACE), _(KEY_TILDE) +}; + +uint8_t *set_key_buf(uint8_t MOD, uint8_t KEY){ + buf[1] = MOD; + buf[3] = KEY; + buf[4] = 0; + return buf; +} + +/** + * return buffer for sending symbol "ltr" with addition modificator mod + */ +uint8_t *press_key_mod(char ltr, uint8_t mod){ + uint8_t MOD = 0; + uint8_t KEY = 0; + buf[3] = buf[4]; + if(ltr > 31){ + KEY = keycodes[ltr - 32]; + if(KEY & 0x80){ + MOD = MOD_SHIFT; + KEY &= 0x7f; + } + }else if (ltr == '\n') KEY = KEY_ENTER; + buf[1] = MOD | mod; + buf[4] = KEY; + return buf; +} diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_HID/keycodes.h b/F1:F103/USB_New_concept/USB_NEW_concept_HID/keycodes.h new file mode 100644 index 0000000..5a4037e --- /dev/null +++ b/F1:F103/USB_New_concept/USB_NEW_concept_HID/keycodes.h @@ -0,0 +1,140 @@ +/* + * keycodes.h + * + * Copyright 2015 Edward V. Emelianov + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#pragma once +#ifndef __KEYKODES_H__ +#define __KEYKODES_H__ + +#include + +uint8_t *set_key_buf(uint8_t MOD, uint8_t KEY); +#define release_key() set_key_buf(0,0) +uint8_t *press_key_mod(char key, uint8_t mod); +#define press_key(k) press_key_mod(k, 0) + +#define USB_KEYBOARD_REPORT_SIZE 8 + +#define MOD_CTRL 0x01 +#define MOD_SHIFT 0x02 +#define MOD_ALT 0x04 +#define MOD_GUI 0x08 + +#define LEFT(mod) (mod) +#define RIGHT(mod) ((mod << 4)) + +#define KEY_A 4 +#define KEY_B 5 +#define KEY_C 6 +#define KEY_D 7 +#define KEY_E 8 +#define KEY_F 9 +#define KEY_G 10 +#define KEY_H 11 +#define KEY_I 12 +#define KEY_J 13 +#define KEY_K 14 +#define KEY_L 15 +#define KEY_M 16 +#define KEY_N 17 +#define KEY_O 18 +#define KEY_P 19 +#define KEY_Q 20 +#define KEY_R 21 +#define KEY_S 22 +#define KEY_T 23 +#define KEY_U 24 +#define KEY_V 25 +#define KEY_W 26 +#define KEY_X 27 +#define KEY_Y 28 +#define KEY_Z 29 +#define KEY_1 30 +#define KEY_2 31 +#define KEY_3 32 +#define KEY_4 33 +#define KEY_5 34 +#define KEY_6 35 +#define KEY_7 36 +#define KEY_8 37 +#define KEY_9 38 +#define KEY_0 39 +#define KEY_ENTER 40 +#define KEY_ESC 41 +#define KEY_BACKSPACE 42 +#define KEY_TAB 43 +#define KEY_SPACE 44 +#define KEY_MINUS 45 +#define KEY_EQUAL 46 +#define KEY_LEFT_BRACE 47 +#define KEY_RIGHT_BRACE 48 +#define KEY_BACKSLASH 49 +#define KEY_NUMBER 50 +#define KEY_SEMICOLON 51 +#define KEY_QUOTE 52 +#define KEY_TILDE 53 +#define KEY_COMMA 54 +#define KEY_PERIOD 55 +#define KEY_SLASH 56 +#define KEY_CAPS_LOCK 57 +#define KEY_F1 58 +#define KEY_F2 59 +#define KEY_F3 60 +#define KEY_F4 61 +#define KEY_F5 62 +#define KEY_F6 63 +#define KEY_F7 64 +#define KEY_F8 65 +#define KEY_F9 66 +#define KEY_F10 67 +#define KEY_F11 68 +#define KEY_F12 69 +#define KEY_PRINTSCREEN 70 +#define KEY_SCROLL_LOCK 71 +#define KEY_PAUSE 72 +#define KEY_INSERT 73 +#define KEY_HOME 74 +#define KEY_PAGE_UP 75 +#define KEY_DELETE 76 +#define KEY_END 77 +#define KEY_PAGE_DOWN 78 +#define KEY_RIGHT 79 +#define KEY_LEFT 80 +#define KEY_DOWN 81 +#define KEY_UP 82 +#define KEY_NUM_LOCK 83 +#define KEYPAD_SLASH 84 +#define KEYPAD_ASTERIX 85 +#define KEYPAD_MINUS 86 +#define KEYPAD_PLUS 87 +#define KEYPAD_ENTER 88 +#define KEYPAD_1 89 +#define KEYPAD_2 90 +#define KEYPAD_3 91 +#define KEYPAD_4 92 +#define KEYPAD_5 93 +#define KEYPAD_6 94 +#define KEYPAD_7 95 +#define KEYPAD_8 96 +#define KEYPAD_9 97 +#define KEYPAD_0 98 +#define KEYPAD_PERIOD 99 + +#endif // __KEYKODES_H__ diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_HID/main.c b/F1:F103/USB_New_concept/USB_NEW_concept_HID/main.c new file mode 100644 index 0000000..4615b93 --- /dev/null +++ b/F1:F103/USB_New_concept/USB_NEW_concept_HID/main.c @@ -0,0 +1,103 @@ +/* + * This file is part of the I2Cscan project. + * Copyright 2020 Edward V. Emelianov . + * + * 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 . + */ + +#include "hardware.h" +#include "keycodes.h" +#ifdef EBUG +#include "usart.h" +#endif +#include "usb_dev.h" + +volatile uint32_t Tms = 0; + +/* Called when systick fires */ +void sys_tick_handler(void){ + ++Tms; +} + +/* + * buf[0]: 1 - report ID + * buf[1]: bit2 - middle button, bit1 - right, bit0 - left + * buf[2]: move X + * buf[3]: move Y + * buf[4]: wheel + */ +static void move_mouse(int8_t x, int8_t y){ + int8_t buf[5] = {1,0,0,0,0}; + buf[2] = x; buf[3] = y; + USB_send((uint8_t*)buf, 5); +} + +/* + * Keyboard buffer: + * buf[1]: MOD + * buf[2]: reserved + * buf[3]..buf[8] - keycodes 1..6 + */ +static void send_word(const char *wrd){ + char last = 0; + do{ + // release key before pressing it again + if(last == *wrd) USB_send(release_key(), USB_KEYBOARD_REPORT_SIZE); + last = *wrd; + USB_send(press_key(last), USB_KEYBOARD_REPORT_SIZE); + IWDG->KR = IWDG_REFRESH; + }while(*(++wrd)); + USB_send(release_key(), USB_KEYBOARD_REPORT_SIZE); +} + +int main(void){ + uint32_t lastT = 0, lastsend = 0; + StartHSE(); + hw_setup(); + USBPU_OFF(); + SysTick_Config(72000); +#ifdef EBUG + usart_setup(); + uint32_t tt = 0; +#endif + USB_setup(); +#ifndef EBUG + iwdg_setup(); +#endif + USBPU_ON(); + while (1){ + IWDG->KR = IWDG_REFRESH; // refresh watchdog + if(Tms - lastT > 499){ + LED_blink(LED0); + lastT = Tms; + } +#ifdef EBUG + if(Tms != tt){ + __disable_irq(); + usart_transmit(); + tt = Tms; + __enable_irq(); + } +#endif + if(Tms - lastsend > 9999){ + if(usbON){ + send_word("Hello "); + move_mouse(100, 100); + //move_mouse(0,0); + lastsend = Tms; + } + } + } + return 0; +} diff --git a/F1:F103/USB_NEW_concept/openocd.cfg b/F1:F103/USB_New_concept/USB_NEW_concept_HID/openocd.cfg similarity index 100% rename from F1:F103/USB_NEW_concept/openocd.cfg rename to F1:F103/USB_New_concept/USB_NEW_concept_HID/openocd.cfg diff --git a/F1:F103/USB_NEW_concept/ringbuffer.c b/F1:F103/USB_New_concept/USB_NEW_concept_HID/ringbuffer.c similarity index 100% rename from F1:F103/USB_NEW_concept/ringbuffer.c rename to F1:F103/USB_New_concept/USB_NEW_concept_HID/ringbuffer.c diff --git a/F1:F103/USB_NEW_concept/ringbuffer.h b/F1:F103/USB_New_concept/USB_NEW_concept_HID/ringbuffer.h similarity index 100% rename from F1:F103/USB_NEW_concept/ringbuffer.h rename to F1:F103/USB_New_concept/USB_NEW_concept_HID/ringbuffer.h diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_HID/someusb.bin b/F1:F103/USB_New_concept/USB_NEW_concept_HID/someusb.bin new file mode 100755 index 0000000000000000000000000000000000000000..4310e47da98ec4fc08d86efbfe719da5963e53a9 GIT binary patch literal 3056 zcmd5;Yj6|S6+U-&C9fU<$u@~B3|>jbv8`YPP8u4fWi88#Ede5So+gi#BW4t$V#kh~ z&~)lG<{?M`+rnwUPGb|3GI?PPv}C5#uH7GLnoebiIzW=*gcOmuoms;gmPg~B6`8c9 z$^Y)mr?Y$RchBqId#<1mxPR(_-A;hrdK2KLN8@PF)SCQ3#{bT_*~WK$e}X>0ZLH&_ z7`~13|Ex3lEr;W=-QL2X9ASBG*pd}t6VzgQVk6^GsRiXKcZ8KVQ1-#jcfEQ28n z00$!QU!`D3`v#|aq%@ElwTB;$uF&1}p(juqwJ_Pq)zJlhTAoSg5Hcy1(GzVng&Se#-bfU;ZRUE&VcR> zDmBnlQ8?5j(38ac_?J<$O)w^E1kz)ic+u?h-KkQmakWmhkxLs%)SbVBgn7bk`=o9!m3Wxao{=rJYAxvNX z^H=*P7^-uy&sY5J(aEJVsgr5TZTzLBPZvfo^8&)R${u136p30~Kg77AQ3rD+`Bc=# zoKI?V=#x-AK*>pEkMuWlybjb$0h5{EnUaVb){OXlhB!8Y8F z`f;be@WW7GcBFgo34eOOHa=Em=Qk*PwNbPV$j9a|qsiKprRgZ4=vZQouvR#Pk>WYk zF{M?OyV8;VcbspeR#dK7J`z2wp0iML3)SIe5@oVPeiz<|G0^Diy_7}2FX_krtV3PuK9Am=lVIH<>RudsGgcI#+=WAwt2VdVLW&ve zHb!xgzedFByO%2K58Rm1qC9&*H`x!f!~#rGr(#VtzYz!|lF{D}HG_gfWU zpZYmBFm7ENfrF)1m zV5)k-t3Ph^XR5?RBX(nNW&^B0?q!aH12wbb-fLqZXJfX&X+3P*1gs{nBWV9|^}L6a zj^OV%z1%tf3#sz0z?K2J(;o3&nAzY}q(wP`9Zw_O-R9Muq`OHe9XCaK=u64H7-2hI zk?iwBzBOVK%47?%iq?ojrqi-arcl;KYQF~Bs?*+`%1<*j=~d37L_f0BXcy^SI`lzG z4^91~g^p9l>Bw$!DG82PpcZXAWtvLQktvjP$A5B}7~ z%Wwo`*$f3iMVf_`%qQG4fjv)pE6-gqTUz0C8lvmWUtWTD~^H z(ubz5wwO)`m7|f<<+B+|fofWYnyhjV6Lt7kmUx)=??An(7*-FTZ;IhR<77vh(O9%$%F3 zs4yfd1kK9X#!pWg=VxLUvI~DpX>&HJhTe^;31RN7z?(q2{$+}CYTYWCDs+MKc&c2` zcuzE*ZFDt#g8rv3ue)vwz@GSd8iWhsa*N2kv0cr!SOlE|I^R|^J=2#Ty^eWUq!d{2 zOmGMwyk#85m*x@VF6*#xDcq1VTVsWMI$@jjsj=vWT+@GIXu95s>pS+WI|W7b1o*>TlT5 zjOmDh>LUiy2b+k_kVA^-Sul@u(aofl>LSg$R)P$VVd1RSc`eOs7uBjC9yaLv$RpVZTVh+cz3}4p9Xs1QI^(;#Ui$gVyZ3bW zys}`S=e4)*Vs!cp)?hT5Z<#UEV$ICTo^|VOwjBHH+&Kph4jj=^PCsVa10`7C5?BZ& z^!-o+Uf`e-s=$ZxM^F#V&;)D14Nu|kdi)z#4 - + EnvironmentId @@ -33,6 +33,7 @@ false 4 false + 0 80 true true diff --git a/F1:F103/USB_NEW_concept/someusb.cxxflags b/F1:F103/USB_New_concept/USB_NEW_concept_HID/someusb.cxxflags similarity index 100% rename from F1:F103/USB_NEW_concept/someusb.cxxflags rename to F1:F103/USB_New_concept/USB_NEW_concept_HID/someusb.cxxflags diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_HID/someusb.files b/F1:F103/USB_New_concept/USB_NEW_concept_HID/someusb.files new file mode 100644 index 0000000..b5487b1 --- /dev/null +++ b/F1:F103/USB_New_concept/USB_NEW_concept_HID/someusb.files @@ -0,0 +1,14 @@ +hardware.c +hardware.h +keycodes.c +main.c +ringbuffer.c +ringbuffer.h +usart.c +usart.h +usb_descr.c +usb_descr.h +usb_lib.c +usb_lib.h +usb_dev.c +usb_dev.h diff --git a/F1:F103/USB_NEW_concept/someusb.includes b/F1:F103/USB_New_concept/USB_NEW_concept_HID/someusb.includes similarity index 100% rename from F1:F103/USB_NEW_concept/someusb.includes rename to F1:F103/USB_New_concept/USB_NEW_concept_HID/someusb.includes diff --git a/F1:F103/USB_NEW_concept/usart.c b/F1:F103/USB_New_concept/USB_NEW_concept_HID/usart.c similarity index 100% rename from F1:F103/USB_NEW_concept/usart.c rename to F1:F103/USB_New_concept/USB_NEW_concept_HID/usart.c diff --git a/F1:F103/USB_NEW_concept/usart.h b/F1:F103/USB_New_concept/USB_NEW_concept_HID/usart.h similarity index 98% rename from F1:F103/USB_NEW_concept/usart.h rename to F1:F103/USB_New_concept/USB_NEW_concept_HID/usart.h index f7bc03f..c362186 100644 --- a/F1:F103/USB_NEW_concept/usart.h +++ b/F1:F103/USB_New_concept/USB_NEW_concept_HID/usart.h @@ -23,7 +23,7 @@ #include -#define UARTBUFSZO (1024) +#define UARTBUFSZO (2048) // macro for static strings #define USEND(str) usart_send(str) diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_descr.c b/F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_descr.c new file mode 100644 index 0000000..901536c --- /dev/null +++ b/F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_descr.c @@ -0,0 +1,259 @@ +/* + * Copyright 2024 Edward V. Emelianov . + * + * 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 . + */ + +#include "usart.h" +#include "usb_descr.h" + +/* +#undef DBG +#define DBG(x) +#undef DBGs +#define DBGs(x) +*/ + +// low/high for uint16_t +#define L16(x) (x & 0xff) +#define H16(x) (x >> 8) + +static const uint8_t USB_DeviceDescriptor[] = { + USB_DT_DEVICE_SIZE, // bLength + USB_DT_DEVICE, // bDescriptorType + L16(bcdUSB), // bcdUSB_L + H16(bcdUSB), // bcdUSB_H + USB_CLASS_PER_INTERFACE, // bDeviceClass + bDeviceSubClass, // bDeviceSubClass + bDeviceProtocol, // bDeviceProtocol + USB_EP0BUFSZ, // bMaxPacketSize + L16(idVendor), // idVendor_L + H16(idVendor), // idVendor_H + L16(idProduct), // idProduct_L + H16(idProduct), // idProduct_H + L16(bcdDevice_Ver), // bcdDevice_Ver_L + H16(bcdDevice_Ver), // bcdDevice_Ver_H + iMANUFACTURER_DESCR, // iManufacturer - indexes of string descriptors in array + iPRODUCT_DESCR, // iProduct + iSERIAL_DESCR, // iSerial + bNumConfigurations // bNumConfigurations +}; + +static const uint8_t USB_DeviceQualifierDescriptor[] = { + USB_DT_QUALIFIER_SIZE, //bLength + USB_DT_QUALIFIER, // bDescriptorType + L16(bcdUSB), // bcdUSB_L + H16(bcdUSB), // bcdUSB_H + USB_CLASS_PER_INTERFACE, // bDeviceClass + bDeviceSubClass, // bDeviceSubClass + bDeviceProtocol, // bDeviceProtocol + USB_EP0BUFSZ, // bMaxPacketSize0 + bNumConfigurations, // bNumConfigurations + 0 // Reserved +}; + +static const uint8_t HID_ReportDescriptor[] = { + 0x05, 0x01, /* Usage Page (Generic Desktop) */ + 0x09, 0x02, /* Usage (Mouse) */ + 0xA1, 0x01, /* Collection (Application) */ + 0x09, 0x01, /* Usage (Pointer) */ + 0xA1, 0x00, /* Collection (Physical) */ + 0x85, 0x01, /* Report ID */ + 0x05, 0x09, /* Usage Page (Buttons) */ + 0x19, 0x01, /* Usage Minimum (01) */ + 0x29, 0x03, /* Usage Maximum (03) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x25, 0x01, /* Logical Maximum (0) */ + 0x95, 0x03, /* Report Count (3) */ + 0x75, 0x01, /* Report Size (1) */ + 0x81, 0x02, /* Input (Data, Variable, Absolute) */ + 0x95, 0x01, /* Report Count (1) */ + 0x75, 0x05, /* Report Size (5) */ + 0x81, 0x01, /* Input (Constant) ;5 bit padding */ + 0x05, 0x01, /* Usage Page (Generic Desktop) */ + 0x09, 0x30, /* Usage (X) */ + 0x09, 0x31, /* Usage (Y) */ + 0x15, 0x81, /* Logical Minimum (-127) */ + 0x25, 0x7F, /* Logical Maximum (127) */ + 0x75, 0x08, /* Report Size (8) */ + 0x95, 0x02, /* Report Count (2) */ + 0x81, 0x06, /* Input (Data, Variable, Relative) */ + 0xC0, 0xC0,/* End Collection,End Collection */ + // + 0x09, 0x06, /* Usage (Keyboard) */ + 0xA1, 0x01, /* Collection (Application) */ + 0x85, 0x02, /* Report ID */ + 0x05, 0x07, /* Usage (Key codes) */ + 0x19, 0xE0, /* Usage Minimum (224) */ + 0x29, 0xE7, /* Usage Maximum (231) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x25, 0x01, /* Logical Maximum (1) */ + 0x75, 0x01, /* Report Size (1) */ + 0x95, 0x08, /* Report Count (8) */ + 0x81, 0x02, /* Input (Data, Variable, Absolute) */ + 0x95, 0x01, /* Report Count (1) */ + 0x75, 0x08, /* Report Size (8) */ + 0x81, 0x01, /* Input (Constant) ;5 bit padding */ + 0x95, 0x05, /* Report Count (5) */ + 0x75, 0x01, /* Report Size (1) */ + 0x05, 0x08, /* Usage Page (Page# for LEDs) */ + 0x19, 0x01, /* Usage Minimum (01) */ + 0x29, 0x05, /* Usage Maximum (05) */ + 0x91, 0x02, /* Output (Data, Variable, Absolute) */ + 0x95, 0x01, /* Report Count (1) */ + 0x75, 0x03, /* Report Size (3) */ + 0x91, 0x01, /* Output (Constant) */ + 0x95, 0x06, /* Report Count (1) */ + 0x75, 0x08, /* Report Size (3) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x25, 0x65, /* Logical Maximum (101) */ + 0x05, 0x07, /* Usage (Key codes) */ + 0x19, 0x00, /* Usage Minimum (00) */ + 0x29, 0x65, /* Usage Maximum (101) */ + 0x81, 0x00, /* Input (Data, Array) */ + 0xC0 /* End Collection,End Collection */ +}; + +#define wTotalLength (USB_DT_CONFIG_SIZE + (bNumInterfaces * USB_DT_INTERFACE_SIZE) + (bTotNumEndpoints * USB_DT_ENDPOINT_SIZE) + USB_DT_HID_SIZE) + +static const uint8_t USB_ConfigDescriptor[] = { + // Configuration Descriptor + USB_DT_CONFIG_SIZE, // bLength: Configuration Descriptor size + USB_DT_CONFIG, // bDescriptorType: Configuration + L16(wTotalLength), // wTotalLength.L :no of returned bytes + H16(wTotalLength), // wTotalLength.H + bNumInterfaces, // bNumInterfaces + 1, // bConfigurationValue: Current configuration value + 0, // iConfiguration: Index of string descriptor describing the configuration or 0 + BusPowered, // bmAttributes - Bus powered + 50, // MaxPower in 2mA units + //--------------------------------------------------------------------------- + // Interface Descriptor + USB_DT_INTERFACE_SIZE, // bLength: Interface Descriptor size + USB_DT_INTERFACE, // bDescriptorType: Interface + 0, // bInterfaceNumber: Number of Interface + 0, // bAlternateSetting: Alternate setting + bTotNumEndpoints, // bNumEndpoints + USB_CLASS_HID, // bInterfaceClass + 1, // bInterfaceSubClass: boot + 1, // bInterfaceProtocol: keyboard + 0, // iInterface: + //--------------------------------------------------------------------------- + // HID device descriptor + USB_DT_HID_SIZE, // bLength + USB_DT_HID, // bDescriptorType: HID + L16(bcdUSB), // bcdUSB_L + H16(bcdUSB), // bcdUSB_H + 0, // bCountryCode: Not supported + 1, // bNumDescriptors: 1 + USB_DT_REPORT, // bDescriptorType: Report + L16(sizeof(HID_ReportDescriptor)), // wDescriptorLength + H16(sizeof(HID_ReportDescriptor)), + // Endpoint 1 Descriptor + USB_DT_ENDPOINT_SIZE, // bLength: Endpoint Descriptor size + USB_DT_ENDPOINT, // bDescriptorType: Endpoint + 0x81, // bEndpointAddress IN1 + USB_BM_ATTR_INTERRUPT, // bmAttributes: Interrupt + L16(USB_EP1BUFSZ), // wMaxPacketSize LO + H16(USB_EP1BUFSZ), // wMaxPacketSize HI + 0x01, // bInterval: 1ms +}; + +_USB_LANG_ID_(LD, LANG_US); +_USB_STRING_(SD, u"0.0.1"); +_USB_STRING_(MD, u"eddy@sao.ru"); +_USB_STRING_(PD, u"USB HID mouse+keyboard"); +//_USB_STRING_(ID, u"mouse_keyboard"); + +static const void* const StringDescriptor[iDESCR_AMOUNT] = { + [iLANGUAGE_DESCR] = &LD, + [iMANUFACTURER_DESCR] = &MD, + [iPRODUCT_DESCR] = &PD, + [iSERIAL_DESCR] = &SD, +// [iINTERFACE_DESCR1] = &ID +}; + +void wr0(const uint8_t *buf, uint16_t size, uint16_t askedsize){ + if(askedsize < size) size = askedsize; // shortened request + if(size < USB_EP0BUFSZ){ + //DBG("short wr0"); + EP_WriteIRQ(0, buf, size); + return; + } + //DBG("long wr0"); + while(size){ + //DBG("write"); + //DBGs(uhex2str(size)); + uint16_t l = size; + if(l > USB_EP0BUFSZ) l = USB_EP0BUFSZ; + //DBGs(uhex2str(l)); + EP_WriteIRQ(0, buf, l); + buf += l; + size -= l; + uint8_t needzlp = (l == USB_EP0BUFSZ) ? 1 : 0; + if(size || needzlp){ // send next data buffer + uint16_t epstatus = KEEP_DTOG(USB->EPnR[0]); + // keep DTOGs, clear CTR_TX/CTR_RX, set TX VALID, leave stat_Rx + USB->EPnR[0] = (epstatus & ~(USB_EPnR_CTR_RX|USB_EPnR_CTR_TX|USB_EPnR_STAT_RX)) + ^ USB_EPnR_STAT_TX; + //USB->EPnR[0] = (epstatus & ~(USB_EPnR_CTR_TX|USB_EPnR_STAT_RX)) + // ^ USB_EPnR_STAT_TX; + uint32_t ctr = 100000; + while(--ctr && (USB->ISTR & USB_ISTR_CTR) == 0){IWDG->KR = IWDG_REFRESH;}; + //DBGs(uhex2str(USB->ISTR)); + //DBGs(uhex2str(USB->EPnR[0])); + if((USB->ISTR & USB_ISTR_CTR) == 0){ + DBG("No CTR!"); + return; + } + if(needzlp) EP_WriteIRQ(0, NULL, 0); + } + } +} + +void get_descriptor(config_pack_t *pack){ + uint8_t descrtype = pack->wValue >> 8, + descridx = pack->wValue & 0xff; + DBG("DESCR:"); + DBGs(uhex2str(descrtype)); + DBGs(uhex2str(descridx)); + DBGs(uhex2str(pack->wLength)); + switch(descrtype){ + case DEVICE_DESCRIPTOR: + DBG("DEVICE_DESCRIPTOR"); + wr0(USB_DeviceDescriptor, sizeof(USB_DeviceDescriptor), pack->wLength); + break; + case CONFIGURATION_DESCRIPTOR: + DBG("CONFIGURATION_DESCRIPTOR"); + wr0(USB_ConfigDescriptor, sizeof(USB_ConfigDescriptor), pack->wLength); + break; + case STRING_DESCRIPTOR: + DBG("STRING_DESCRIPTOR"); + if(descridx < iDESCR_AMOUNT) wr0((const uint8_t *)StringDescriptor[descridx], *((uint8_t*)StringDescriptor[descridx]), pack->wLength); + else EP_WriteIRQ(0, NULL, 0); + break; + case DEVICE_QUALIFIER_DESCRIPTOR: + DBG("DEVICE_QUALIFIER_DESCRIPTOR"); + wr0(USB_DeviceQualifierDescriptor, sizeof(USB_DeviceQualifierDescriptor), pack->wLength); + break; + case HID_REPORT_DESCRIPTOR: + DBG("HID_REPORT_DESCRIPTOR"); + wr0(HID_ReportDescriptor, sizeof(HID_ReportDescriptor), pack->wLength); + break; + default: + DBG("Wrong"); + DBGs(uhex2str(descrtype)); + break; + } +} diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_descr.h b/F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_descr.h new file mode 100644 index 0000000..2361708 --- /dev/null +++ b/F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_descr.h @@ -0,0 +1,63 @@ +/* + * Copyright 2024 Edward V. Emelianov . + * + * 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 . + */ +#pragma once + +#include + +#include "usb_lib.h" + +// definition of parts common for USB_DeviceDescriptor & USB_DeviceQualifierDescriptor +// bcdUSB: 1.10 +#define bcdUSB 0x0110 +#define bDeviceSubClass 0x00 +#define bDeviceProtocol 0x00 +#define idVendor 0x045e +#define idProduct 0x005c +#define bcdDevice_Ver 0x0200 +#define bNumConfigurations 1 + +// amount of interfaces and endpoints (except 0) used +#define bNumInterfaces 1 +#define bTotNumEndpoints 1 + +// powered +#define BusPowered (1<<7) +#define SelfPowered (1<<6) +#define RemoteWakeup (1<<5) + +// buffer sizes +// for USB FS EP0 buffers are from 8 to 64 bytes long +#define USB_EP0BUFSZ 64 +#define USB_EP1BUFSZ 10 + +// string descriptors +enum{ + iLANGUAGE_DESCR, + iMANUFACTURER_DESCR, + iPRODUCT_DESCR, + iSERIAL_DESCR, + /*iINTERFACE_DESCR1, + iINTERFACE_DESCR2, + iINTERFACE_DESCR3, + iINTERFACE_DESCR4, + iINTERFACE_DESCR5, + iINTERFACE_DESCR6, + iINTERFACE_DESCR7,*/ + iDESCR_AMOUNT +}; + +void get_descriptor(config_pack_t *pack); diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_dev.c b/F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_dev.c new file mode 100644 index 0000000..ac768e6 --- /dev/null +++ b/F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_dev.c @@ -0,0 +1,67 @@ +/* + * Copyright 2024 Edward V. Emelianov . + * + * 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 . + */ + +#include +#include + +#include "usart.h" +#include "usb_descr.h" +#include "usb_dev.h" + +static volatile uint8_t tx_succesfull = 1; + +static void EP1_Handler(){ + uint16_t epstatus = KEEP_DTOG(USB->EPnR[1]); + if(RX_FLAG(epstatus)) epstatus = (epstatus & ~USB_EPnR_STAT_TX) ^ USB_EPnR_STAT_RX; // set valid RX + else{ + tx_succesfull = 1; + epstatus = epstatus & ~(USB_EPnR_STAT_TX|USB_EPnR_STAT_RX); + } + // clear CTR + epstatus = (epstatus & ~(USB_EPnR_CTR_RX|USB_EPnR_CTR_TX)); + USB->EPnR[1] = epstatus; +} + +int USB_send(uint8_t *buf, uint16_t size){ + if(!usbON || !size) return 0; + uint16_t ctr = 0; + while(size){ + uint16_t s = (size > USB_EP1BUFSZ) ? USB_EP1BUFSZ : size; + tx_succesfull = 0; + EP_Write(1, (uint8_t*)&buf[ctr], s); + uint32_t ctra = 1000000; + while(--ctra && tx_succesfull == 0){ + IWDG->KR = IWDG_REFRESH; + } + if(!tx_succesfull){ + DBG("Error sending data!"); + return ctr; + } + size -= s; + ctr += s; + } + return ctr; +} + +// USB is configured: setup endpoints +void set_configuration(){ + DBG("set_configuration()"); + EP_Init(1, EP_TYPE_INTERRUPT, USB_EP1BUFSZ, 0, EP1_Handler); // IN1 - transmit +} + + + diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_dev.h b/F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_dev.h new file mode 100644 index 0000000..6872a98 --- /dev/null +++ b/F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_dev.h @@ -0,0 +1,22 @@ +/* + * Copyright 2024 Edward V. Emelianov . + * + * 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 . + */ + +#include +#include "usb_lib.h" + +int USB_send(uint8_t *buf, uint16_t size); + diff --git a/F1:F103/USB_NEW_concept/usb_lib.c b/F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_lib.c similarity index 78% rename from F1:F103/USB_NEW_concept/usb_lib.c rename to F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_lib.c index 1c81afd..9db1799 100644 --- a/F1:F103/USB_NEW_concept/usb_lib.c +++ b/F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_lib.c @@ -21,21 +21,20 @@ #include "usb_descr.h" #include "usb_dev.h" +/* #undef DBG #define DBG(x) #undef DBGs #define DBGs(x) +*/ static ep_t endpoints[STM32ENDPOINTS]; static uint16_t USB_Addr = 0; -static uint8_t ep0databuf[EP0DATABUF_SIZE], setupdatabuf[EP0DATABUF_SIZE]; -static uint8_t ep0dbuflen = 0; +static uint8_t setupdatabuf[EP0DATABUF_SIZE]; static config_pack_t *setup_packet = (config_pack_t*) setupdatabuf; volatile uint8_t usbON = 0; // device is configured and active -const uint8_t HID_ReportDescriptor[] WEAK = {0}; - static uint16_t configuration = 0; // reply for GET_CONFIGURATION (==1 if configured) static inline void std_d2h_req(){ uint16_t st = 0; @@ -84,47 +83,26 @@ static inline void std_h2d_req(){ void WEAK usb_standard_request(){ uint8_t recipient = REQUEST_RECIPIENT(setup_packet->bmRequestType); uint8_t dev2host = (setup_packet->bmRequestType & 0x80) ? 1 : 0; - uint8_t reqtype = REQUEST_TYPE(setup_packet->bmRequestType); switch(recipient){ case REQ_RECIPIENT_DEVICE: DBG("REQ_RECIPIENT_DEVICE"); if(dev2host){ std_d2h_req(); - return; }else{ std_h2d_req(); - EP_WriteIRQ(0, NULL, 0); + //EP_WriteIRQ(0, NULL, 0); } break; case REQ_RECIPIENT_INTERFACE: DBG("REQ_RECIPIENT_INTERFACE"); - switch(reqtype){ - case REQ_TYPE_STANDARD: - DBG("REQ_TYPE_STANDARD"); - if(dev2host && setup_packet->bRequest == GET_DESCRIPTOR){ - get_descriptor(setup_packet); - }else EP_WriteIRQ(0, NULL, 0); - break; - case REQ_TYPE_CLASS: - DBG("REQ_TYPE_CLASS"); - if(setup_packet->bRequest == GET_INTERFACE){ - EP_WriteIRQ(0, NULL, 0); - }else{ DBG("Wrong"); } - /*else if (setup_packet->bRequest == SET_FEAUTRE){ - //set_featuring = 1; - }*/ - break; - default: - DBG("Wrong"); - DBGs(uhex2str(reqtype)); - if(dev2host) EP_WriteIRQ(0, NULL, 0); - break; - } + if(dev2host && setup_packet->bRequest == GET_DESCRIPTOR){ + get_descriptor(setup_packet); + }//else EP_WriteIRQ(0, NULL, 0); break; case REQ_RECIPIENT_ENDPOINT: DBG("REQ_RECIPIENT_ENDPOINT"); if(setup_packet->bRequest == CLEAR_FEATURE){ - EP_WriteIRQ(0, NULL, 0); + //EP_WriteIRQ(0, NULL, 0); }else{ DBG("Wrong"); } @@ -134,16 +112,34 @@ void WEAK usb_standard_request(){ DBGs(uhex2str(recipient)); break; } + if(!dev2host) EP_WriteIRQ(0, NULL, 0); } -void WEAK usb_class_request(config_pack_t _U_ *req, uint8_t _U_ *data, uint16_t _U_ datalen){ - DBG("weak"); - EP_WriteIRQ(0, NULL, 0); +void WEAK usb_class_request(config_pack_t *req, uint8_t _U_ *data, uint16_t _U_ datalen){ + DBG("REQ_TYPE_CLASS"); + switch(req->bRequest){ + case GET_INTERFACE: + DBG("GI"); + break; + case SET_CONFIGURATION: // set featuring by req->wValue + DBG("SC"); + break; + default: + DBG("Wrong"); + DBGs(uhex2str(req->bmRequestType)); + DBGs(uhex2str(req->bRequest)); + DBGs(uhex2str(req->wIndex)); + DBGs(uhex2str(req->wLength)); + DBGs(uhex2str(req->wValue)); + } + if(0 == (setup_packet->bmRequestType & 0x80)) // host2dev + EP_WriteIRQ(0, NULL, 0); } void WEAK usb_vendor_request(config_pack_t _U_ *packet, uint8_t _U_ *data, uint16_t _U_ datalen){ - DBG("weak"); - EP_WriteIRQ(0, NULL, 0); + DBG("vendor"); + if(0 == (setup_packet->bmRequestType & 0x80)) // host2dev + EP_WriteIRQ(0, NULL, 0); } /* @@ -156,59 +152,45 @@ bmRequestType: 76543210 * Endpoint0 (control) handler */ static void EP0_Handler(){ + uint8_t ep0dbuflen = 0; + uint8_t ep0databuf[EP0DATABUF_SIZE]; uint16_t epstatus = USB->EPnR[0]; // EP0R on input -> return this value after modifications - uint8_t reqtype = REQUEST_TYPE(setup_packet->bmRequestType); - int rxflag = RX_FLAG(epstatus); - DBG("EP0_Handler"); + //DBG("EP0_Handler"); // check direction if(USB->ISTR & USB_ISTR_DIR){ // OUT interrupt - receive data, CTR_RX==1 (if CTR_TX == 1 - two pending transactions: receive following by transmit) if(epstatus & USB_EPnR_SETUP){ // setup packet -> copy data to conf_pack - DBG("USB_EPnR_SETUP"); + //DBG("USB_EPnR_SETUP"); EP_Read(0, setupdatabuf); // interrupt handler will be called later }else if(epstatus & USB_EPnR_CTR_RX){ // data packet -> push received data to ep0databuf - if(endpoints[0].rx_cnt){ DBG("data");} + //if(endpoints[0].rx_cnt){ DBG("data");} ep0dbuflen = EP_Read(0, ep0databuf); } } - if(rxflag && SETUP_FLAG(epstatus)){ + int rxflag = RX_FLAG(epstatus); + if(rxflag){ + uint8_t reqtype = REQUEST_TYPE(setup_packet->bmRequestType); switch(reqtype){ case REQ_TYPE_STANDARD: DBG("REQ_TYPE_STANDARD"); usb_standard_request(); - break; + break; case REQ_TYPE_CLASS: DBG("REQ_TYPE_CLASS"); - usb_class_request(setup_packet, NULL, 0); - break; + usb_class_request(setup_packet, ep0databuf, ep0dbuflen); + break; case REQ_TYPE_VENDOR: DBG("REQ_TYPE_VENDOR"); - usb_vendor_request(setup_packet, NULL, 0); - break; + usb_vendor_request(setup_packet, ep0databuf, ep0dbuflen); + break; default: DBG("Wrong"); DBGs(uhex2str(reqtype)); EP_WriteIRQ(0, NULL, 0); - break; - } - }else if(rxflag){ // got data over EP0 or host acknowlegement - if(ep0dbuflen){ - switch(reqtype){ - case REQ_TYPE_CLASS: - DBG("REQ_TYPE_CLASS"); - usb_class_request(setup_packet, ep0databuf, ep0dbuflen); break; - case REQ_TYPE_VENDOR: - DBG("REQ_TYPE_VENDOR"); - usb_vendor_request(setup_packet, ep0databuf, ep0dbuflen); - break; - default: - DBG("Wrong"); - DBGs(uhex2str(reqtype)); - } - ep0dbuflen = 0; } - }else if(TX_FLAG(epstatus)){ // package transmitted + } + if(TX_FLAG(epstatus)){ // now we can change address after enumeration if ((USB->DADDR & USB_DADDR_ADD) != USB_Addr){ USB->DADDR = USB_DADDR_EF | USB_Addr; @@ -218,7 +200,7 @@ static void EP0_Handler(){ } } epstatus = KEEP_DTOG(USB->EPnR[0]); - if(rxflag) epstatus ^= USB_EPnR_STAT_TX; // start ZLP/data transmission + if(rxflag) epstatus ^= USB_EPnR_STAT_TX; // start ZLP or data transmission else epstatus &= ~USB_EPnR_STAT_TX; // or leave unchanged // keep DTOGs, clear CTR_RX,TX, set RX VALID USB->EPnR[0] = (epstatus & ~(USB_EPnR_CTR_RX|USB_EPnR_CTR_TX)) ^ USB_EPnR_STAT_RX; @@ -302,18 +284,11 @@ static uint16_t lastaddr = LASTADDR_DEFAULT; * @return 0 if all OK */ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*func)(ep_t ep)){ - /*DBG("num, type, txsz, rxsz"); - DBGs(uhex2str(number)); - DBGs(uhex2str(type)); - DBGs(uhex2str(txsz)); - DBGs(uhex2str(rxsz));*/ if(number >= STM32ENDPOINTS) return 4; // out of configured amount if(txsz > USB_BTABLE_SIZE || rxsz > USB_BTABLE_SIZE) return 1; // buffer too large if(lastaddr + txsz + rxsz >= USB_BTABLE_SIZE/ACCESSZ) return 2; // out of btable USB->EPnR[number] = (type << 9) | (number & USB_EPnR_EA); USB->EPnR[number] ^= USB_EPnR_STAT_RX | USB_EPnR_STAT_TX_1; - /*DBG("EPnR="); - DBGs(uhex2str(USB->EPnR[number]));*/ if(rxsz & 1 || rxsz > USB_BTABLE_SIZE) return 3; // wrong rx buffer size uint16_t countrx = 0; if(rxsz < 64) countrx = rxsz / 2; @@ -321,32 +296,21 @@ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*f if(rxsz & 0x1f) return 3; // should be multiple of 32 countrx = 31 + rxsz / 32; } - //DBG("addrtx, txbuf, txbufsz"); USB_BTABLE->EP[number].USB_ADDR_TX = lastaddr; endpoints[number].tx_buf = (uint16_t *)(USB_BTABLE_BASE + lastaddr * ACCESSZ); endpoints[number].txbufsz = txsz; - /*DBGs(uhex2str(USB_BTABLE->EP[number].USB_ADDR_TX)); - DBGs(uhex2str((uint32_t)endpoints[number].tx_buf)); - DBGs(uhex2str(endpoints[number].txbufsz));*/ lastaddr += txsz; USB_BTABLE->EP[number].USB_COUNT_TX = 0; USB_BTABLE->EP[number].USB_ADDR_RX = lastaddr; endpoints[number].rx_buf = (uint8_t *)(USB_BTABLE_BASE + lastaddr * ACCESSZ); - /*DBG("Adrrx, rxbuf"); - DBGs(uhex2str(USB_BTABLE->EP[number].USB_ADDR_RX)); - DBGs(uhex2str((uint32_t)endpoints[number].rx_buf));*/ lastaddr += rxsz; USB_BTABLE->EP[number].USB_COUNT_RX = countrx << 10; - /*DBG("countrx"); - DBGs(uhex2str(USB_BTABLE->EP[number].USB_COUNT_RX));*/ endpoints[number].func = func; return 0; } // standard IRQ handler void USB_IRQ(){ - /*DBG("USB_IRQ"); - DBGs(uhex2str(USB->ISTR));*/ uint32_t CNTR = USB->CNTR; USB->CNTR = 0; if(USB->ISTR & USB_ISTR_RESET){ @@ -359,19 +323,19 @@ void USB_IRQ(){ lastaddr = LASTADDR_DEFAULT; // clear address, leave only enable bit USB->DADDR = USB_DADDR_EF; + USB->ISTR = ~USB_ISTR_RESET; if(EP_Init(0, EP_TYPE_CONTROL, USB_EP0BUFSZ, USB_EP0BUFSZ, EP0_Handler)){ DBG("Can't init EP0"); return; }; } if(USB->ISTR & USB_ISTR_CTR){ - DBG("USB_ISTR_CTR"); // EP number uint8_t n = USB->ISTR & USB_ISTR_EPID; // copy received bytes amount endpoints[n].rx_cnt = USB_BTABLE->EP[n].USB_COUNT_RX & 0x3FF; // low 10 bits is counter // call EP handler - if(endpoints[n].func) endpoints[n].func(endpoints[n]); + if(endpoints[n].func) endpoints[n].func(); } if(USB->ISTR & USB_ISTR_WKUP){ // wakeup DBG("USB_ISTR_WKUP"); @@ -380,6 +344,7 @@ void USB_IRQ(){ #else CNTR &= ~(USB_CNTR_FSUSP | USB_CNTR_LPMODE | USB_CNTR_WKUPM); #endif + USB->ISTR = ~USB_ISTR_WKUP; } if(USB->ISTR & USB_ISTR_SUSP){ // suspend -> still no connection, may sleep DBG("USB_ISTR_SUSP"); @@ -390,14 +355,13 @@ void USB_IRQ(){ CNTR |= USB_CNTR_FSUSP | USB_CNTR_LPMODE | USB_CNTR_WKUPM; #endif CNTR &= ~(USB_CNTR_SUSPM); + USB->ISTR = ~USB_ISTR_SUSP; } - USB->ISTR = 0; // clear all flags USB->CNTR = CNTR; // rewoke interrupts } // here we suppose that all PIN settings done in hw_setup earlier void USB_setup(){ - DBG(">\n>\n>\nUSB_setup"); #if defined STM32F3 NVIC_DisableIRQ(USB_LP_IRQn); // remap USB LP & Wakeup interrupts to 75 and 76 - works only on pure F303 @@ -437,7 +401,6 @@ void USB_setup(){ USB->BCDR |= USB_BCDR_DPPU; NVIC_EnableIRQ(USB_IRQn); #endif - DBG("USB ready"); } diff --git a/F1:F103/USB_NEW_concept/usb_lib.h b/F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_lib.h similarity index 95% rename from F1:F103/USB_NEW_concept/usb_lib.h rename to F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_lib.h index 9fa7897..86ecc50 100644 --- a/F1:F103/USB_NEW_concept/usb_lib.h +++ b/F1:F103/USB_New_concept/USB_NEW_concept_HID/usb_lib.h @@ -195,6 +195,7 @@ typedef struct{ #define USB_DT_DEVICE_SIZE 18 #define USB_DT_CONFIG_SIZE 9 #define USB_DT_INTERFACE_SIZE 9 +#define USB_DT_HID_SIZE 9 #define USB_DT_ENDPOINT_SIZE 7 #define USB_DT_QUALIFIER_SIZE 10 @@ -214,38 +215,31 @@ typedef struct{ #define REQ_TYPE_VENDOR 2 #define REQ_TYPE_RESERVED 3 -/* -// deprecated defines: -#define STANDARD_DEVICE_REQUEST_TYPE 0 -#define STANDARD_INTERFACE_REQUEST_TYPE 1 -#define STANDARD_ENDPOINT_REQUEST_TYPE 2 -#define STANDARD_OTHER_REQUEST_TYPE 3 -#define VENDOR_REQUEST_TYPE 0x40 -#define CONTROL_REQUEST_TYPE 0x21 -*/ -// bRequest, standard; for bmRequestType == 0x80 +//#define VENDOR_REQUEST 0x01 + +// standard device requests #define GET_STATUS 0x00 -#define GET_DESCRIPTOR 0x06 -#define GET_CONFIGURATION 0x08 -// for bmRequestType == 0 #define CLEAR_FEATURE 0x01 #define SET_FEATURE 0x03 #define SET_ADDRESS 0x05 +#define GET_DESCRIPTOR 0x06 #define SET_DESCRIPTOR 0x07 +#define GET_CONFIGURATION 0x08 #define SET_CONFIGURATION 0x09 -// for bmRequestType == 0x81, 1 or 0xB2 +// and some standard interface requests #define GET_INTERFACE 0x0A #define SET_INTERFACE 0x0B +// and some standard endpoint requests #define SYNC_FRAME 0x0C -#define VENDOR_REQUEST 0x01 // Types of descriptors #define DEVICE_DESCRIPTOR 0x01 #define CONFIGURATION_DESCRIPTOR 0x02 #define STRING_DESCRIPTOR 0x03 #define DEVICE_QUALIFIER_DESCRIPTOR 0x06 -#define HID_REPORT_DESCRIPTOR 0x2200 +#define DEBUG_DESCRIPTOR 0x0a +#define HID_REPORT_DESCRIPTOR 0x22 // EP types for EP_init #define EP_TYPE_BULK 0x00 diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/Makefile b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/Makefile new file mode 100644 index 0000000..32e070d --- /dev/null +++ b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/Makefile @@ -0,0 +1,9 @@ +BINARY := someusb +# MCU code +MCU ?= F103x6 +# change this linking script depending on particular MCU model, +LDSCRIPT ?= stm32f103x6.ld +DEFINES := -DSTM32F10X_LD + +include ../makefile.f1 +include ../../makefile.stm32 diff --git a/F1:F103/USB_NEW_concept/hardware.c b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/hardware.c similarity index 100% rename from F1:F103/USB_NEW_concept/hardware.c rename to F1:F103/USB_New_concept/USB_NEW_concept_PL2303/hardware.c diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/hardware.h b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/hardware.h new file mode 100644 index 0000000..e7bfb32 --- /dev/null +++ b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/hardware.h @@ -0,0 +1,37 @@ +/* + * Copyright 2024 Edward V. Emelianov . + * + * 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 . + */ + +#pragma once + +#include "stm32f1.h" + +// LED0 - PC13 (bluepill), blinking each second +#define LED0_port GPIOC +#define LED0_pin (1<<13) + +// USB pullup (not present in bluepill, should be soldered) - PA15 +#define USBPU_port GPIOA +#define USBPU_pin (1<<15) +#define USBPU_ON() pin_set(USBPU_port, USBPU_pin) +#define USBPU_OFF() pin_clear(USBPU_port, USBPU_pin) + +#define LED_blink(x) pin_toggle(x ## _port, x ## _pin) +#define LED_on(x) pin_clear(x ## _port, x ## _pin) +#define LED_off(x) pin_set(x ## _port, x ## _pin) + +void hw_setup(); +void iwdg_setup(); diff --git a/F1:F103/USB_NEW_concept/main.c b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/main.c similarity index 100% rename from F1:F103/USB_NEW_concept/main.c rename to F1:F103/USB_New_concept/USB_NEW_concept_PL2303/main.c diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/openocd.cfg b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/openocd.cfg new file mode 100644 index 0000000..18ecde1 --- /dev/null +++ b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/openocd.cfg @@ -0,0 +1,4 @@ +set FLASH_SIZE 0x20000 + +source [find interface/stlink-v2-1.cfg] +source [find target/stm32f1x.cfg] diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/ringbuffer.c b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/ringbuffer.c new file mode 100644 index 0000000..b0ffe8e --- /dev/null +++ b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/ringbuffer.c @@ -0,0 +1,166 @@ +/* + * Copyright 2023 Edward V. Emelianov . + * + * 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 . + */ + +#include "ringbuffer.h" + +static int datalen(ringbuffer *b){ + if(b->tail >= b->head) return (b->tail - b->head); + else return (b->length - b->head + b->tail); +} + +// stored data length +int RB_datalen(ringbuffer *b){ + if(b->busy) return -1; + b->busy = 1; + int l = datalen(b); + b->busy = 0; + return l; +} + +static int hasbyte(ringbuffer *b, uint8_t byte){ + if(b->head == b->tail) return -1; // no data in buffer + int startidx = b->head; + if(b->head > b->tail){ // + for(int found = b->head; found < b->length; ++found) + if(b->data[found] == byte) return found; + startidx = 0; + } + for(int found = startidx; found < b->tail; ++found) + if(b->data[found] == byte) return found; + return -1; +} + +/** + * @brief RB_hasbyte - check if buffer has given byte stored + * @param b - buffer + * @param byte - byte to find + * @return index if found, -1 if none or busy + */ +int RB_hasbyte(ringbuffer *b, uint8_t byte){ + if(b->busy) return -1; + b->busy = 1; + int ret = hasbyte(b, byte); + b->busy = 0; + return ret; +} + +// poor memcpy +static void mcpy(uint8_t *targ, const uint8_t *src, int l){ + while(l--) *targ++ = *src++; +} + +// increment head or tail +TRUE_INLINE void incr(ringbuffer *b, volatile int *what, int n){ + *what += n; + if(*what >= b->length) *what -= b->length; +} + +static int read(ringbuffer *b, uint8_t *s, int len){ + int l = datalen(b); + if(!l) return 0; + if(l > len) l = len; + int _1st = b->length - b->head; + if(_1st > l) _1st = l; + if(_1st > len) _1st = len; + mcpy(s, b->data + b->head, _1st); + if(_1st < len && l > _1st){ + mcpy(s+_1st, b->data, l - _1st); + incr(b, &b->head, l); + return l; + } + incr(b, &b->head, _1st); + return _1st; +} + +/** + * @brief RB_read - read data from ringbuffer + * @param b - buffer + * @param s - array to write data + * @param len - max len of `s` + * @return bytes read or -1 if busy + */ +int RB_read(ringbuffer *b, uint8_t *s, int len){ + if(b->busy) return -1; + b->busy = 1; + int r = read(b, s, len); + b->busy = 0; + return r; +} + +static int readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len){ + int idx = hasbyte(b, byte); + if(idx < 0) return 0; + int partlen = idx + 1 - b->head; + // now calculate length of new data portion + if(idx < b->head) partlen += b->length; + if(partlen > len) return -read(b, s, len); + return read(b, s, partlen); +} + +/** + * @brief RB_readto fill array `s` with data until byte `byte` (with it) + * @param b - ringbuffer + * @param byte - check byte + * @param s - buffer to write data + * @param len - length of `s` + * @return amount of bytes written (negative, if lenbusy) return -1; + b->busy = 1; + int n = readto(b, byte, s, len); + b->busy = 0; + return n; +} + +static int write(ringbuffer *b, const uint8_t *str, int l){ + int r = b->length - 1 - datalen(b); // rest length + if(l > r || !l) return 0; + int _1st = b->length - b->tail; + if(_1st > l) _1st = l; + mcpy(b->data + b->tail, str, _1st); + if(_1st < l){ // add another piece from start + mcpy(b->data, str+_1st, l-_1st); + } + incr(b, &b->tail, l); + return l; +} + +/** + * @brief RB_write - write some data to ringbuffer + * @param b - buffer + * @param str - data + * @param l - length + * @return amount of bytes written or -1 if busy + */ +int RB_write(ringbuffer *b, const uint8_t *str, int l){ + if(b->busy) return -1; + b->busy = 1; + int w = write(b, str, l); + b->busy = 0; + return w; +} + +// just delete all information in buffer `b` +int RB_clearbuf(ringbuffer *b){ + if(b->busy) return -1; + b->busy = 1; + b->head = 0; + b->tail = 0; + b->busy = 0; + return 1; +} diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/ringbuffer.h b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/ringbuffer.h new file mode 100644 index 0000000..ed2cf95 --- /dev/null +++ b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/ringbuffer.h @@ -0,0 +1,41 @@ +/* + * Copyright 2023 Edward V. Emelianov . + * + * 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 . + */ + +#pragma once + +#if defined STM32F0 +#include +#elif defined STM32F1 +#include +#elif defined STM32F3 +#include +#endif + +typedef struct{ + uint8_t *data; // data buffer + const int length; // its length + int head; // head index + int tail; // tail index + volatile int busy; // == TRUE if buffer is busy now +} ringbuffer; + +int RB_read(ringbuffer *b, uint8_t *s, int len); +int RB_readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len); +int RB_hasbyte(ringbuffer *b, uint8_t byte); +int RB_write(ringbuffer *b, const uint8_t *str, int l); +int RB_datalen(ringbuffer *b); +int RB_clearbuf(ringbuffer *b); diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/someusb.bin b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/someusb.bin new file mode 100755 index 0000000000000000000000000000000000000000..957f65496d3fb80da62ceb8a8051f046ef62bcf7 GIT binary patch literal 3912 zcmd58e^gV~`MdAEKnPTVz#0PTOM)7Sc0sx`k8b7h2(OSJSkTSkwmu+sPsoH~yLM}P zh=P{d^@!4TMcg@PyVm|V6N0+6+Qs6wyQ7J zobTOxzk9#m-~GM|cHk#dK!1jSe)MwypZn1>6eyaG-!OcU=JPzhYW;`gFQ?tgd^!HB z`24@&)7{2{0ZnlBiuPcRRGH^Bo@~~Km}TsEC+F0dua|0^V~=<(?3pUwq$^Kymo$bI z|FI<> zsCOULp!HPF`=&#a&|Y#D7F1vH>-AB;+c5cCw{WGz^0o%Xvl^^=A+R+jtPvdSIG3_j z<#owXsKvciepmGs$jDmBMPU^?Db!Y9DP>_&SXHLkoz+(amPGx6ZoEqelgETt{EU

5>f;PgzX^S*y}ZNSdML|h^w#>e4E#X% z%~K0Kbv`4PHM-6>-_5G&Yz{#gCG23{m&DOD}GCg@-W}x-WmKZbupHYz|xMKd*o3(y$CC>djBG~-%kRs)Hoo0zx;?s3;u%8cC$I@Jb=vx|_Te_d;K%eSar38gi$4#ErgMEsr(iR&leOlYg+tgO} zmw|#oVg*~LwvX@B_Bt&)-a;F94eBLZ^F4Vj6DhzIRT$H%_{Z7t&7?@<(zv20#RVFZ zs)a`aT*dqtlp!7el-zoh=D;mo-$g%f$DA}sm=UGL1>I7|z_K%&rMWBTRl6i%u{|i{ zzYr*wEK+>>_>KMJ9J4F1*H!TPZ==QO%xQK2e(na@9gAd030|e$mu~6?P7sR4 zbP&5T4P=GRVLpA~GOK21BN+F0RKJC0*Tur6)T>K(izx?X9h91!o@;l~-h~>6uI>e`s&g_Vcrp#97F;yW_ z;0?i&&d|09qs}8_QT3IPY*UDOK0dvF=8?!MwC7Vhw?`;`&rC~%*if2tH1bMf3`d^T z-skz{nFX^k+Kg(*o;4@qe}0B+$6&Gp)Gj}3`1Gb3x-L5~ z9Dz@E?>caVa&^ubN^+P(dPijl9PP2914CVf3gfT`8CzXmjgb^^L9iNRySrA-kHC`R z*t`RjDhbcdIgk{+i1xm5|*!=w6lEXcDDmpizLCy^6_b5hU(t${MRM49ljf(UVc$qQ272OsuOXTC3_HW zx}!Mu_g^2@@(WYtGauiHTXlR#Fdpad-j=bTe+*#__Gw)&>*1a=r0s6Y*}PV6iC`<{ zbsn>_3u|9>3|0{f>s~8|6a4^y5$L{pke#EGo_ohAy(AtE=H-4X_hL@n+^pPA(SFW8 zbS}3;+#h76I~31gnna54a{a}Wr4h$bF-ap|zZUKgQ_dDBsV=gdxH2{3c~WFFQhhBv zt~4pEYg`^zdPL^jxU$=PMOJCe;ptaB82W%IO_H7$e-ms~Ou3MI%)}3Mqa>rWN$HeK zxi{x>+5Vs`6)85?vcbx^^GqmV-4T(~$i3IX-6Aql;Zt}EWH$^Ex*>;zI;Sohf_$nwxf2Sm zhi~n^H(0Hbl&q?xs8Rn{jqiUW3hCFwRta-U`lH5o$EUNgBjKz+<^11Ji+r=rSMx<@o;At@ThFYPf2zSbol_{)bp#|OwRvm#ziZxv(y zr8$zBc8IMqkE^?PkkH_q!oKLorDus*z;K8Hz<^6Jv?W;8>^B zeGJH}fzGY5M`zPfj9tbN<*5EPvrL}Wp$t+qH2Jf3(!-3fN-voj1WJR2$++;hBh)}QzOz?>2|5A;)2$?v$k?|m08x;pTKwF8I0k&+@Zf!j-*$d)(`K>t z{3$K}7)0aC)5giHd!$*>_+9m`KSzmyjNM;WA2N)Sv_qVS zrnD$w_KgE`A~<3SO#0g&eb-dZyd0k%oM9!f_J|FQYtP>nO(t)z&cv>A#|>tGeA;m% z1LyV|t@Pd+v3~LhKm^be!8itE^gSiy5P*N+JU<5X{Q`I|z(@r8#>z*~>?LJ@2Lwrjczv+Rt4I6*NKUBYof1ss>_qA;N5z@>iMl=|NN0L|@u!Lc8mBK6p zLcqT?1v?oV2jG%*n^^;pWF5nx=aO|DbbvIhFEP~R1j12-{RoDnoBSx#EOrglf(T3S zyBbzP5iEr?)`<@z3Wc!vGyChI4K_eM_<)B}Xn~FJ0AgBj?E|`JV%LKg|3AghZNhUc g$e|4$1ddJNs4g%}CF+5GeGD?8lh6Eo + + + + + EnvironmentId + {7bd84e39-ca37-46d3-be9d-99ebea85bc0d} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + KOI8-R + false + 4 + false + 0 + 80 + true + true + 1 + 0 + false + true + false + 0 + true + true + 0 + 8 + true + false + 1 + true + false + true + *.md, *.MD, Makefile + false + true + true + + + + ProjectExplorer.Project.PluginSettings + + + true + false + true + true + true + true + + false + + + 0 + true + + true + true + Builtin.DefaultTidyAndClazy + 8 + true + + + + true + + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + Desktop + {65a14f9e-e008-4c1b-89df-4eaa4774b6e3} + 0 + 0 + 0 + + + + + all + + true + GenericProjectManager.GenericMakeStep + + 1 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + + clean + + true + GenericProjectManager.GenericMakeStep + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Default + GenericProjectManager.GenericBuildConfiguration + + 1 + + + 0 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + true + 0 + true + + + 2 + + false + -e cpu-cycles --call-graph dwarf,4096 -F 250 + + ProjectExplorer.CustomExecutableRunConfiguration + + false + true + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/someusb.cxxflags b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/someusb.cxxflags new file mode 100644 index 0000000..6435dfc --- /dev/null +++ b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/someusb.cxxflags @@ -0,0 +1 @@ +-std=c++17 \ No newline at end of file diff --git a/F1:F103/USB_NEW_concept/someusb.files b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/someusb.files similarity index 100% rename from F1:F103/USB_NEW_concept/someusb.files rename to F1:F103/USB_New_concept/USB_NEW_concept_PL2303/someusb.files diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/someusb.includes b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/someusb.includes new file mode 100644 index 0000000..06d1130 --- /dev/null +++ b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/someusb.includes @@ -0,0 +1,6 @@ +. +../inc +../inc/Fx +../inc/cm +../inc/ld +../inc/startup diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usart.c b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usart.c new file mode 100644 index 0000000..fa97a75 --- /dev/null +++ b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usart.c @@ -0,0 +1,122 @@ +/* + * usart.c + * + * Copyright 2018 Edward V. Emelianoff + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include + +#include "stm32f1.h" +#include "usart.h" +#include "ringbuffer.h" + +extern volatile uint32_t Tms; +static uint8_t buf[UARTBUFSZO], txbuf[UARTBUFSZO]; +static ringbuffer ringbuf = {.data = buf, .length = UARTBUFSZO}; + +static volatile int usart_txrdy = 1; // transmission done + +// transmit current tbuf +void usart_transmit(){ + if(RB_hasbyte(&ringbuf, '\n') < 0 || !usart_txrdy) return; + int L = 0, l = 0; + do{ + l = RB_readto(&ringbuf, '\n', txbuf + L, UARTBUFSZO - L); + if(l > 0) L += l; + }while(l > 0 && L < UARTBUFSZO); + if(L < 1) return; + usart_txrdy = 0; + if(L < UARTBUFSZO-1){ + txbuf[L++] = '$'; txbuf[L++] = '\n'; + } + DMA1_Channel4->CCR &= ~DMA_CCR_EN; + DMA1_Channel4->CMAR = (uint32_t) txbuf; // mem + DMA1_Channel4->CNDTR = L; + DMA1_Channel4->CCR |= DMA_CCR_EN; +} + +void usart_putchar(const char ch){ + RB_write(&ringbuf, (const uint8_t*)&ch, 1); +} + +void usart_send(const char *str){ + int l = strlen(str); + RB_write(&ringbuf, (const uint8_t*)str, l); +} + +/* + * USART speed: baudrate = Fck/(USARTDIV) + * USARTDIV stored in USART->BRR + * + * for 72MHz USARTDIV=72000/f(kboud); so for 115200 USARTDIV=72000/115.2=625 -> BRR=0x271 + * 9600: BRR = 7500 (0x1D4C) + */ + +void usart_setup(){ + uint32_t tmout = 16000000; + // PA9 - Tx, PA10 - Rx + RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_USART1EN | RCC_APB2ENR_AFIOEN; + RCC->AHBENR |= RCC_AHBENR_DMA1EN; + GPIOA->CRH |= CRH(9, CNF_AFPP|MODE_NORMAL) | CRH(10, CNF_FLINPUT|MODE_INPUT); + + // USART1 Tx DMA - Channel4 (Rx - channel 5) + DMA1_Channel4->CPAR = (uint32_t) &USART1->DR; // periph + DMA1_Channel4->CCR |= DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE; // 8bit, mem++, mem->per, transcompl irq + // Tx CNDTR set @ each transmission due to data size + NVIC_SetPriority(DMA1_Channel4_IRQn, 3); + NVIC_EnableIRQ(DMA1_Channel4_IRQn); + NVIC_SetPriority(USART1_IRQn, 0); + // setup usart1 + USART1->BRR = 72000000 / 4000000; + USART1->CR1 = USART_CR1_TE | USART_CR1_UE; // 1start,8data,nstop; enable Rx,Tx,USART + while(!(USART1->SR & USART_SR_TC)){if(--tmout == 0) break;} // polling idle frame Transmission + USART1->SR = 0; // clear flags + USART1->CR1 |= USART_CR1_RXNEIE; // allow Rx IRQ + USART1->CR3 = USART_CR3_DMAT; // enable DMA Tx +} + + +void dma1_channel4_isr(){ + if(DMA1->ISR & DMA_ISR_TCIF4){ // Tx + DMA1->IFCR = DMA_IFCR_CTCIF4; // clear TC flag + usart_txrdy = 1; + } +} + + + +char *uhex2str(uint32_t val){ + static char abuf[12] = "0x"; + int npos = 2; + uint8_t *ptr = (uint8_t*)&val + 3; + int8_t i, j, z=1; + for(i = 0; i < 4; ++i, --ptr){ + if(*ptr == 0){ // omit leading zeros + if(i == 3) z = 0; + if(z) continue; + } + else z = 0; + for(j = 1; j > -1; --j){ + uint8_t half = (*ptr >> (4*j)) & 0x0f; + if(half < 10) abuf[npos++] = half + '0'; + else abuf[npos++] = half - 10 + 'a'; + } + } + abuf[npos] = 0; + return abuf; +} diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usart.h b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usart.h new file mode 100644 index 0000000..c362186 --- /dev/null +++ b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usart.h @@ -0,0 +1,45 @@ +/* + * usart.h + * + * Copyright 2018 Edward V. Emelianoff + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#pragma once + +#include + +#define UARTBUFSZO (2048) + +// macro for static strings +#define USEND(str) usart_send(str) + +#ifdef EBUG +#define STR_HELPER(s) #s +#define STR(s) STR_HELPER(s) +#define DBG(str) do{usart_send(__FILE__ " (L" STR(__LINE__) "): " str); usart_putchar('\n');}while(0) +#define DBGs(str) do{usart_send(str); usart_putchar('\n');}while(0) +#else +#define DBG(s) +#define DBGs(s) +#endif + +void usart_transmit(); +void usart_setup(); +void usart_send(const char *str); +void usart_putchar(const char ch); +char *uhex2str(uint32_t val); diff --git a/F1:F103/USB_NEW_concept/usb_descr.c b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_descr.c similarity index 96% rename from F1:F103/USB_NEW_concept/usb_descr.c rename to F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_descr.c index cb55877..ea253f4 100644 --- a/F1:F103/USB_NEW_concept/usb_descr.c +++ b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_descr.c @@ -22,7 +22,7 @@ #define L16(x) (x & 0xff) #define H16(x) (x >> 8) -const uint8_t USB_DeviceDescriptor[] = { +static const uint8_t USB_DeviceDescriptor[] = { USB_DT_DEVICE_SIZE, // bLength USB_DT_DEVICE, // bDescriptorType L16(bcdUSB), // bcdUSB_L @@ -43,7 +43,7 @@ const uint8_t USB_DeviceDescriptor[] = { bNumConfigurations // bNumConfigurations }; -const uint8_t USB_DeviceQualifierDescriptor[] = { +static const uint8_t USB_DeviceQualifierDescriptor[] = { USB_DT_QUALIFIER_SIZE, //bLength USB_DT_QUALIFIER, // bDescriptorType L16(bcdUSB), // bcdUSB_L @@ -58,7 +58,7 @@ const uint8_t USB_DeviceQualifierDescriptor[] = { #define wTotalLength (USB_DT_CONFIG_SIZE + (bNumInterfaces * USB_DT_INTERFACE_SIZE) + (bTotNumEndpoints * USB_DT_ENDPOINT_SIZE)) -const uint8_t USB_ConfigDescriptor[] = { +static const uint8_t USB_ConfigDescriptor[] = { // Configuration Descriptor USB_DT_CONFIG_SIZE, // bLength: Configuration Descriptor size USB_DT_CONFIG, // bDescriptorType: Configuration @@ -123,7 +123,7 @@ static const void* const StringDescriptor[iDESCR_AMOUNT] = { [iINTERFACE_DESCR1] = &ID }; -void wr0(const uint8_t *buf, uint16_t size, uint16_t askedsize){ +static void wr0(const uint8_t *buf, uint16_t size, uint16_t askedsize){ if(askedsize < size) size = askedsize; // shortened request if(size < USB_EP0BUFSZ){ //DBG("short wr0"); diff --git a/F1:F103/USB_NEW_concept/usb_descr.h b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_descr.h similarity index 100% rename from F1:F103/USB_NEW_concept/usb_descr.h rename to F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_descr.h diff --git a/F1:F103/USB_NEW_concept/usb_dev.c b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_dev.c similarity index 93% rename from F1:F103/USB_NEW_concept/usb_dev.c rename to F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_dev.c index 2428257..606b8f8 100644 --- a/F1:F103/USB_NEW_concept/usb_dev.c +++ b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_dev.c @@ -144,9 +144,12 @@ void set_configuration(){ void usb_class_request(config_pack_t *req, uint8_t *data, uint16_t datalen){ uint8_t recipient = REQUEST_RECIPIENT(req->bmRequestType); uint8_t dev2host = (req->bmRequestType & 0x80) ? 1 : 0; + DBG("usb_class_request"); + DBGs(uhex2str(req->bRequest)); switch(recipient){ case REQ_RECIPIENT_INTERFACE: switch(req->bRequest){ + case 0x32: // non-standard but used for same purpose in PL2303 case SET_LINE_CODING: DBG("SET_LINE_CODING"); if(!data || !datalen) break; // wait for data @@ -154,6 +157,7 @@ void usb_class_request(config_pack_t *req, uint8_t *data, uint16_t datalen){ linecoding_handler((usb_LineCoding*)data); CDCready = 1; break; + case 0x33: // -//- case GET_LINE_CODING: DBG("GET_LINE_CODING"); EP_WriteIRQ(0, (uint8_t*)&lineCoding, sizeof(lineCoding)); @@ -167,7 +171,7 @@ void usb_class_request(config_pack_t *req, uint8_t *data, uint16_t datalen){ DBG("SEND_BREAK"); CDCready = 0; break_handler(); - break; + break; default: DBG("Wrong"); DBGs(uhex2str(req->bRequest)); @@ -181,41 +185,28 @@ void usb_class_request(config_pack_t *req, uint8_t *data, uint16_t datalen){ DBGs(uhex2str(req->bRequest)); if(dev2host) EP_WriteIRQ(0, NULL, 0); } + if(!dev2host) EP_WriteIRQ(0, NULL, 0); } -#if 0 - pl2303_vendor_read(serial, 0x8484, buf); - pl2303_vendor_write(serial, 0x0404, 0); - pl2303_vendor_read(serial, 0x8484, buf); - pl2303_vendor_read(serial, 0x8383, buf); - pl2303_vendor_read(serial, 0x8484, buf); - pl2303_vendor_write(serial, 0x0404, 1); - pl2303_vendor_read(serial, 0x8484, buf); - pl2303_vendor_read(serial, 0x8383, buf); - pl2303_vendor_write(serial, 0, 1); - pl2303_vendor_write(serial, 1, 0); - if (spriv->quirks & PL2303_QUIRK_LEGACY) - pl2303_vendor_write(serial, 2, 0x24); - else - pl2303_vendor_write(serial, 2, 0x44); -#endif - // Vendor request for PL2303 void usb_vendor_request(config_pack_t *req, uint8_t _U_ *data, uint16_t _U_ datalen){ - uint8_t c; + //uint8_t buf[8] = {0}; + //uint16_t l = req->wLength; + //if(l > 8) l = 8; + uint8_t c = 0; if(req->bmRequestType & 0x80){ // read switch(req->wValue){ case 0x8484: - c = 2; + c = 0x02; break; case 0x0080: - c = 1; + c = 0x01; break; case 0x8686: c = 0xaa; break; - default: - c = 0; + default: // c=0 + break; } EP_WriteIRQ(0, &c, 1); DBG("Vendor read"); diff --git a/F1:F103/USB_NEW_concept/usb_dev.h b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_dev.h similarity index 100% rename from F1:F103/USB_NEW_concept/usb_dev.h rename to F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_dev.h diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_lib.c b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_lib.c new file mode 100644 index 0000000..9db1799 --- /dev/null +++ b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_lib.c @@ -0,0 +1,413 @@ +/* + * Copyright 2024 Edward V. Emelianov . + * + * 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 . + */ +#include + +#include "usart.h" +#include "usb_lib.h" +#include "usb_descr.h" +#include "usb_dev.h" + +/* +#undef DBG +#define DBG(x) +#undef DBGs +#define DBGs(x) +*/ + +static ep_t endpoints[STM32ENDPOINTS]; + +static uint16_t USB_Addr = 0; +static uint8_t setupdatabuf[EP0DATABUF_SIZE]; +static config_pack_t *setup_packet = (config_pack_t*) setupdatabuf; +volatile uint8_t usbON = 0; // device is configured and active + +static uint16_t configuration = 0; // reply for GET_CONFIGURATION (==1 if configured) +static inline void std_d2h_req(){ + uint16_t st = 0; + switch(setup_packet->bRequest){ + case GET_DESCRIPTOR: + DBG("GET_DESCRIPTOR"); + get_descriptor(setup_packet); + break; + case GET_STATUS: + DBG("GET_STATUS"); + EP_WriteIRQ(0, (uint8_t *)&st, 2); // send status: Bus Powered + break; + case GET_CONFIGURATION: + DBG("GET_CONFIGURATION"); + EP_WriteIRQ(0, (uint8_t*)&configuration, 1); + break; + default: + DBG("Wrong"); + DBGs(uhex2str(setup_packet->bRequest)); + break; + } +} + +static inline void std_h2d_req(){ + switch(setup_packet->bRequest){ + case SET_ADDRESS: + DBG("SET_ADDRESS"); + // new address will be assigned later - after acknowlegement or request to host + USB_Addr = setup_packet->wValue; + DBGs(uhex2str(USB_Addr)); + break; + case SET_CONFIGURATION: + DBG("SET_CONFIGURATION"); + // Now device configured + configuration = setup_packet->wValue; + set_configuration(); + usbON = 1; + break; + default: + DBG("Wrong"); + DBGs(uhex2str(setup_packet->bRequest)); + break; + } +} + +void WEAK usb_standard_request(){ + uint8_t recipient = REQUEST_RECIPIENT(setup_packet->bmRequestType); + uint8_t dev2host = (setup_packet->bmRequestType & 0x80) ? 1 : 0; + switch(recipient){ + case REQ_RECIPIENT_DEVICE: + DBG("REQ_RECIPIENT_DEVICE"); + if(dev2host){ + std_d2h_req(); + }else{ + std_h2d_req(); + //EP_WriteIRQ(0, NULL, 0); + } + break; + case REQ_RECIPIENT_INTERFACE: + DBG("REQ_RECIPIENT_INTERFACE"); + if(dev2host && setup_packet->bRequest == GET_DESCRIPTOR){ + get_descriptor(setup_packet); + }//else EP_WriteIRQ(0, NULL, 0); + break; + case REQ_RECIPIENT_ENDPOINT: + DBG("REQ_RECIPIENT_ENDPOINT"); + if(setup_packet->bRequest == CLEAR_FEATURE){ + //EP_WriteIRQ(0, NULL, 0); + }else{ + DBG("Wrong"); + } + break; + default: + DBG("Wrong"); + DBGs(uhex2str(recipient)); + break; + } + if(!dev2host) EP_WriteIRQ(0, NULL, 0); +} + +void WEAK usb_class_request(config_pack_t *req, uint8_t _U_ *data, uint16_t _U_ datalen){ + DBG("REQ_TYPE_CLASS"); + switch(req->bRequest){ + case GET_INTERFACE: + DBG("GI"); + break; + case SET_CONFIGURATION: // set featuring by req->wValue + DBG("SC"); + break; + default: + DBG("Wrong"); + DBGs(uhex2str(req->bmRequestType)); + DBGs(uhex2str(req->bRequest)); + DBGs(uhex2str(req->wIndex)); + DBGs(uhex2str(req->wLength)); + DBGs(uhex2str(req->wValue)); + } + if(0 == (setup_packet->bmRequestType & 0x80)) // host2dev + EP_WriteIRQ(0, NULL, 0); +} + +void WEAK usb_vendor_request(config_pack_t _U_ *packet, uint8_t _U_ *data, uint16_t _U_ datalen){ + DBG("vendor"); + if(0 == (setup_packet->bmRequestType & 0x80)) // host2dev + EP_WriteIRQ(0, NULL, 0); +} + +/* +bmRequestType: 76543210 +7 direction: 0 - host->device, 1 - device->host +65 type: 0 - standard, 1 - class, 2 - vendor +4..0 getter: 0 - device, 1 - interface, 2 - endpoint, 3 - other +*/ +/** + * Endpoint0 (control) handler + */ +static void EP0_Handler(){ + uint8_t ep0dbuflen = 0; + uint8_t ep0databuf[EP0DATABUF_SIZE]; + uint16_t epstatus = USB->EPnR[0]; // EP0R on input -> return this value after modifications + //DBG("EP0_Handler"); + // check direction + if(USB->ISTR & USB_ISTR_DIR){ // OUT interrupt - receive data, CTR_RX==1 (if CTR_TX == 1 - two pending transactions: receive following by transmit) + if(epstatus & USB_EPnR_SETUP){ // setup packet -> copy data to conf_pack + //DBG("USB_EPnR_SETUP"); + EP_Read(0, setupdatabuf); + // interrupt handler will be called later + }else if(epstatus & USB_EPnR_CTR_RX){ // data packet -> push received data to ep0databuf + //if(endpoints[0].rx_cnt){ DBG("data");} + ep0dbuflen = EP_Read(0, ep0databuf); + } + } + int rxflag = RX_FLAG(epstatus); + if(rxflag){ + uint8_t reqtype = REQUEST_TYPE(setup_packet->bmRequestType); + switch(reqtype){ + case REQ_TYPE_STANDARD: + DBG("REQ_TYPE_STANDARD"); + usb_standard_request(); + break; + case REQ_TYPE_CLASS: + DBG("REQ_TYPE_CLASS"); + usb_class_request(setup_packet, ep0databuf, ep0dbuflen); + break; + case REQ_TYPE_VENDOR: + DBG("REQ_TYPE_VENDOR"); + usb_vendor_request(setup_packet, ep0databuf, ep0dbuflen); + break; + default: + DBG("Wrong"); + DBGs(uhex2str(reqtype)); + EP_WriteIRQ(0, NULL, 0); + break; + } + } + if(TX_FLAG(epstatus)){ + // now we can change address after enumeration + if ((USB->DADDR & USB_DADDR_ADD) != USB_Addr){ + USB->DADDR = USB_DADDR_EF | USB_Addr; + usbON = 0; + DBG("Enum"); + DBGs(uhex2str(USB_Addr)); + } + } + epstatus = KEEP_DTOG(USB->EPnR[0]); + if(rxflag) epstatus ^= USB_EPnR_STAT_TX; // start ZLP or data transmission + else epstatus &= ~USB_EPnR_STAT_TX; // or leave unchanged + // keep DTOGs, clear CTR_RX,TX, set RX VALID + USB->EPnR[0] = (epstatus & ~(USB_EPnR_CTR_RX|USB_EPnR_CTR_TX)) ^ USB_EPnR_STAT_RX; +} + +/** + * Write data to EP buffer (called from IRQ handler) + * @param number - EP number + * @param *buf - array with data + * @param size - its size + */ +void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size){ + if(size > endpoints[number].txbufsz) size = endpoints[number].txbufsz; + uint16_t N2 = (size + 1) >> 1; + // the buffer is 16-bit, so we should copy data as it would be uint16_t + uint16_t *buf16 = (uint16_t *)buf; +#if defined USB1_16 + // very bad: what if `size` is odd? + uint32_t *out = (uint32_t *)endpoints[number].tx_buf; + for(int i = 0; i < N2; ++i, ++out){ + *out = buf16[i]; + } +#elif defined USB2_16 + // use memcpy instead? + for(int i = 0; i < N2; i++){ + endpoints[number].tx_buf[i] = buf16[i]; + } +#else +#error "Define USB1_16 or USB2_16" +#endif + USB_BTABLE->EP[number].USB_COUNT_TX = size; +} + +/** + * Write data to EP buffer (called outside IRQ handler) + * @param number - EP number + * @param *buf - array with data + * @param size - its size + */ +void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size){ + EP_WriteIRQ(number, buf, size); + uint16_t epstatus = KEEP_DTOG(USB->EPnR[number]); + // keep DTOGs, clear CTR_TX & set TX VALID to start transmission + USB->EPnR[number] = (epstatus & ~(USB_EPnR_CTR_TX)) ^ USB_EPnR_STAT_TX; +} + +/* + * Copy data from EP buffer into user buffer area + * @param *buf - user array for data + * @return amount of data read + */ +int EP_Read(uint8_t number, uint8_t *buf){ + int sz = endpoints[number].rx_cnt; + if(!sz) return 0; + endpoints[number].rx_cnt = 0; +#if defined USB1_16 + int n = (sz + 1) >> 1; + uint32_t *in = (uint32_t*)endpoints[number].rx_buf; + uint16_t *out = (uint16_t*)buf; + for(int i = 0; i < n; ++i, ++in) + out[i] = *(uint16_t*)in; +#elif defined USB2_16 + // use memcpy instead? + for(int i = 0; i < sz; ++i) + buf[i] = endpoints[number].rx_buf[i]; +#else +#error "Define USB1_16 or USB2_16" +#endif + return sz; +} + + +static uint16_t lastaddr = LASTADDR_DEFAULT; +/** + * Endpoint initialisation + * @param number - EP num (0...7) + * @param type - EP type (EP_TYPE_BULK, EP_TYPE_CONTROL, EP_TYPE_ISO, EP_TYPE_INTERRUPT) + * @param txsz - transmission buffer size @ USB/CAN buffer + * @param rxsz - reception buffer size @ USB/CAN buffer + * @param uint16_t (*func)(ep_t *ep) - EP handler function + * @return 0 if all OK + */ +int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*func)(ep_t ep)){ + if(number >= STM32ENDPOINTS) return 4; // out of configured amount + if(txsz > USB_BTABLE_SIZE || rxsz > USB_BTABLE_SIZE) return 1; // buffer too large + if(lastaddr + txsz + rxsz >= USB_BTABLE_SIZE/ACCESSZ) return 2; // out of btable + USB->EPnR[number] = (type << 9) | (number & USB_EPnR_EA); + USB->EPnR[number] ^= USB_EPnR_STAT_RX | USB_EPnR_STAT_TX_1; + if(rxsz & 1 || rxsz > USB_BTABLE_SIZE) return 3; // wrong rx buffer size + uint16_t countrx = 0; + if(rxsz < 64) countrx = rxsz / 2; + else{ + if(rxsz & 0x1f) return 3; // should be multiple of 32 + countrx = 31 + rxsz / 32; + } + USB_BTABLE->EP[number].USB_ADDR_TX = lastaddr; + endpoints[number].tx_buf = (uint16_t *)(USB_BTABLE_BASE + lastaddr * ACCESSZ); + endpoints[number].txbufsz = txsz; + lastaddr += txsz; + USB_BTABLE->EP[number].USB_COUNT_TX = 0; + USB_BTABLE->EP[number].USB_ADDR_RX = lastaddr; + endpoints[number].rx_buf = (uint8_t *)(USB_BTABLE_BASE + lastaddr * ACCESSZ); + lastaddr += rxsz; + USB_BTABLE->EP[number].USB_COUNT_RX = countrx << 10; + endpoints[number].func = func; + return 0; +} + +// standard IRQ handler +void USB_IRQ(){ + uint32_t CNTR = USB->CNTR; + USB->CNTR = 0; + if(USB->ISTR & USB_ISTR_RESET){ + DBG("USB_ISTR_RESET"); + usbON = 0; + // Reinit registers + CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM | USB_CNTR_SUSPM; + // Endpoint 0 - CONTROL + // ON USB LS size of EP0 may be 8 bytes, but on FS it should be 64 bytes! + lastaddr = LASTADDR_DEFAULT; + // clear address, leave only enable bit + USB->DADDR = USB_DADDR_EF; + USB->ISTR = ~USB_ISTR_RESET; + if(EP_Init(0, EP_TYPE_CONTROL, USB_EP0BUFSZ, USB_EP0BUFSZ, EP0_Handler)){ + DBG("Can't init EP0"); + return; + }; + } + if(USB->ISTR & USB_ISTR_CTR){ + // EP number + uint8_t n = USB->ISTR & USB_ISTR_EPID; + // copy received bytes amount + endpoints[n].rx_cnt = USB_BTABLE->EP[n].USB_COUNT_RX & 0x3FF; // low 10 bits is counter + // call EP handler + if(endpoints[n].func) endpoints[n].func(); + } + if(USB->ISTR & USB_ISTR_WKUP){ // wakeup + DBG("USB_ISTR_WKUP"); +#ifndef STM32F0 + CNTR &= ~(USB_CNTR_FSUSP | USB_CNTR_LP_MODE | USB_CNTR_WKUPM); // clear suspend flags +#else + CNTR &= ~(USB_CNTR_FSUSP | USB_CNTR_LPMODE | USB_CNTR_WKUPM); +#endif + USB->ISTR = ~USB_ISTR_WKUP; + } + if(USB->ISTR & USB_ISTR_SUSP){ // suspend -> still no connection, may sleep + DBG("USB_ISTR_SUSP"); + usbON = 0; +#ifndef STM32F0 + CNTR |= USB_CNTR_FSUSP | USB_CNTR_LP_MODE | USB_CNTR_WKUPM; +#else + CNTR |= USB_CNTR_FSUSP | USB_CNTR_LPMODE | USB_CNTR_WKUPM; +#endif + CNTR &= ~(USB_CNTR_SUSPM); + USB->ISTR = ~USB_ISTR_SUSP; + } + USB->CNTR = CNTR; // rewoke interrupts +} + +// here we suppose that all PIN settings done in hw_setup earlier +void USB_setup(){ +#if defined STM32F3 + NVIC_DisableIRQ(USB_LP_IRQn); + // remap USB LP & Wakeup interrupts to 75 and 76 - works only on pure F303 + RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; // enable tacting of SYSCFG + SYSCFG->CFGR1 |= SYSCFG_CFGR1_USB_IT_RMP; +#elif defined STM32F1 + NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn); + NVIC_DisableIRQ(USB_HP_CAN1_TX_IRQn); +#elif defined STM32F0 + NVIC_DisableIRQ(USB_IRQn); + RCC->APB1ENR |= RCC_APB1ENR_CRSEN; + RCC->CFGR3 &= ~RCC_CFGR3_USBSW; // reset USB + RCC->CR2 |= RCC_CR2_HSI48ON; // turn ON HSI48 + uint32_t tmout = 16000000; + while(!(RCC->CR2 & RCC_CR2_HSI48RDY)){if(--tmout == 0) break;} + FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY; + CRS->CFGR &= ~CRS_CFGR_SYNCSRC; + CRS->CFGR |= CRS_CFGR_SYNCSRC_1; // USB SOF selected as sync source + CRS->CR |= CRS_CR_AUTOTRIMEN; // enable auto trim + CRS->CR |= CRS_CR_CEN; // enable freq counter & block CRS->CFGR as read-only + RCC->CFGR |= RCC_CFGR_SW; +#endif + RCC->APB1ENR |= RCC_APB1ENR_USBEN; + //?? + USB->CNTR = USB_CNTR_FRES; // Force USB Reset + for(uint32_t ctr = 0; ctr < 72000; ++ctr) nop(); // wait >1ms + USB->CNTR = 0; + USB->BTABLE = 0; + USB->DADDR = 0; + USB->ISTR = 0; + USB->CNTR = USB_CNTR_RESETM; // allow only reset interrupts +#if defined STM32F3 + NVIC_EnableIRQ(USB_LP_IRQn); +#elif defined STM32F1 + NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn); +#elif defined STM32F0 + USB->BCDR |= USB_BCDR_DPPU; + NVIC_EnableIRQ(USB_IRQn); +#endif +} + + +#if defined STM32F3 +void usb_lp_isr() __attribute__ ((alias ("USB_IRQ"))); +#elif defined STM32F1 +void usb_lp_can_rx0_isr() __attribute__ ((alias ("USB_IRQ"))); +#elif defined STM32F0 +void usb_isr() __attribute__ ((alias ("USB_IRQ"))); +#endif diff --git a/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_lib.h b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_lib.h new file mode 100644 index 0000000..86ecc50 --- /dev/null +++ b/F1:F103/USB_New_concept/USB_NEW_concept_PL2303/usb_lib.h @@ -0,0 +1,320 @@ +/* + * Copyright 2024 Edward V. Emelianov . + * + * 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 . + */ +#pragma once + +#include +#include + +/****************************************************************** + * Hardware registers etc * + *****************************************************************/ +#if defined STM32F0 +#include +#elif defined STM32F1 +#include +// there's no this define in standard header +#define USB_BASE ((uint32_t)0x40005C00) +#elif defined STM32F3 +#include +#endif + +// max endpoints number +#define STM32ENDPOINTS 8 +/** + * Buffers size definition + **/ + +// F0 - USB2_16; F1 - USB1_16; F3 - 1/2 depending on series +#if !defined USB1_16 && !defined USB2_16 +#if defined STM32F0 +#define USB2_16 +#elif defined STM32F1 +#define USB1_16 +#else +#error "Can't determine USB1_16 or USB2_16, define by hands" +#endif +#endif + +// BTABLE_SIZE FOR STM32F3: +// In STM32F303/302xB/C, 512 bytes SRAM is not shared with CAN. +// In STM32F302x6/x8 and STM32F30xxD/E, 726 bytes dedicated SRAM and 256 bytes shared SRAM with CAN i.e. +// 1Kbytes dedicated SRAM in case CAN is disabled. +// remember, that USB_BTABLE_SIZE will be divided by ACCESSZ, so don't divide it twice for 32-bit addressing + +#ifdef NOCAN +#if defined STM32F0 +#define USB_BTABLE_SIZE 1024 +#elif defined STM32F3 +#define USB_BTABLE_SIZE 512 +#warning "Please, check real buffer size due to docs" +#else +#error "define STM32F0 or STM32F3" +#endif +#else // !NOCAN: F0/F3 with CAN or F1 (can't simultaneously run CAN and USB) +#if defined STM32F0 +#define USB_BTABLE_SIZE 768 +#elif defined STM32F3 +#define USB_BTABLE_SIZE 512 +#warning "Please, check real buffer size due to docs" +#else // STM32F103: 1024 bytes but with 32-bit addressing +#define USB_BTABLE_SIZE 1024 +#endif +#endif // NOCAN + +// first 64 bytes of USB_BTABLE are registers! + +#define USB_BTABLE_BASE 0x40006000 +#define USB ((USB_TypeDef *) USB_BASE) + +#ifdef USB_BTABLE +#undef USB_BTABLE +#endif +#define USB_BTABLE ((USB_BtableDef *)(USB_BTABLE_BASE)) +#define USB_ISTR_EPID 0x0000000F +#define USB_FNR_LSOF_0 0x00000800 +#define USB_FNR_lSOF_1 0x00001000 +#define USB_LPMCSR_BESL_0 0x00000010 +#define USB_LPMCSR_BESL_1 0x00000020 +#define USB_LPMCSR_BESL_2 0x00000040 +#define USB_LPMCSR_BESL_3 0x00000080 +#define USB_EPnR_CTR_RX 0x00008000 +#define USB_EPnR_DTOG_RX 0x00004000 +#define USB_EPnR_STAT_RX 0x00003000 +#define USB_EPnR_STAT_RX_0 0x00001000 +#define USB_EPnR_STAT_RX_1 0x00002000 +#define USB_EPnR_SETUP 0x00000800 +#define USB_EPnR_EP_TYPE 0x00000600 +#define USB_EPnR_EP_TYPE_0 0x00000200 +#define USB_EPnR_EP_TYPE_1 0x00000400 +#define USB_EPnR_EP_KIND 0x00000100 +#define USB_EPnR_CTR_TX 0x00000080 +#define USB_EPnR_DTOG_TX 0x00000040 +#define USB_EPnR_STAT_TX 0x00000030 +#define USB_EPnR_STAT_TX_0 0x00000010 +#define USB_EPnR_STAT_TX_1 0x00000020 +#define USB_EPnR_EA 0x0000000F +#define USB_COUNTn_RX_BLSIZE 0x00008000 +#define USB_COUNTn_NUM_BLOCK 0x00007C00 +#define USB_COUNTn_RX 0x0000003F + +#define USB_TypeDef USB_TypeDef_custom + +typedef struct { + __IO uint32_t EPnR[STM32ENDPOINTS]; + __IO uint32_t RESERVED[STM32ENDPOINTS]; + __IO uint32_t CNTR; + __IO uint32_t ISTR; + __IO uint32_t FNR; + __IO uint32_t DADDR; + __IO uint32_t BTABLE; +#ifdef STM32F0 + __IO uint32_t LPMCSR; + __IO uint32_t BCDR; +#endif +} USB_TypeDef; + +// F303 D/E have 2x16 access scheme +typedef struct{ +#if defined USB2_16 + __IO uint16_t USB_ADDR_TX; + __IO uint16_t USB_COUNT_TX; + __IO uint16_t USB_ADDR_RX; + __IO uint16_t USB_COUNT_RX; +#define ACCESSZ (1) +#define BUFTYPE uint8_t +#elif defined USB1_16 + __IO uint32_t USB_ADDR_TX; + __IO uint32_t USB_COUNT_TX; + __IO uint32_t USB_ADDR_RX; + __IO uint32_t USB_COUNT_RX; +#define ACCESSZ (2) +#define BUFTYPE uint16_t +#else +#error "Define USB1_16 or USB2_16" +#endif +} USB_EPDATA_TypeDef; + + +typedef struct{ + __IO USB_EPDATA_TypeDef EP[STM32ENDPOINTS]; +} USB_BtableDef; + +#define EP0DATABUF_SIZE (64) +#define LASTADDR_DEFAULT (STM32ENDPOINTS * 8) + +/****************************************************************** + * Defines from usb.h * + *****************************************************************/ + +/* + * Device and/or Interface Class codes + */ +#define USB_CLASS_PER_INTERFACE 0 +#define USB_CLASS_AUDIO 1 +#define USB_CLASS_COMM 2 +#define USB_CLASS_HID 3 +#define USB_CLASS_PRINTER 7 +#define USB_CLASS_PTP 6 +#define USB_CLASS_MASS_STORAGE 8 +#define USB_CLASS_HUB 9 +#define USB_CLASS_DATA 10 +#define USB_CLASS_VENDOR_SPEC 0xff + +/* + * Descriptor types + */ +#define USB_DT_DEVICE 0x01 +#define USB_DT_CONFIG 0x02 +#define USB_DT_STRING 0x03 +#define USB_DT_INTERFACE 0x04 +#define USB_DT_ENDPOINT 0x05 +#define USB_DT_QUALIFIER 0x06 + +#define USB_DT_HID 0x21 +#define USB_DT_REPORT 0x22 +#define USB_DT_PHYSICAL 0x23 +#define USB_DT_HUB 0x29 + +/* + * Descriptor sizes per descriptor type + */ +#define USB_DT_DEVICE_SIZE 18 +#define USB_DT_CONFIG_SIZE 9 +#define USB_DT_INTERFACE_SIZE 9 +#define USB_DT_HID_SIZE 9 +#define USB_DT_ENDPOINT_SIZE 7 +#define USB_DT_QUALIFIER_SIZE 10 + + + +// bmRequestType & 0x80 == dev2host (1) or host2dev (0) +// recipient: bmRequestType & 0x1f +#define REQUEST_RECIPIENT(b) (b & 0x1f) +#define REQ_RECIPIENT_DEVICE 0 +#define REQ_RECIPIENT_INTERFACE 1 +#define REQ_RECIPIENT_ENDPOINT 2 +#define REQ_RECIPIENT_OTHER 3 +// type: [bmRequestType & 0x60 >> 5] +#define REQUEST_TYPE(b) ((b&0x60)>>5) +#define REQ_TYPE_STANDARD 0 +#define REQ_TYPE_CLASS 1 +#define REQ_TYPE_VENDOR 2 +#define REQ_TYPE_RESERVED 3 + + +//#define VENDOR_REQUEST 0x01 + +// standard device requests +#define GET_STATUS 0x00 +#define CLEAR_FEATURE 0x01 +#define SET_FEATURE 0x03 +#define SET_ADDRESS 0x05 +#define GET_DESCRIPTOR 0x06 +#define SET_DESCRIPTOR 0x07 +#define GET_CONFIGURATION 0x08 +#define SET_CONFIGURATION 0x09 +// and some standard interface requests +#define GET_INTERFACE 0x0A +#define SET_INTERFACE 0x0B +// and some standard endpoint requests +#define SYNC_FRAME 0x0C + +// Types of descriptors +#define DEVICE_DESCRIPTOR 0x01 +#define CONFIGURATION_DESCRIPTOR 0x02 +#define STRING_DESCRIPTOR 0x03 +#define DEVICE_QUALIFIER_DESCRIPTOR 0x06 +#define DEBUG_DESCRIPTOR 0x0a +#define HID_REPORT_DESCRIPTOR 0x22 + +// EP types for EP_init +#define EP_TYPE_BULK 0x00 +#define EP_TYPE_CONTROL 0x01 +#define EP_TYPE_ISO 0x02 +#define EP_TYPE_INTERRUPT 0x03 + +// EP types for descriptors +#define USB_BM_ATTR_CONTROL 0x00 +#define USB_BM_ATTR_ISO 0x01 +#define USB_BM_ATTR_BULK 0x02 +#define USB_BM_ATTR_INTERRUPT 0x03 + + +/****************************************************************** + * Other stuff * + *****************************************************************/ + +#define RX_FLAG(epstat) (epstat & USB_EPnR_CTR_RX) +#define TX_FLAG(epstat) (epstat & USB_EPnR_CTR_TX) +#define SETUP_FLAG(epstat) (epstat & USB_EPnR_SETUP) + +// EPnR bits manipulation +#define KEEP_DTOG_STAT(EPnR) (EPnR & ~(USB_EPnR_STAT_RX|USB_EPnR_STAT_TX|USB_EPnR_DTOG_RX|USB_EPnR_DTOG_TX)) +#define KEEP_DTOG(EPnR) (EPnR & ~(USB_EPnR_DTOG_RX|USB_EPnR_DTOG_TX)) + +#define LANG_US (uint16_t)0x0409 + +#define _USB_STRING_(name, str) \ +static const struct name \ +{ \ + uint8_t bLength; \ + uint8_t bDescriptorType; \ + uint16_t bString[(sizeof(str) - 2) / 2]; \ + \ +} \ +name = {sizeof(name), 0x03, str} + +#define _USB_LANG_ID_(name, lng_id) \ +static const struct name \ +{ \ + uint8_t bLength; \ + uint8_t bDescriptorType; \ + uint16_t bString; \ + \ +} \ +name = {0x04, 0x03, lng_id} + +// EP0 configuration packet +typedef struct { + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} config_pack_t; + +// endpoints state +typedef struct{ + uint16_t *tx_buf; // transmission buffer address + uint16_t txbufsz; // transmission buffer size + uint8_t *rx_buf; // reception buffer address + void (*func)(); // endpoint action function + unsigned rx_cnt : 10; // received data counter +} ep_t; + +extern volatile uint8_t usbON; + +void USB_setup(); +int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*func)()); +void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size); +void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size); +int EP_Read(uint8_t number, uint8_t *buf); + +// could be [re]defined in usb_dev.c +extern void usb_class_request(config_pack_t *packet, uint8_t *data, uint16_t datalen); +extern void usb_vendor_request(config_pack_t *packet, uint8_t *data, uint16_t datalen); +extern void set_configuration();