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 58a8119..b8c99a2 100755 Binary files a/F0:F030,F042,F072/usbcan_ringbuffer/usbcan.bin and b/F0:F030,F042,F072/usbcan_ringbuffer/usbcan.bin differ diff --git a/F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.config b/F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.config index 0402e5c..1ec56d2 100644 --- a/F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.config +++ b/F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.config @@ -3,3 +3,4 @@ #define EBUG #define STM32F0 #define STM32F042x6 +#define USB2_16 diff --git a/F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.creator.user b/F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.creator.user index 819893c..3f190b9 100644 --- a/F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.creator.user +++ b/F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.creator.user @@ -1,10 +1,10 @@ - + 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 + +