From fe8e444338b7272a814c6ea4700bf619c11d005e Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Tue, 11 Apr 2023 22:57:23 +0300 Subject: [PATCH] change USB-CAN according to new USB doctrine: iInterface for each device --- F0:F030,F042,F072/usbcan_ringbuffer/Makefile | 2 + F0:F030,F042,F072/usbcan_ringbuffer/can.c | 13 +- F0:F030,F042,F072/usbcan_ringbuffer/can.h | 4 +- F0:F030,F042,F072/usbcan_ringbuffer/main.c | 1 - F0:F030,F042,F072/usbcan_ringbuffer/proto.c | 38 ++-- F0:F030,F042,F072/usbcan_ringbuffer/usb.c | 92 +++------- F0:F030,F042,F072/usbcan_ringbuffer/usb.h | 20 +- F0:F030,F042,F072/usbcan_ringbuffer/usb_lib.c | 171 ++++++++++++------ F0:F030,F042,F072/usbcan_ringbuffer/usb_lib.h | 54 +++--- .../usbcan_ringbuffer/usbcan.bin | Bin 11468 -> 11664 bytes .../usbcan_ringbuffer/usbcanrb.config | 1 + .../usbcan_ringbuffer/usbcanrb.creator.user | 31 +++- .../usbcanrb.creator.user.cf63021 | 160 ++++++++++++++++ F0:F030,F042,F072/usbcan_ringbuffer/usbhw.c | 33 ++-- F0:F030,F042,F072/usbcan_ringbuffer/usbhw.h | 27 ++- .../usbcan_ringbuffer/version.inc | 4 +- .../nitrogen.creator.user.cf63021 | 160 ++++++++++++++++ 17 files changed, 594 insertions(+), 217 deletions(-) create mode 100644 F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.creator.user.cf63021 create mode 100644 F3:F303/NitrogenFlooding/nitrogen.creator.user.cf63021 diff --git a/F0:F030,F042,F072/usbcan_ringbuffer/Makefile b/F0:F030,F042,F072/usbcan_ringbuffer/Makefile index f959722..3ecb35b 100644 --- a/F0:F030,F042,F072/usbcan_ringbuffer/Makefile +++ b/F0:F030,F042,F072/usbcan_ringbuffer/Makefile @@ -4,5 +4,7 @@ MCU := F042x6 # change this linking script depending on particular MCU model, LDSCRIPT := stm32f042x6.ld +DEFINES := -DUSB2_16 + include ../makefile.f0 include ../../makefile.stm32 diff --git a/F0:F030,F042,F072/usbcan_ringbuffer/can.c b/F0:F030,F042,F072/usbcan_ringbuffer/can.c index a3c7156..f136f6f 100644 --- a/F0:F030,F042,F072/usbcan_ringbuffer/can.c +++ b/F0:F030,F042,F072/usbcan_ringbuffer/can.c @@ -25,7 +25,6 @@ static CAN_message messages[CAN_INMESSAGE_SIZE]; static uint8_t first_free_idx = 0; // index of first empty cell static int8_t first_nonfree_idx = -1; // index of first data cell -static uint16_t oldspeed = 100; // speed of last init uint32_t floodT = FLOOD_PERIOD_MS; // flood period in ms static uint8_t incrflood = 0; // ==1 for incremental flooding @@ -84,11 +83,11 @@ CAN_message *CAN_messagebuf_pop(){ return msg; } -void CAN_reinit(uint16_t speed){ +int CAN_reinit(uint16_t speed){ CAN->TSR |= CAN_TSR_ABRQ0 | CAN_TSR_ABRQ1 | CAN_TSR_ABRQ2; RCC->APB1RSTR |= RCC_APB1RSTR_CANRST; RCC->APB1RSTR &= ~RCC_APB1RSTR_CANRST; - CAN_setup(speed); + return CAN_setup(speed); } /* @@ -112,8 +111,9 @@ so if TBS1=4 and TBS2=3, sum=8, bit sampling freq is 48/8 = 6MHz 1MBps - 6 */ -// speed - in kbps -void CAN_setup(uint16_t speed){ +// speed - in kbps. @return - current speed +int CAN_setup(uint16_t speed){ + static uint16_t oldspeed = 100; // speed of last init LED_off(LED1); if(speed == 0) speed = oldspeed; else if(speed < 50) speed = 50; @@ -168,6 +168,7 @@ void CAN_setup(uint16_t speed){ NVIC_SetPriority(CEC_CAN_IRQn, 0); /* (14) */ NVIC_EnableIRQ(CEC_CAN_IRQn); /* (15) */ can_status = CAN_READY; + return speed; } void printCANerr(){ @@ -234,7 +235,7 @@ void can_proc(){ can_send(flood_msg->data, flood_msg->length, flood_msg->ID); }else if(incrflood && (Tms - lastFloodTime) >= floodT){ // incremental flood message lastFloodTime = Tms; - if(CAN_OK == can_send((uint8_t*)&incrmessagectr, 4, flood_msg->ID)) ++incrmessagectr; + if(CAN_OK == can_send((uint8_t*)&incrmessagectr, 4, loc_flood_msg.ID)) ++incrmessagectr; } } diff --git a/F0:F030,F042,F072/usbcan_ringbuffer/can.h b/F0:F030,F042,F072/usbcan_ringbuffer/can.h index 8b3cde8..4085f84 100644 --- a/F0:F030,F042,F072/usbcan_ringbuffer/can.h +++ b/F0:F030,F042,F072/usbcan_ringbuffer/can.h @@ -47,8 +47,8 @@ typedef enum{ CAN_status CAN_get_status(); -void CAN_reinit(uint16_t speed); -void CAN_setup(uint16_t speed); +int CAN_reinit(uint16_t speed); +int CAN_setup(uint16_t speed); CAN_status can_send(uint8_t *msg, uint8_t len, uint16_t target_id); void can_proc(); diff --git a/F0:F030,F042,F072/usbcan_ringbuffer/main.c b/F0:F030,F042,F072/usbcan_ringbuffer/main.c index 0b20083..109b6bb 100644 --- a/F0:F030,F042,F072/usbcan_ringbuffer/main.c +++ b/F0:F030,F042,F072/usbcan_ringbuffer/main.c @@ -52,7 +52,6 @@ int main(void){ lastT = 0; } can_proc(); - USB_proc(); if(CAN_get_status() == CAN_FIFO_OVERRUN){ USB_sendstr("CAN bus fifo overrun occured!\n"); } diff --git a/F0:F030,F042,F072/usbcan_ringbuffer/proto.c b/F0:F030,F042,F072/usbcan_ringbuffer/proto.c index b356ac9..e177ab7 100644 --- a/F0:F030,F042,F072/usbcan_ringbuffer/proto.c +++ b/F0:F030,F042,F072/usbcan_ringbuffer/proto.c @@ -228,7 +228,7 @@ TRUE_INLINE void CANini(char *txt){ } CAN_reinit((uint16_t)N); USB_sendstr("Reinit CAN bus with speed "); - printu(N); USB_sendstr("kbps"); + printu(N); USB_sendstr("kbps\n"); } TRUE_INLINE void addIGN(char *txt){ @@ -250,6 +250,7 @@ TRUE_INLINE void addIGN(char *txt){ Ignore_IDs[IgnSz++] = (uint16_t)(N & 0x7ff); USB_sendstr("Added ID "); printu(N); USB_sendstr("\nIgn buffer size: "); printu(IgnSz); + newline(); } TRUE_INLINE void print_ign_buf(){ @@ -321,15 +322,16 @@ TRUE_INLINE void list_filters(){ } } + + TRUE_INLINE void setfloodt(char *s){ uint32_t N; s = omit_spaces(s); char *n = getnum(s, &N); - if(s == n){ - USB_sendstr("t="); printu(floodT); USB_putbyte('\n'); - return; + if(s != n){ + floodT = N; } - floodT = N; + USB_sendstr("t="); printu(floodT); USB_putbyte('\n'); } /** @@ -421,7 +423,7 @@ static void add_filter(char *str){ } CAN->FMR &=~ CAN_FMR_FINIT; USB_sendstr("Added filter with "); - printu(nfilt); USB_sendstr(" parameters"); + printu(nfilt); USB_sendstr(" parameters\n"); } const char *helpmsg = @@ -472,31 +474,31 @@ void cmd_parser(char *txt){ switch(_1st){ case 'a': addIGN(txt); - goto eof; + return; break; case 'b': CANini(txt); - goto eof; + return; break; case 'f': add_filter(txt); - goto eof; + return; break; case 'F': set_flood(parseCANmsg(txt), 0); - goto eof; + return; break; case 's': case 'S': USB_sendstrCANcommand(txt); - goto eof; + return; break; case 't': setfloodt(txt); - goto eof; + return; break; } - if(*txt != '\n') _1st = '?'; // help for wrong message length + if(*txt) _1st = '?'; // help for wrong message length switch(_1st){ case 'c': getcanstat(); @@ -517,7 +519,9 @@ void cmd_parser(char *txt){ USB_sendstr("Incremental flooding is ON ('F' to off)\n"); break; case 'I': - CAN_reinit(0); + USB_sendstr("CANspeed="); + printu(CAN_reinit(0)); + newline(); break; case 'l': list_filters(); @@ -526,9 +530,11 @@ void cmd_parser(char *txt){ ledsON = 0; LED_off(LED0); LED_off(LED1); + USB_sendstr("LEDS=0\n"); break; case 'O': ledsON = 1; + USB_sendstr("LEDS=1\n"); break; case 'p': print_ign_buf(); @@ -552,8 +558,8 @@ void cmd_parser(char *txt){ USB_sendstr(helpmsg); break; } -eof: - USB_putbyte('\n'); +//eof: + //USB_putbyte('\n'); } // print 32bit unsigned int diff --git a/F0:F030,F042,F072/usbcan_ringbuffer/usb.c b/F0:F030,F042,F072/usbcan_ringbuffer/usb.c index 4e1182c..9a83e16 100644 --- a/F0:F030,F042,F072/usbcan_ringbuffer/usb.c +++ b/F0:F030,F042,F072/usbcan_ringbuffer/usb.c @@ -1,6 +1,6 @@ /* * This file is part of the usbcanrb project. - * Copyright 2022 Edward V. Emelianov . + * 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 @@ -16,34 +16,36 @@ * along with this program. If not, see . */ -#include "ringbuffer.h" +#include + +#include "hardware.h" #include "usb.h" #include "usb_lib.h" -static uint8_t usbbuff[USB_TXBUFSZ]; // temporary buffer for sending data +static volatile uint8_t usbbuff[USB_TXBUFSZ]; // temporary buffer for sending data // ring buffers for incoming and outgoing data static uint8_t obuf[RBOUTSZ], ibuf[RBINSZ]; -static ringbuffer out = {.data = obuf, .length = RBOUTSZ, .head = 0, .tail = 0}; -static ringbuffer in = {.data = ibuf, .length = RBINSZ, .head = 0, .tail = 0}; +volatile ringbuffer rbout = {.data = obuf, .length = RBOUTSZ, .head = 0, .tail = 0}; +volatile ringbuffer rbin = {.data = ibuf, .length = RBINSZ, .head = 0, .tail = 0}; // transmission is succesfull -static volatile uint8_t bufisempty = 1; -static volatile uint8_t bufovrfl = 0; +volatile uint8_t bufisempty = 1; +volatile uint8_t bufovrfl = 0; -static void send_next(){ +void send_next(){ if(bufisempty) return; static int lastdsz = 0; - int buflen = RB_read(&out, usbbuff, USB_TXBUFSZ); + int buflen = RB_read((ringbuffer*)&rbout, (uint8_t*)usbbuff, USB_TXBUFSZ); if(!buflen){ if(lastdsz == 64) EP_Write(3, NULL, 0); // send ZLP after 64 bits packet when nothing more to send lastdsz = 0; bufisempty = 1; return; } - EP_Write(3, usbbuff, buflen); + EP_Write(3, (uint8_t*)usbbuff, buflen); lastdsz = buflen; } -// send full content of ring buffer +// blocking send full content of ring buffer int USB_sendall(){ while(!bufisempty){ if(!usbON) return 0; @@ -55,7 +57,7 @@ int USB_sendall(){ int USB_send(const uint8_t *buf, int len){ if(!buf || !usbON || !len) return 0; while(len){ - int a = RB_write(&out, buf, len); + int a = RB_write((ringbuffer*)&rbout, buf, len); len -= a; buf += a; if(bufisempty){ @@ -68,7 +70,7 @@ int USB_send(const uint8_t *buf, int len){ int USB_putbyte(uint8_t byte){ if(!usbON) return 0; - while(0 == RB_write(&out, &byte, 1)){ + while(0 == RB_write((ringbuffer*)&rbout, &byte, 1)){ if(bufisempty){ bufisempty = 0; send_next(); @@ -88,14 +90,16 @@ int USB_sendstr(const char *string){ /** * @brief USB_receive - get binary data from receiving ring-buffer - * @param buf (i) - buffer[64] for received data + * @param buf (i) - buffer for received data + * @param len - length of `buf` * @return amount of received bytes (negative, if overfull happened) */ int USB_receive(uint8_t *buf, int len){ - int sz = RB_read(&in, buf, len); + int sz = RB_read((ringbuffer*)&rbin, buf, len); if(bufovrfl){ - RB_clearbuf(&in); - sz = -sz; + RB_clearbuf((ringbuffer*)&rbin); + if(!sz) sz = -1; + else sz = -sz; bufovrfl = 0; } return sz; @@ -108,61 +112,15 @@ int USB_receive(uint8_t *buf, int len){ * @return strlen or negative value indicating overflow (if so, string won't be ends with 0 and buffer should be cleared) */ int USB_receivestr(char *buf, int len){ - int l = RB_readto(&in, '\n', (uint8_t*)buf, len); - if(l < 0 || bufovrfl) RB_clearbuf(&in); + int l = RB_readto((ringbuffer*)&rbin, '\n', (uint8_t*)buf, len); + if(l == 0) return 0; + if(--l < 0 || bufovrfl) RB_clearbuf((ringbuffer*)&rbin); else buf[l] = 0; // replace '\n' with strend if(bufovrfl){ if(l > 0) l = -l; + else l = -1; bufovrfl = 0; } return l; } -// interrupt IN handler (never used?) -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 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; -} - -// data IN/OUT handlers -static void transmit_Handler(){ // EP3IN - uint16_t epstatus = KEEP_DTOG_STAT(USB->EPnR[3]); - // clear CTR keep DTOGs & STATs - USB->EPnR[3] = (epstatus & ~(USB_EPnR_CTR_TX)); // clear TX ctr - send_next(); -} - -static void receive_Handler(){ // EP2OUT - uint16_t epstatus = KEEP_DTOG(USB->EPnR[2]); - uint8_t sz = endpoints[2].rx_cnt; - if(sz){ - if(RB_write(&in, endpoints[2].rx_buf, sz) != sz) bufovrfl = 1; - } - // keep stat_tx & set ACK rx, clear RX ctr - USB->EPnR[2] = (epstatus & ~USB_EPnR_CTR_RX) ^ USB_EPnR_STAT_RX; -} - -void USB_proc(){ - switch(USB_Dev.USB_Status){ - case USB_STATE_CONFIGURED: - // make new BULK endpoint - // Buffer have 1024 bytes, but last 256 we use for CAN bus (30.2 of RM: USB main features) - EP_Init(1, EP_TYPE_INTERRUPT, USB_EP1BUFSZ, 0, EP1_Handler); // IN1 - transmit - EP_Init(2, EP_TYPE_BULK, 0, USB_RXBUFSZ, receive_Handler); // OUT2 - receive data - EP_Init(3, EP_TYPE_BULK, USB_TXBUFSZ, 0, transmit_Handler); // IN3 - transmit data - USB_Dev.USB_Status = USB_STATE_CONNECTED; - break; - case USB_STATE_DEFAULT: - case USB_STATE_ADDRESSED: - if(usbON){ - usbON = 0; - } - break; - default: // USB_STATE_CONNECTED - send next data portion - if(!usbON) return; - } -} diff --git a/F0:F030,F042,F072/usbcan_ringbuffer/usb.h b/F0:F030,F042,F072/usbcan_ringbuffer/usb.h index 5111aa1..14512f2 100644 --- a/F0:F030,F042,F072/usbcan_ringbuffer/usb.h +++ b/F0:F030,F042,F072/usbcan_ringbuffer/usb.h @@ -1,6 +1,6 @@ /* * This file is part of the usbcanrb project. - * Copyright 2022 Edward V. Emelianov . + * 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 @@ -18,13 +18,29 @@ #pragma once +#include "ringbuffer.h" #include "usbhw.h" // sizes of ringbuffers for outgoing and incoming data #define RBOUTSZ (512) #define RBINSZ (512) -void USB_proc(); +#define newline() USB_putbyte('\n') +#define USND(s) do{USB_sendstr(s); USB_putbyte('\n');}while(0) + +#define STR_HELPER(s) #s +#define STR(s) STR_HELPER(s) + +#ifdef EBUG +#define DBG(str) do{USB_sendstr(__FILE__ " (L" STR(__LINE__) "): " str); newline();}while(0) +#else +#define DBG(str) +#endif + +extern volatile ringbuffer rbout, rbin; +extern volatile uint8_t bufisempty, bufovrfl; + +void send_next(); int USB_sendall(); int USB_send(const uint8_t *buf, int len); int USB_putbyte(uint8_t byte); diff --git a/F0:F030,F042,F072/usbcan_ringbuffer/usb_lib.c b/F0:F030,F042,F072/usbcan_ringbuffer/usb_lib.c index d514ba7..9ef42e8 100644 --- a/F0:F030,F042,F072/usbcan_ringbuffer/usb_lib.c +++ b/F0:F030,F042,F072/usbcan_ringbuffer/usb_lib.c @@ -1,6 +1,6 @@ /* * This file is part of the usbcanrb project. - * Copyright 2022 Edward V. Emelianov . + * 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 @@ -17,19 +17,20 @@ */ #include +#include "usb.h" #include "usb_lib.h" +#include "usbhw.h" ep_t endpoints[STM32ENDPOINTS]; -usb_dev_t USB_Dev; +static uint16_t USB_Addr = 0; static usb_LineCoding lineCoding = {115200, 0, 0, 8}; -config_pack_t setup_packet; -uint8_t ep0databuf[EP0DATABUF_SIZE]; -//uint8_t ep0dbuflen = 0; +uint8_t ep0databuf[EP0DATABUF_SIZE], setupdatabuf[EP0DATABUF_SIZE]; +config_pack_t *setup_packet = (config_pack_t*) setupdatabuf; usb_LineCoding getLineCoding(){return lineCoding;} -uint8_t usbON = 0; // device disconnected from terminal +volatile uint8_t usbON = 0; // device disconnected from terminal // definition of parts common for USB_DeviceDescriptor & USB_DeviceQualifierDescriptor #define bcdUSB_L 0x10 @@ -54,9 +55,9 @@ static const uint8_t USB_DeviceDescriptor[] = { 0x23, // idProduct_H 0x00, // bcdDevice_Ver_L 0x03, // bcdDevice_Ver_H - 0x01, // iManufacturer - 0x02, // iProduct - 0x00, // iSerialNumber + iMANUFACTURER_DESCR, // iManufacturer + iPRODUCT_DESCR, // iProduct + iSERIAL_DESCR, // iSerialNumber bNumConfigurations // bNumConfigurations }; @@ -96,7 +97,7 @@ static const uint8_t USB_ConfigDescriptor[] = { 0xff, /* bInterfaceClass */ 0x00, /* bInterfaceSubClass */ 0x00, /* bInterfaceProtocol */ - 0x00, /* iInterface: */ + iINTERFACE_DESCR, /* iInterface: */ /////////////////////////////////////////////////// /*Endpoint 1 Descriptor*/ 0x07, /* bLength: Endpoint Descriptor size */ @@ -126,11 +127,19 @@ static const uint8_t USB_ConfigDescriptor[] = { 0x00, /* bInterval: ignore for Bulk transfer */ }; -_USB_LANG_ID_(USB_StringLangDescriptor, LANG_US); -// these descriptors are not used in PL2303 emulator! -_USB_STRING_(USB_StringSerialDescriptor, u"0"); -_USB_STRING_(USB_StringManufacturingDescriptor, u"Prolific Technology Inc."); -_USB_STRING_(USB_StringProdDescriptor, u"USB-Serial Controller"); +_USB_LANG_ID_(LD, LANG_US); +_USB_STRING_(SD, u"0.0.1"); +_USB_STRING_(MD, u"Prolific Technology Inc."); +_USB_STRING_(PD, u"USB-Serial Controller"); +_USB_STRING_(ID, u"can-usb"); +static void const *StringDescriptor[iDESCR_AMOUNT] = { + [iLANGUAGE_DESCR] = &LD, + [iMANUFACTURER_DESCR] = &MD, + [iPRODUCT_DESCR] = &PD, + [iSERIAL_DESCR] = &SD, + [iINTERFACE_DESCR] = &ID +}; + /* * default handlers @@ -149,8 +158,8 @@ void WEAK break_handler(){ // handler of vendor requests void WEAK vendor_handler(config_pack_t *packet){ + uint16_t c; if(packet->bmRequestType & 0x80){ // read - uint8_t c; switch(packet->wValue){ case 0x8484: c = 2; @@ -164,14 +173,15 @@ void WEAK vendor_handler(config_pack_t *packet){ default: c = 0; } - EP_WriteIRQ(0, &c, 1); + EP_WriteIRQ(0, (uint8_t*)&c, 1); }else{ // write ZLP - EP_WriteIRQ(0, (uint8_t *)0, 0); + c = 0; + EP_WriteIRQ(0, (uint8_t *)&c, 0); } } static void wr0(const uint8_t *buf, uint16_t size){ - if(setup_packet.wLength < size) size = setup_packet.wLength; // shortened request + if(setup_packet->wLength < size) size = setup_packet->wLength; // shortened request if(size < endpoints[0].txbufsz){ EP_WriteIRQ(0, buf, size); return; @@ -199,24 +209,18 @@ static void wr0(const uint8_t *buf, uint16_t size){ } static inline void get_descriptor(){ - switch(setup_packet.wValue){ + uint8_t descrtype = setup_packet->wValue >> 8, + descridx = setup_packet->wValue & 0xff; + switch(descrtype){ case DEVICE_DESCRIPTOR: wr0(USB_DeviceDescriptor, sizeof(USB_DeviceDescriptor)); break; case CONFIGURATION_DESCRIPTOR: wr0(USB_ConfigDescriptor, sizeof(USB_ConfigDescriptor)); break; - case STRING_LANG_DESCRIPTOR: - wr0((const uint8_t *)&USB_StringLangDescriptor, STRING_LANG_DESCRIPTOR_SIZE_BYTE); - break; - case STRING_MAN_DESCRIPTOR: - wr0((const uint8_t *)&USB_StringManufacturingDescriptor, USB_StringManufacturingDescriptor.bLength); - break; - case STRING_PROD_DESCRIPTOR: - wr0((const uint8_t *)&USB_StringProdDescriptor, USB_StringProdDescriptor.bLength); - break; - case STRING_SN_DESCRIPTOR: - wr0((const uint8_t *)&USB_StringSerialDescriptor, USB_StringSerialDescriptor.bLength); + case STRING_DESCRIPTOR: + if(descridx < iDESCR_AMOUNT) wr0((const uint8_t *)StringDescriptor[descridx], *((uint8_t*)StringDescriptor[descridx])); + else EP_WriteIRQ(0, (uint8_t*)0, 0); break; case DEVICE_QUALIFIER_DESCRIPTOR: wr0(USB_DeviceQualifierDescriptor, USB_DeviceQualifierDescriptor[0]); @@ -226,10 +230,10 @@ static inline void get_descriptor(){ } } -static uint8_t configuration = 0; // reply for GET_CONFIGURATION (==1 if configured) +static uint16_t configuration = 0; // reply for GET_CONFIGURATION (==1 if configured) static inline void std_d2h_req(){ uint16_t status = 0; // bus powered - switch(setup_packet.bRequest){ + switch(setup_packet->bRequest){ case GET_DESCRIPTOR: get_descriptor(); break; @@ -237,23 +241,54 @@ static inline void std_d2h_req(){ EP_WriteIRQ(0, (uint8_t *)&status, 2); // send status: Bus Powered break; case GET_CONFIGURATION: - EP_WriteIRQ(0, &configuration, 1); + EP_WriteIRQ(0, (uint8_t*)&configuration, 1); break; default: break; } } +// interrupt IN handler (never used?) +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 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; +} + +// data IN/OUT handlers +static void transmit_Handler(){ // EP3IN + uint16_t epstatus = KEEP_DTOG_STAT(USB->EPnR[3]); + // clear CTR keep DTOGs & STATs + USB->EPnR[3] = (epstatus & ~(USB_EPnR_CTR_TX)); // clear TX ctr + send_next(); +} + +static void receive_Handler(){ // EP2OUT + uint8_t buf[USB_RXBUFSZ]; + uint16_t epstatus = KEEP_DTOG(USB->EPnR[2]); + uint8_t sz = EP_Read(2, (uint8_t*)buf); + if(sz){ + if(RB_write((ringbuffer*)&rbin, buf, sz) != sz) bufovrfl = 1; + } + // keep stat_tx & set ACK rx, clear RX ctr + USB->EPnR[2] = (epstatus & ~USB_EPnR_CTR_RX) ^ USB_EPnR_STAT_RX; +} + static inline void std_h2d_req(){ - switch(setup_packet.bRequest){ + switch(setup_packet->bRequest){ case SET_ADDRESS: // new address will be assigned later - after acknowlegement or request to host - USB_Dev.USB_Addr = setup_packet.wValue; + USB_Addr = setup_packet->wValue; break; case SET_CONFIGURATION: // Now device configured - USB_Dev.USB_Status = USB_STATE_CONFIGURED; - configuration = setup_packet.wValue; + configuration = setup_packet->wValue; + EP_Init(1, EP_TYPE_INTERRUPT, USB_EP1BUFSZ, 0, EP1_Handler); // IN1 - transmit + EP_Init(2, EP_TYPE_BULK, 0, USB_RXBUFSZ, receive_Handler); // OUT2 - receive data + EP_Init(3, EP_TYPE_BULK, USB_TXBUFSZ, 0, transmit_Handler); // IN3 - transmit data break; default: break; @@ -271,8 +306,8 @@ bmRequestType: 76543210 */ void EP0_Handler(){ uint16_t epstatus = USB->EPnR[0]; // EP0R on input -> return this value after modifications - uint8_t reqtype = setup_packet.bmRequestType & 0x7f; - uint8_t dev2host = (setup_packet.bmRequestType & 0x80) ? 1 : 0; + uint8_t reqtype = setup_packet->bmRequestType & 0x7f; + uint8_t dev2host = (setup_packet->bmRequestType & 0x80) ? 1 : 0; int rxflag = RX_FLAG(epstatus); if(rxflag && SETUP_FLAG(epstatus)){ switch(reqtype){ @@ -285,15 +320,15 @@ void EP0_Handler(){ } break; case STANDARD_ENDPOINT_REQUEST_TYPE: // standard endpoint request - if(setup_packet.bRequest == CLEAR_FEATURE){ + if(setup_packet->bRequest == CLEAR_FEATURE){ EP_WriteIRQ(0, (uint8_t *)0, 0); } break; case VENDOR_REQUEST_TYPE: - vendor_handler(&setup_packet); + vendor_handler(setup_packet); break; case CONTROL_REQUEST_TYPE: - switch(setup_packet.bRequest){ + switch(setup_packet->bRequest){ case GET_LINE_CODING: EP_WriteIRQ(0, (uint8_t*)&lineCoding, sizeof(lineCoding)); break; @@ -301,7 +336,7 @@ void EP0_Handler(){ break; case SET_CONTROL_LINE_STATE: usbON = 1; - clstate_handler(setup_packet.wValue); + clstate_handler(setup_packet->wValue); break; case SEND_BREAK: usbON = 0; @@ -310,23 +345,22 @@ void EP0_Handler(){ default: break; } - if(setup_packet.bRequest != GET_LINE_CODING) EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement + if(setup_packet->bRequest != GET_LINE_CODING) EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement break; default: EP_WriteIRQ(0, (uint8_t *)0, 0); } }else if(rxflag){ // got data over EP0 or host acknowlegement if(endpoints[0].rx_cnt){ - if(setup_packet.bRequest == SET_LINE_CODING){ + if(setup_packet->bRequest == SET_LINE_CODING){ linecoding_handler((usb_LineCoding*)ep0databuf); } } } else if(TX_FLAG(epstatus)){ // package transmitted // now we can change address after enumeration - if ((USB->DADDR & USB_DADDR_ADD) != USB_Dev.USB_Addr){ - USB->DADDR = USB_DADDR_EF | USB_Dev.USB_Addr; - // change state to ADRESSED - USB_Dev.USB_Status = USB_STATE_ADDRESSED; + if ((USB->DADDR & USB_DADDR_ADD) != USB_Addr){ + USB->DADDR = USB_DADDR_EF | USB_Addr; + usbON = 0; } } epstatus = KEEP_DTOG(USB->EPnR[0]); @@ -343,13 +377,24 @@ void EP0_Handler(){ * @param size - its size */ void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size){ - if(size > USB_TXBUFSZ) size = USB_TXBUFSZ; + 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; } @@ -372,10 +417,22 @@ void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size){ * @return amount of data read */ int EP_Read(uint8_t number, uint8_t *buf){ - int n = endpoints[number].rx_cnt; - if(n){ - for(int i = 0; i < n; ++i) - buf[i] = endpoints[number].rx_buf[i]; - } - return n; + 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; } + diff --git a/F0:F030,F042,F072/usbcan_ringbuffer/usb_lib.h b/F0:F030,F042,F072/usbcan_ringbuffer/usb_lib.h index d6af404..8bfe48a 100644 --- a/F0:F030,F042,F072/usbcan_ringbuffer/usb_lib.h +++ b/F0:F030,F042,F072/usbcan_ringbuffer/usb_lib.h @@ -1,6 +1,6 @@ /* * This file is part of the usbcanrb project. - * Copyright 2022 Edward V. Emelianov . + * 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 @@ -60,14 +60,21 @@ #define CONTROL_DTR 0x01 #define CONTROL_RTS 0x02 -// wValue -#define DEVICE_DESCRIPTOR 0x100 -#define CONFIGURATION_DESCRIPTOR 0x200 -#define STRING_LANG_DESCRIPTOR 0x300 -#define STRING_MAN_DESCRIPTOR 0x301 -#define STRING_PROD_DESCRIPTOR 0x302 -#define STRING_SN_DESCRIPTOR 0x303 -#define DEVICE_QUALIFIER_DESCRIPTOR 0x600 +// string descriptors +enum{ + iLANGUAGE_DESCR, + iMANUFACTURER_DESCR, + iPRODUCT_DESCR, + iSERIAL_DESCR, + iINTERFACE_DESCR, + iDESCR_AMOUNT +}; + +// Types of descriptors +#define DEVICE_DESCRIPTOR 0x01 +#define CONFIGURATION_DESCRIPTOR 0x02 +#define STRING_DESCRIPTOR 0x03 +#define DEVICE_QUALIFIER_DESCRIPTOR 0x06 #define RX_FLAG(epstat) (epstat & USB_EPnR_CTR_RX) #define TX_FLAG(epstat) (epstat & USB_EPnR_CTR_TX) @@ -77,14 +84,6 @@ #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)) -// USB state: uninitialized, addressed, ready for use -typedef enum{ - USB_STATE_DEFAULT, - USB_STATE_ADDRESSED, - USB_STATE_CONFIGURED, - USB_STATE_CONNECTED -} USB_state; - // EP types #define EP_TYPE_BULK 0x00 #define EP_TYPE_CONTROL 0x01 @@ -113,7 +112,6 @@ static const struct name \ \ } \ name = {0x04, 0x03, lng_id} -#define STRING_LANG_DESCRIPTOR_SIZE_BYTE (4) // EP0 configuration packet typedef struct { @@ -125,20 +123,14 @@ typedef struct { } config_pack_t; // endpoints state -typedef struct __ep_t{ +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 - uint16_t rx_cnt; // received data counter + unsigned rx_cnt : 10; // received data counter } ep_t; -// USB status & its address -typedef struct { - uint8_t USB_Status; - uint16_t USB_Addr; -}usb_dev_t; - typedef struct { uint32_t dwDTERate; uint8_t bCharFormat; @@ -163,15 +155,15 @@ typedef struct { } __attribute__ ((packed)) usb_cdc_notification; extern ep_t endpoints[]; -extern usb_dev_t USB_Dev; -extern uint8_t usbON; -extern config_pack_t setup_packet; -extern uint8_t ep0databuf[]; -//extern uint8_t ep0dbuflen; +extern volatile uint8_t usbON; +extern config_pack_t *setup_packet; +extern uint8_t ep0databuf[], setupdatabuf[]; void EP0_Handler(); +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); usb_LineCoding getLineCoding(); void linecoding_handler(usb_LineCoding *lc); diff --git a/F0:F030,F042,F072/usbcan_ringbuffer/usbcan.bin b/F0:F030,F042,F072/usbcan_ringbuffer/usbcan.bin index 58a8119a788c9329fdbd25258c2046a39d81fb24..b8c99a261c3de67b1c098b52a156be927cc1a8d1 100755 GIT binary patch delta 7069 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 delta 6913 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 - + EnvironmentId - {cf63021e-ef53-49b0-b03b-2f2570cdf3b6} + {7bd84e39-ca37-46d3-be9d-99ebea85bc0d} ProjectExplorer.Project.ActiveTarget @@ -38,32 +38,43 @@ true 1 false - false + true false - 1 + 0 true true 0 8 true false - 2 + 1 true - true + false true *.md, *.MD, Makefile - true + false true ProjectExplorer.Project.PluginSettings + + true + false + true + true + true + true + + + 0 + true true true Builtin.DefaultTidyAndClazy - 4 + 2 @@ -77,12 +88,12 @@ Desktop Desktop Desktop - {91347f2c-5221-46a7-80b1-0a054ca02f79} + {65a14f9e-e008-4c1b-89df-4eaa4774b6e3} 0 0 0 - /home/eddy/Docs/SAO/ELECTRONICS/STM32/F0-srcs/usbcan_ringbuffer + /Big/Data/00__Electronics/STM32/F0-nolib/usbcan_ringbuffer diff --git a/F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.creator.user.cf63021 b/F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.creator.user.cf63021 new file mode 100644 index 0000000..819893c --- /dev/null +++ b/F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.creator.user.cf63021 @@ -0,0 +1,160 @@ + + + + + + EnvironmentId + {cf63021e-ef53-49b0-b03b-2f2570cdf3b6} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + KOI8-R + false + 4 + false + 80 + true + true + 1 + false + false + false + 1 + true + true + 0 + 8 + true + false + 2 + true + true + true + *.md, *.MD, Makefile + true + true + + + + ProjectExplorer.Project.PluginSettings + + + true + true + Builtin.DefaultTidyAndClazy + 4 + + + + true + + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + Desktop + {91347f2c-5221-46a7-80b1-0a054ca02f79} + 0 + 0 + 0 + + /home/eddy/Docs/SAO/ELECTRONICS/STM32/F0-srcs/usbcan_ringbuffer + + + + all + + true + GenericProjectManager.GenericMakeStep + + 1 + Сборка + Сборка + ProjectExplorer.BuildSteps.Build + + + + + clean + + true + GenericProjectManager.GenericMakeStep + + 1 + Очистка + Очистка + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + По умолчанию + GenericProjectManager.GenericBuildConfiguration + + 1 + + + 0 + Развёртывание + Развёртывание + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + 2 + + ProjectExplorer.CustomExecutableRunConfiguration + + false + true + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/F0:F030,F042,F072/usbcan_ringbuffer/usbhw.c b/F0:F030,F042,F072/usbcan_ringbuffer/usbhw.c index 03ab887..345138c 100644 --- a/F0:F030,F042,F072/usbcan_ringbuffer/usbhw.c +++ b/F0:F030,F042,F072/usbcan_ringbuffer/usbhw.c @@ -1,6 +1,6 @@ /* * This file is part of the usbcanrb project. - * Copyright 2022 Edward V. Emelianov . + * 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 @@ -17,9 +17,9 @@ */ #include "usb.h" -#include "usbhw.h" #include "usb_lib.h" +// here we suppose that all PIN settings done in hw_setup earlier void USB_setup(){ RCC->APB1ENR |= RCC_APB1ENR_CRSEN | RCC_APB1ENR_USBEN; // enable CRS (hsi48 sync) & USB RCC->CFGR3 &= ~RCC_CFGR3_USBSW; // reset USB @@ -44,7 +44,6 @@ void USB_setup(){ static uint16_t lastaddr = LASTADDR_DEFAULT; /** * Endpoint initialisation - * !!! when working with CAN bus change USB_BTABLE_SIZE to 768 !!! * @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 @@ -52,13 +51,13 @@ static uint16_t lastaddr = LASTADDR_DEFAULT; * @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)()){ +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) 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 + if(rxsz & 1 || rxsz > 512) return 3; // wrong rx buffer size uint16_t countrx = 0; if(rxsz < 64) countrx = rxsz / 2; else{ @@ -66,33 +65,33 @@ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*f countrx = 31 + rxsz / 32; } USB_BTABLE->EP[number].USB_ADDR_TX = lastaddr; - endpoints[number].tx_buf = (uint16_t *)(USB_BTABLE_BASE + 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); + endpoints[number].rx_buf = (uint8_t *)(USB_BTABLE_BASE + lastaddr * ACCESSZ); lastaddr += rxsz; - // buffer size: Table127 of RM USB_BTABLE->EP[number].USB_COUNT_RX = countrx << 10; endpoints[number].func = func; return 0; } -// standard IRQ handler +// standard IRQ handler (just rename it due to MCU model) void usb_isr(){ - if (USB->ISTR & USB_ISTR_RESET){ + if(USB->ISTR & USB_ISTR_RESET){ + usbON = 0; // Reinit registers USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; - USB->ISTR = 0; // Endpoint 0 - CONTROL // ON USB LS size of EP0 may be 8 bytes, but on FS it should be 64 bytes! - lastaddr = LASTADDR_DEFAULT; // roll back to beginning of buffer - EP_Init(0, EP_TYPE_CONTROL, USB_EP0_BUFSZ, USB_EP0_BUFSZ, EP0_Handler); + lastaddr = LASTADDR_DEFAULT; // clear address, leave only enable bit USB->DADDR = USB_DADDR_EF; - // state is default - wait for enumeration - USB_Dev.USB_Status = USB_STATE_DEFAULT; + if(EP_Init(0, EP_TYPE_CONTROL, USB_EP0_BUFSZ, USB_EP0_BUFSZ, EP0_Handler)){ + return; + } + USB->ISTR = ~USB_ISTR_RESET; } if(USB->ISTR & USB_ISTR_CTR){ // EP number @@ -105,10 +104,10 @@ void usb_isr(){ 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(n == 0){ // control endpoint if(epstatus & USB_EPnR_SETUP){ // setup packet -> copy data to conf_pack - EP_Read(0, (uint8_t*)&setup_packet); + EP_Read(0, setupdatabuf); // interrupt handler will be called later }else if(epstatus & USB_EPnR_CTR_RX){ // data packet -> push received data to ep0databuf - EP_Read(0, (uint8_t*)&ep0databuf); + EP_Read(0, ep0databuf); } } } diff --git a/F0:F030,F042,F072/usbcan_ringbuffer/usbhw.h b/F0:F030,F042,F072/usbcan_ringbuffer/usbhw.h index 5d7f9e4..14d40d1 100644 --- a/F0:F030,F042,F072/usbcan_ringbuffer/usbhw.h +++ b/F0:F030,F042,F072/usbcan_ringbuffer/usbhw.h @@ -1,6 +1,6 @@ /* * This file is part of the usbcanrb project. - * Copyright 2022 Edward V. Emelianov . + * 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 @@ -25,18 +25,20 @@ /** * Buffers size definition **/ -// !!! when working with CAN bus change USB_BTABLE_SIZE to 768 !!! #define USB_BTABLE_SIZE 768 +// first 64 bytes of USB_BTABLE are registers! +//#define USB_EP0_BASEADDR 64 // for USB FS EP0 buffers are from 8 to 64 bytes long (64 for PL2303) #define USB_EP0_BUFSZ 64 // USB transmit buffer size (64 for PL2303) #define USB_TXBUFSZ 64 // USB receive buffer size (64 for PL2303) #define USB_RXBUFSZ 64 -// EP1 buffer size +// EP1 - interrupt - buffer size #define USB_EP1BUFSZ 8 -#define USB_BTABLE_BASE ((uint32_t)0x40006000) +#define USB_BTABLE_BASE 0x40006000 +#define USB ((USB_TypeDef *) USB_BASE) #ifdef USB_BTABLE #undef USB_BTABLE @@ -83,18 +85,31 @@ typedef struct { __IO uint32_t BCDR; } 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; 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); -int EP_Read(uint8_t number, uint8_t *buf); diff --git a/F0:F030,F042,F072/usbcan_ringbuffer/version.inc b/F0:F030,F042,F072/usbcan_ringbuffer/version.inc index 8443cc3..9445724 100644 --- a/F0:F030,F042,F072/usbcan_ringbuffer/version.inc +++ b/F0:F030,F042,F072/usbcan_ringbuffer/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "26" -#define BUILD_DATE "2023-01-31" +#define BUILD_NUMBER "34" +#define BUILD_DATE "2023-04-11" diff --git a/F3:F303/NitrogenFlooding/nitrogen.creator.user.cf63021 b/F3:F303/NitrogenFlooding/nitrogen.creator.user.cf63021 new file mode 100644 index 0000000..4a03d2d --- /dev/null +++ b/F3:F303/NitrogenFlooding/nitrogen.creator.user.cf63021 @@ -0,0 +1,160 @@ + + + + + + EnvironmentId + {cf63021e-ef53-49b0-b03b-2f2570cdf3b6} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + KOI8-R + false + 4 + false + 80 + true + true + 1 + false + false + false + 1 + true + true + 0 + 8 + true + false + 2 + true + true + true + *.md, *.MD, Makefile + true + true + + + + ProjectExplorer.Project.PluginSettings + + + true + true + Builtin.DefaultTidyAndClazy + 4 + + + + true + + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + Desktop + {91347f2c-5221-46a7-80b1-0a054ca02f79} + 0 + 0 + 0 + + /home/eddy/Docs/SAO/ELECTRONICS/STM32/F3-srcs/NitrogenFlooding + + + + all + + true + GenericProjectManager.GenericMakeStep + + 1 + Сборка + Сборка + ProjectExplorer.BuildSteps.Build + + + + + clean + + true + GenericProjectManager.GenericMakeStep + + 1 + Очистка + Очистка + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + По умолчанию + GenericProjectManager.GenericBuildConfiguration + + 1 + + + 0 + Развёртывание + Развёртывание + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + 2 + + ProjectExplorer.CustomExecutableRunConfiguration + + false + true + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + +