This commit is contained in:
2025-05-13 04:55:13 +03:00
parent 3f693566bd
commit ceb6d0ccec
4364 changed files with 2897163 additions and 0 deletions
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,10 @@
*** SESSION июня 11, 2016 17:02:26.51 ------------------------------------------
*** SESSION июня 11, 2016 17:03:15.86 ------------------------------------------
*** SESSION июня 11, 2016 17:16:58.28 ------------------------------------------
*** SESSION июня 11, 2016 17:22:26.47 ------------------------------------------
*** SESSION июня 11, 2016 17:25:39.76 ------------------------------------------
*** SESSION июня 11, 2016 17:28:50.70 ------------------------------------------
*** SESSION июня 11, 2016 17:45:50.07 ------------------------------------------
*** SESSION июня 12, 2016 14:31:08.97 ------------------------------------------
*** SESSION июня 13, 2016 09:50:26.20 ------------------------------------------
*** SESSION июня 14, 2016 16:36:46.82 ------------------------------------------
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><SharedRoot><SharedProperty id="prefix" value="arm-none-eabi-"/></SharedRoot>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<section name="Workbench">
<section name="org.eclipse.cdt.dsf.debug.internal.ui.ExpressionInformationControlCreator$ExpressionInformationControl">
<item value="500" key="SashWeightTree"/>
<item value="500" key="SashWeightDetails"/>
<item value="866" key="WIDTH"/>
<item value="654" key="HEIGHT"/>
</section>
</section>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<section name="Workbench">
<section name="org.eclipse.cdt.internal.ui.MakeView">
</section>
</section>
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<section name="Workbench">
<item value="../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" key="org.eclipse.cdt.utils.ui.controls.FileListControl"/>
<item value="Default C++ source template" key="LastUsedSourceTemplate"/>
<item value="Default C++ header template" key="LastUsedHeaderTemplate"/>
<section name="org.eclipse.cdt.ui.OPEN_ACTION_SELECTION_DIALOG_SECTION">
<item value="398" key="DIALOG_WIDTH"/>
<item value="1|Segoe UI|9.0|0|WINDOWS|1|-12|0|0|0|400|0|0|0|1|0|0|0|0|Segoe UI" key="DIALOG_FONT_NAME"/>
<item value="438" key="DIALOG_HEIGHT"/>
<item value="423" key="DIALOG_X_ORIGIN"/>
<item value="231" key="DIALOG_Y_ORIGIN"/>
</section>
<section name="org.eclipse.cdt.ui.text.hover.CMacroExpansionExploration.internal">
<item value="180" key="size.height"/>
<item value="593" key="size.width"/>
</section>
<section name="org.eclipse.cdt.ui.text.hover.CMacroExpansionExploration">
</section>
<section name="PDOMSearchPage">
</section>
<section name="completion_proposal_size">
</section>
</section>
@@ -0,0 +1,6 @@
01:16:00 **** Incremental Build of configuration Debug for project eeprom_programmer ****
make -j8 all
make: Nothing to be done for `all'.
01:16:00 Build Finished (took 173ms)
@@ -0,0 +1,319 @@
01:15:56 **** Build of configuration Debug for project eeprom_programmer ****
make -j8 all
'Building file: ../src/main_cpp.cpp'
'Building file: ../generated/Src/main.c'
'Building file: ../generated/Src/stm32f0xx_hal_msp.c'
'Building file: ../generated/Src/stm32f0xx_it.c'
'Building file: ../generated/Src/usb_device.c'
'Building file: ../generated/Src/usbd_cdc_if.c'
'Building file: ../generated/Src/usbd_conf.c'
'Building file: ../generated/Src/usbd_desc.c'
'Invoking: MCU G++ Compiler'
'Invoking: MCU GCC Compiler'
'Invoking: MCU GCC Compiler'
'Invoking: MCU GCC Compiler'
'Invoking: MCU GCC Compiler'
'Invoking: MCU GCC Compiler'
'Invoking: MCU GCC Compiler'
'Invoking: MCU GCC Compiler'
D:\f0projects\eeprom_programmer\Debug
D:\f0projects\eeprom_programmer\Debug
D:\f0projects\eeprom_programmer\Debug
D:\f0projects\eeprom_programmer\Debug
D:\f0projects\eeprom_programmer\Debug
D:\f0projects\eeprom_programmer\Debug
arm-none-eabi-g++ -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -std=c++1y -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -fno-exceptions -fno-rtti -MMD -MP -MF"src/main_cpp.d" -MT"src/main_cpp.o" -o "src/main_cpp.o" "../src/main_cpp.cpp"
D:\f0projects\eeprom_programmer\Debug
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Src/main.d" -MT"generated/Src/main.o" -o "generated/Src/main.o" "../generated/Src/main.c"
D:\f0projects\eeprom_programmer\Debug
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Src/stm32f0xx_hal_msp.d" -MT"generated/Src/stm32f0xx_hal_msp.o" -o "generated/Src/stm32f0xx_hal_msp.o" "../generated/Src/stm32f0xx_hal_msp.c"
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Src/stm32f0xx_it.d" -MT"generated/Src/stm32f0xx_it.o" -o "generated/Src/stm32f0xx_it.o" "../generated/Src/stm32f0xx_it.c"
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Src/usb_device.d" -MT"generated/Src/usb_device.o" -o "generated/Src/usb_device.o" "../generated/Src/usb_device.c"
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Src/usbd_cdc_if.d" -MT"generated/Src/usbd_cdc_if.o" -o "generated/Src/usbd_cdc_if.o" "../generated/Src/usbd_cdc_if.c"
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Src/usbd_conf.d" -MT"generated/Src/usbd_conf.o" -o "generated/Src/usbd_conf.o" "../generated/Src/usbd_conf.c"
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Src/usbd_desc.d" -MT"generated/Src/usbd_desc.o" -o "generated/Src/usbd_desc.o" "../generated/Src/usbd_desc.c"
../generated/Src/usbd_desc.c: In function 'USBD_FS_ProductStrDescriptor':
../generated/Src/usbd_desc.c:63:36: warning: pointer targets in passing argument 1 of 'USBD_GetString' differ in signedness [-Wpointer-sign]
#define USBD_PRODUCT_STRING_FS "EEPROM_programmer"
^
../generated/Src/usbd_desc.c:204:21: note: in expansion of macro 'USBD_PRODUCT_STRING_FS'
USBD_GetString (USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
^
In file included from D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h:40:0,
from ../generated/Src/usbd_desc.c:36:
D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h:93:6: note: expected 'uint8_t * {aka unsigned char *}' but argument is of type 'char *'
void USBD_GetString (uint8_t *desc, uint8_t *unicode, uint16_t *len);
^
../generated/Src/usbd_desc.c:63:36: warning: pointer targets in passing argument 1 of 'USBD_GetString' differ in signedness [-Wpointer-sign]
#define USBD_PRODUCT_STRING_FS "EEPROM_programmer"
^
../generated/Src/usbd_desc.c:208:21: note: in expansion of macro 'USBD_PRODUCT_STRING_FS'
USBD_GetString (USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
^
In file included from D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h:40:0,
from ../generated/Src/usbd_desc.c:36:
D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h:93:6: note: expected 'uint8_t * {aka unsigned char *}' but argument is of type 'char *'
void USBD_GetString (uint8_t *desc, uint8_t *unicode, uint16_t *len);
^
../generated/Src/usbd_desc.c: In function 'USBD_FS_ManufacturerStrDescriptor':
../generated/Src/usbd_desc.c:61:38: warning: pointer targets in passing argument 1 of 'USBD_GetString' differ in signedness [-Wpointer-sign]
#define USBD_MANUFACTURER_STRING "L"
^
../generated/Src/usbd_desc.c:222:19: note: in expansion of macro 'USBD_MANUFACTURER_STRING'
USBD_GetString (USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
^
In file included from D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h:40:0,
from ../generated/Src/usbd_desc.c:36:
D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h:93:6: note: expected 'uint8_t * {aka unsigned char *}' but argument is of type 'char *'
void USBD_GetString (uint8_t *desc, uint8_t *unicode, uint16_t *len);
^
../generated/Src/usbd_desc.c: In function 'USBD_FS_SerialStrDescriptor':
../generated/Src/usbd_desc.c:64:41: warning: pointer targets in passing argument 1 of 'USBD_GetString' differ in signedness [-Wpointer-sign]
#define USBD_SERIALNUMBER_STRING_FS "00000000001A"
^
../generated/Src/usbd_desc.c:237:21: note: in expansion of macro 'USBD_SERIALNUMBER_STRING_FS'
USBD_GetString (USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length);
^
In file included from D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h:40:0,
from ../generated/Src/usbd_desc.c:36:
D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h:93:6: note: expected 'uint8_t * {aka unsigned char *}' but argument is of type 'char *'
void USBD_GetString (uint8_t *desc, uint8_t *unicode, uint16_t *len);
^
../generated/Src/usbd_desc.c:64:41: warning: pointer targets in passing argument 1 of 'USBD_GetString' differ in signedness [-Wpointer-sign]
#define USBD_SERIALNUMBER_STRING_FS "00000000001A"
^
../generated/Src/usbd_desc.c:241:21: note: in expansion of macro 'USBD_SERIALNUMBER_STRING_FS'
USBD_GetString (USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length);
^
In file included from D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h:40:0,
from ../generated/Src/usbd_desc.c:36:
D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h:93:6: note: expected 'uint8_t * {aka unsigned char *}' but argument is of type 'char *'
void USBD_GetString (uint8_t *desc, uint8_t *unicode, uint16_t *len);
^
../generated/Src/usbd_desc.c: In function 'USBD_FS_ConfigStrDescriptor':
../generated/Src/usbd_desc.c:65:42: warning: pointer targets in passing argument 1 of 'USBD_GetString' differ in signedness [-Wpointer-sign]
#define USBD_CONFIGURATION_STRING_FS "CDC Config"
^
../generated/Src/usbd_desc.c:257:21: note: in expansion of macro 'USBD_CONFIGURATION_STRING_FS'
USBD_GetString (USBD_CONFIGURATION_STRING_FS, USBD_StrDesc, length);
^
In file included from D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h:40:0,
from ../generated/Src/usbd_desc.c:36:
D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h:93:6: note: expected 'uint8_t * {aka unsigned char *}' but argument is of type 'char *'
void USBD_GetString (uint8_t *desc, uint8_t *unicode, uint16_t *len);
^
../generated/Src/usbd_desc.c:65:42: warning: pointer targets in passing argument 1 of 'USBD_GetString' differ in signedness [-Wpointer-sign]
#define USBD_CONFIGURATION_STRING_FS "CDC Config"
^
../generated/Src/usbd_desc.c:261:21: note: in expansion of macro 'USBD_CONFIGURATION_STRING_FS'
USBD_GetString (USBD_CONFIGURATION_STRING_FS, USBD_StrDesc, length);
^
In file included from D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h:40:0,
from ../generated/Src/usbd_desc.c:36:
D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h:93:6: note: expected 'uint8_t * {aka unsigned char *}' but argument is of type 'char *'
void USBD_GetString (uint8_t *desc, uint8_t *unicode, uint16_t *len);
^
../generated/Src/usbd_desc.c: In function 'USBD_FS_InterfaceStrDescriptor':
../generated/Src/usbd_desc.c:66:38: warning: pointer targets in passing argument 1 of 'USBD_GetString' differ in signedness [-Wpointer-sign]
#define USBD_INTERFACE_STRING_FS "CDC Interface"
^
../generated/Src/usbd_desc.c:277:21: note: in expansion of macro 'USBD_INTERFACE_STRING_FS'
USBD_GetString (USBD_INTERFACE_STRING_FS, USBD_StrDesc, length);
^
In file included from D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h:40:0,
from ../generated/Src/usbd_desc.c:36:
D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h:93:6: note: expected 'uint8_t * {aka unsigned char *}' but argument is of type 'char *'
void USBD_GetString (uint8_t *desc, uint8_t *unicode, uint16_t *len);
^
../generated/Src/usbd_desc.c:66:38: warning: pointer targets in passing argument 1 of 'USBD_GetString' differ in signedness [-Wpointer-sign]
#define USBD_INTERFACE_STRING_FS "CDC Interface"
^
../generated/Src/usbd_desc.c:281:21: note: in expansion of macro 'USBD_INTERFACE_STRING_FS'
USBD_GetString (USBD_INTERFACE_STRING_FS, USBD_StrDesc, length);
^
In file included from D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h:40:0,
from ../generated/Src/usbd_desc.c:36:
D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h:93:6: note: expected 'uint8_t * {aka unsigned char *}' but argument is of type 'char *'
void USBD_GetString (uint8_t *desc, uint8_t *unicode, uint16_t *len);
^
'Finished building: ../generated/Src/stm32f0xx_hal_msp.c'
' '
'Finished building: ../generated/Src/main.c'
'Finished building: ../generated/Src/usbd_cdc_if.c'
'Finished building: ../generated/Src/stm32f0xx_it.c'
'Finished building: ../generated/Src/usb_device.c'
'Building file: ../generated/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c'
' '
'Finished building: ../generated/Src/usbd_desc.c'
'Finished building: ../generated/Src/usbd_conf.c'
' '
' '
' '
'Invoking: MCU GCC Compiler'
'Building file: ../generated/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c'
' '
' '
'Building file: ../generated/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c'
'Building file: ../generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c'
'Building file: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal.c'
../src/main_cpp.cpp: In member function 'virtual bool CmdEEPROMRead::Execute(IRequest*, IResponse*)':
../src/main_cpp.cpp:63:9: warning: unused variable 'result' [-Wunused-variable]
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
^
../src/main_cpp.cpp: In member function 'virtual bool CmdEEPROMWrite::Execute(IRequest*, IResponse*)':
../src/main_cpp.cpp:90:9: warning: unused variable 'result' [-Wunused-variable]
D:\f0projects\eeprom_programmer\Debug
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
^
../src/main_cpp.cpp: In constructor 'CommandProcessor::CommandProcessor()':
../src/main_cpp.cpp:343:7: warning: 'CommandProcessor::_last_byte_received' will be initialized after [-Wreorder]
bool _last_byte_received;
^
../src/main_cpp.cpp:340:10: warning: 'uint8_t CommandProcessor::_tx_bits_buffered' [-Wreorder]
uint8_t _tx_bits_buffered;
^
../src/main_cpp.cpp:141:2: warning: when initialized here [-Wreorder]
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
^
'Invoking: MCU GCC Compiler'
'Building file: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_cortex.c'
'Building file: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_dma.c'
'Invoking: MCU GCC Compiler'
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.d" -MT"generated/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.o" -o "generated/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.o" "../generated/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c"
'Invoking: MCU GCC Compiler'
'Invoking: MCU GCC Compiler'
D:\f0projects\eeprom_programmer\Debug
'Invoking: MCU GCC Compiler'
'Invoking: MCU GCC Compiler'
D:\f0projects\eeprom_programmer\Debug
D:\f0projects\eeprom_programmer\Debug
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.d" -MT"generated/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.o" -o "generated/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.o" "../generated/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c"
D:\f0projects\eeprom_programmer\Debug
D:\f0projects\eeprom_programmer\Debug
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.d" -MT"generated/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.o" -o "generated/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.o" "../generated/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c"
D:\f0projects\eeprom_programmer\Debug
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.d" -MT"generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.o" -o "generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.o" "../generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c"
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal.d" -MT"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal.o" -o "generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal.o" "../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal.c"
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_cortex.d" -MT"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_cortex.o" -o "generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_cortex.o" "../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_cortex.c"
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_dma.d" -MT"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_dma.o" -o "generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_dma.o" "../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_dma.c"
'Finished building: ../generated/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c'
'Finished building: ../src/main_cpp.cpp'
'Finished building: ../generated/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c'
'Finished building: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal.c'
'Finished building: ../generated/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c'
' '
' '
' '
' '
'Finished building: ../generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c'
' '
'Building file: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_flash.c'
'Finished building: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_cortex.c'
'Finished building: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_dma.c'
'Building file: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_flash_ex.c'
'Building file: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_gpio.c'
'Building file: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_i2c.c'
' '
'Building file: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_i2c_ex.c'
'Invoking: MCU GCC Compiler'
' '
' '
'Invoking: MCU GCC Compiler'
'Invoking: MCU GCC Compiler'
'Invoking: MCU GCC Compiler'
'Building file: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pcd.c'
'Invoking: MCU GCC Compiler'
D:\f0projects\eeprom_programmer\Debug
'Building file: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pcd_ex.c'
'Building file: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pwr.c'
D:\f0projects\eeprom_programmer\Debug
D:\f0projects\eeprom_programmer\Debug
D:\f0projects\eeprom_programmer\Debug
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_flash.d" -MT"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_flash.o" -o "generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_flash.o" "../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_flash.c"
'Invoking: MCU GCC Compiler'
D:\f0projects\eeprom_programmer\Debug
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_flash_ex.d" -MT"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_flash_ex.o" -o "generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_flash_ex.o" "../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_flash_ex.c"
'Invoking: MCU GCC Compiler'
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_gpio.d" -MT"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_gpio.o" -o "generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_gpio.o" "../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_gpio.c"
'Invoking: MCU GCC Compiler'
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_i2c.d" -MT"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_i2c.o" -o "generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_i2c.o" "../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_i2c.c"
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_i2c_ex.d" -MT"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_i2c_ex.o" -o "generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_i2c_ex.o" "../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_i2c_ex.c"
D:\f0projects\eeprom_programmer\Debug
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pcd.d" -MT"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pcd.o" -o "generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pcd.o" "../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pcd.c"
D:\f0projects\eeprom_programmer\Debug
D:\f0projects\eeprom_programmer\Debug
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pcd_ex.d" -MT"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pcd_ex.o" -o "generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pcd_ex.o" "../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pcd_ex.c"
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pwr.d" -MT"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pwr.o" -o "generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pwr.o" "../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pwr.c"
'Finished building: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_gpio.c'
'Finished building: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_flash.c'
' '
'Finished building: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pcd_ex.c'
' '
'Finished building: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_flash_ex.c'
' '
'Building file: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pwr_ex.c'
' '
'Building file: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_rcc.c'
'Building file: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_rcc_ex.c'
'Finished building: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_i2c_ex.c'
'Invoking: MCU GCC Compiler'
'Building file: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_tim.c'
'Invoking: MCU GCC Compiler'
'Invoking: MCU GCC Compiler'
' '
D:\f0projects\eeprom_programmer\Debug
'Invoking: MCU GCC Compiler'
D:\f0projects\eeprom_programmer\Debug
'Finished building: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pwr.c'
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pwr_ex.d" -MT"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pwr_ex.o" -o "generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pwr_ex.o" "../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pwr_ex.c"
D:\f0projects\eeprom_programmer\Debug
'Building file: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_tim_ex.c'
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_rcc.d" -MT"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_rcc.o" -o "generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_rcc.o" "../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_rcc.c"
D:\f0projects\eeprom_programmer\Debug
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_rcc_ex.d" -MT"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_rcc_ex.o" -o "generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_rcc_ex.o" "../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_rcc_ex.c"
' '
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_tim.d" -MT"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_tim.o" -o "generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_tim.o" "../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_tim.c"
'Invoking: MCU GCC Compiler'
'Building file: ../generated/Drivers/CMSIS/Device/ST/STM32F0xx/Source/Templates/gcc/startup_stm32f072xb.s'
D:\f0projects\eeprom_programmer\Debug
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_tim_ex.d" -MT"generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_tim_ex.o" -o "generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_tim_ex.o" "../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_tim_ex.c"
'Invoking: MCU GCC Assembler'
D:\f0projects\eeprom_programmer\Debug
'Finished building: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pcd.c'
arm-none-eabi-as -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -IC:/Ac6/SystemWorkbench/Debug/"D:/f0projects/eeprom_programmer/inc -IC:/Ac6/SystemWorkbench/Debug/"D:/f0projects/eeprom_programmer/generated/Inc -IC:/Ac6/SystemWorkbench/Debug/"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc -IC:/Ac6/SystemWorkbench/Debug/"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy -IC:/Ac6/SystemWorkbench/Debug/"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include -IC:/Ac6/SystemWorkbench/Debug/"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include -ID:/f0projects/eeprom_programmer/inc -g -o "generated/Drivers/CMSIS/Device/ST/STM32F0xx/Source/Templates/gcc/startup_stm32f072xb.o" "../generated/Drivers/CMSIS/Device/ST/STM32F0xx/Source/Templates/gcc/startup_stm32f072xb.s"
' '
'Finished building: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_i2c.c'
'Building file: ../generated/Drivers/CMSIS/Device/ST/STM32F0xx/Source/Templates/system_stm32f0xx.c'
' '
'Finished building: ../generated/Drivers/CMSIS/Device/ST/STM32F0xx/Source/Templates/gcc/startup_stm32f072xb.s'
'Invoking: MCU GCC Compiler'
' '
D:\f0projects\eeprom_programmer\Debug
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F072xB -DSTM32F072B_DISCO -DSTM32F072RBTx -DSTM32F0 -DSTM32 -DDEBUG -I"D:/f0projects/eeprom_programmer/inc" -I"D:/f0projects/eeprom_programmer/generated/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc" -I"D:/f0projects/eeprom_programmer/generated/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Include" -I"D:/f0projects/eeprom_programmer/generated/Drivers/CMSIS/Device/ST/STM32F0xx/Include" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" -I"D:/f0projects/eeprom_programmer/generated/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc" -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP -MF"generated/Drivers/CMSIS/Device/ST/STM32F0xx/Source/Templates/system_stm32f0xx.d" -MT"generated/Drivers/CMSIS/Device/ST/STM32F0xx/Source/Templates/system_stm32f0xx.o" -o "generated/Drivers/CMSIS/Device/ST/STM32F0xx/Source/Templates/system_stm32f0xx.o" "../generated/Drivers/CMSIS/Device/ST/STM32F0xx/Source/Templates/system_stm32f0xx.c"
'Finished building: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_tim.c'
'Finished building: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pwr_ex.c'
' '
' '
'Finished building: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_tim_ex.c'
'Finished building: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_rcc_ex.c'
' '
' '
'Finished building: ../generated/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_rcc.c'
' '
'Finished building: ../generated/Drivers/CMSIS/Device/ST/STM32F0xx/Source/Templates/system_stm32f0xx.c'
' '
'Building target: eeprom_programmer.elf'
'Invoking: MCU G++ Linker'
arm-none-eabi-g++ -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -specs=nosys.specs -specs=nano.specs -T"D:\f0projects\eeprom_programmer\LinkerScript.ld" -Wl,-Map=output.map -Wl,--gc-sections -fno-exceptions -fno-rtti -lm -o "eeprom_programmer.elf" @"objects.list"
'Finished building target: eeprom_programmer.elf'
' '
make --no-print-directory post-build
'Generating binary and Printing size information:'
arm-none-eabi-objcopy -O binary "eeprom_programmer.elf" "eeprom_programmer.bin"
arm-none-eabi-size "eeprom_programmer.elf"
text data bss dec hex filename
74680 480 3428 78588 132fc eeprom_programmer.elf
' '
01:16:00 **** Incremental Build of configuration Debug for project eeprom_programmer ****
make -j8 all
make: Nothing to be done for `all'.
@@ -0,0 +1,307 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
#include "usbd_def.h"
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
//uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
/* Send Data over USB CDC are stored in this buffer */
//uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
__weak void OnCdcDisconnect(){}
__weak void OnCdcInit(){}
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
OnCdcInit();
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
USBD_SetupReqTypedef* req = (USBD_SetupReqTypedef*)pbuf;
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
if(req->wValue == 0){
OnCdcDisconnect();
}
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete =1;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,360 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(tx_buffer)){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct CmdEcho : public Command{
bool Execute(IRequest* request, IResponse* response) override {
uint32_t data;
if(!request->Read(data)){
return false;
}
if(!response->Write((uint8_t*)&data, sizeof(data))){
return false;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
CmdEcho cmd_echo;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
case CommandId::Echo:
return &cmd_echo;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 1;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
if(!_connected){
return false;
}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,321 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
};
struct UsbRxBuffer rx_buffer;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = Len;
return (USBD_OK);
/* USER CODE END 6 */
}
static uint32_t CDC_Read(uint8_t* buffer, uint32_t size){
size_t i;
if(size == 0){
return 0;
}
while(size > 0){
if(rx_buffer.position >= rx_buffer.size){
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.position >= rx_buffer.size){
}
}
}
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,342 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length) = 0;
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(&tx_buffer[0], sizeof(tx_buffer))){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _tx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_tx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _tx_bits_buffer & 0xff;
--length;
received++;
_tx_bits_buffer >>= 8;
}
}
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
while(true){
switch(cmd){
case CommandId::EEPROMReadBuffer:{
}
break;
case CommandId::EEPROMWriteBuffer:{
}
break;
}
HAL_GPIO_TogglePin(LD4_GPIO_Port, LD4_Pin);
}
}
@@ -0,0 +1,17 @@
/*
* commands.h
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#ifndef COMMANDS_H_
#define COMMANDS_H_
enum class CommandId {
};
#endif /* COMMANDS_H_ */
@@ -0,0 +1,23 @@
/*
* commands.h
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#ifndef COMMANDS_H_
#define COMMANDS_H_
#include <cstdint>
enum class CommandId : uint32_t{
EEPROMReadBuffer,
EEPROMWriteBuffer
};
struct CmdEEPROMReadBufferArgs {
uint32_t startAddress;
size_t
};
#endif /* COMMANDS_H_ */
@@ -0,0 +1,357 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(tx_buffer)){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct CmdEcho : public Command{
bool Execute(IRequest* request, IResponse* response) override {
/*uint32_t size;
if(!request->Read(size)){
return false;
}*/
uint32_t data;
if(!request->Read(data)){
return false;
}
if(!response->Write((uint8_t*)&data, sizeof(data))){
return false;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,360 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(tx_buffer)){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct CmdEcho : public Command{
bool Execute(IRequest* request, IResponse* response) override {
uint32_t data;
if(!request->Read(data)){
return false;
}
if(!response->Write((uint8_t*)&data, sizeof(data))){
return false;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
CmdEcho cmd_echo;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
case CommandId::Echo:
return &cmd_echo;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 1;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
if(!_connected){
return false;
}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,22 @@
/*
* commands.h
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#ifndef COMMANDS_H_
#define COMMANDS_H_
#include <cstdint>
enum class CommandId : uint32_t{
EEPROMReadBuffer,
EEPROMWriteBuffer
};
struct CmdEEPROMReadBufferArtgs {
};
#endif /* COMMANDS_H_ */
@@ -0,0 +1,342 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length) = 0;
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(&tx_buffer[0], sizeof(tx_buffer))){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _bits_buffer & 0xff;
--length;
received++;
_bits_buffer >>= 8;
}
}
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
while(true){
switch(cmd){
case CommandId::EEPROMReadBuffer:{
}
break;
case CommandId::EEPROMWriteBuffer:{
}
break;
}
HAL_GPIO_TogglePin(LD4_GPIO_Port, LD4_Pin);
}
}
@@ -0,0 +1,353 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(tx_buffer)){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct CmdEcho : public Command{
bool Execute(IRequest* request, IResponse* response) override {
/*uint32_t size;
if(!request->Read(size)){
return false;
}*/
uint32_t data;
if(!request->Read(size)){
return false;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,330 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
};
struct UsbRxBuffer rx_buffer;
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = Len;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
void CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return;
}
while(size > 0){
if(rx_buffer.position >= rx_buffer.size){
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.position >= rx_buffer.size){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position];
rx_buffer.position++;
buffer += block_size;
}
}
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,19 @@
/*
* commands.h
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#ifndef COMMANDS_H_
#define COMMANDS_H_
#include <cstdint>
enum class CommandId {
EEPROMReadBuffer,
EEPROMWriteBuffer
};
#endif /* COMMANDS_H_ */
@@ -0,0 +1,331 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
};
struct UsbRxBuffer rx_buffer;
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = Len;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
void CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return;
}
while(size > 0){
if(rx_buffer.position >= rx_buffer.size){
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.position >= rx_buffer.size){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position];
rx_buffer.position++;
buffer += block_size;
}
}
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,358 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(tx_buffer)){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct CmdEcho : public Command{
bool Execute(IRequest* request, IResponse* response) override {
uint32_t data;
if(!request->Read(data)){
return false;
}
if(!response->Write((uint8_t*)&data, sizeof(data))){
return false;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
CmdEcho cmd_echo;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
case CommandId::Echo:
return &cmd_echo;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 1;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(!_connected){
return false;
}
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,19 @@
/*
* commands.h
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#ifndef COMMANDS_H_
#define COMMANDS_H_
#include <cstdint>
enum class CommandId : uint32_t{
EEPROMReadBuffer,
EEPROMWriteBuffer
};
#endif /* COMMANDS_H_ */
@@ -0,0 +1,357 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(tx_buffer)){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct CmdEcho : public Command{
bool Execute(IRequest* request, IResponse* response) override {
/*uint32_t size;
if(!request->Read(size)){
return false;
}*/
uint32_t data;
if(!request->Read(data)){
return false;
}
if(!response->Write(data)){
return false;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,343 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(tx_buffer)){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct CmdEcho : public Command{
bool Execute(IRequest* request, IResponse* response) override {
uint32_t size;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,23 @@
/*
* commands.h
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#ifndef COMMANDS_H_
#define COMMANDS_H_
#include <cstdint>
enum class CommandId : uint32_t{
EEPROMReadBuffer,
EEPROMWriteBuffer
};
struct CmdEEPROMReadBufferArgs {
uint32_t startAddress;
uint32_t size;
};
#endif /* COMMANDS_H_ */
@@ -0,0 +1,361 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(tx_buffer)){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct CmdEcho : public Command{
bool Execute(IRequest* request, IResponse* response) override {
uint32_t data;
if(!request->Read(data)){
return false;
}
if(!response->Write((uint8_t*)&data, sizeof(data))){
return false;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
CmdEcho cmd_echo;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
case CommandId::Echo:
return &cmd_echo;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 1;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
if(!_connected){
return false;
}
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,17 @@
/*
* commands.h
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#ifndef COMMANDS_H_
#define COMMANDS_H_
enum class Commands {
};
#endif /* COMMANDS_H_ */
@@ -0,0 +1,344 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
struct UsbRxBuffer rx_buffer;
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete =0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete =1;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
void CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return;
}
while(vcp_initialized == 0){
}
while(size > 0){
while(rx_buffer.read_complete == 0){
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position];
rx_buffer.position++;
buffer += block_size;
}
}
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,346 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
struct UsbRxBuffer rx_buffer;
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
//uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
/* Send Data over USB CDC are stored in this buffer */
//uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete =0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete =1;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
void CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return;
}
while(vcp_initialized == 0){
}
while(size > 0){
while(rx_buffer.read_complete == 0){
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,330 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
};
struct UsbRxBuffer rx_buffer;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = Len;
return (USBD_OK);
/* USER CODE END 6 */
}
static uint32_t CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return 0;
}
while(size > 0){
if(rx_buffer.position >= rx_buffer.size){
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.position >= rx_buffer.size){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position];
rx_buffer.position++;
buffer += block_size;
}
}
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,360 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(tx_buffer)){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct CmdEcho : public Command{
bool Execute(IRequest* request, IResponse* response) override {
uint32_t data;
if(!request->Read(data)){
return false;
}
if(!response->Write((uint8_t*)&data, sizeof(data))){
return false;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
CmdEcho cmd_echo;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
case CommandId::Echo:
return &cmd_echo;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 1;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
if(!_connected){
return false;
}
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,360 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(tx_buffer)){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct CmdEcho : public Command{
bool Execute(IRequest* request, IResponse* response) override {
uint32_t data;
if(!request->Read(data)){
return false;
}
if(!response->Write((uint8_t*)&data, sizeof(data))){
return false;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
CmdEcho cmd_echo;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
case CommandId::Echo:
return &cmd_echo;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 1;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
if(!_connected){
return false;
}
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,341 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length) = 0;
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(&tx_buffer[0], sizeof(tx_buffer))){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _bits_buffer & 0xff;
--length;
received++;
_bits_buffer >>= 8;
}
}
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
while(true){
switch(cmd){
case CommandId::EEPROMReadBuffer:{
}
break;
case CommandId::EEPROMWriteBuffer:{
}
break;
}
HAL_GPIO_TogglePin(LD4_GPIO_Port, LD4_Pin);
}
}
@@ -0,0 +1,349 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
struct UsbRxBuffer rx_buffer;
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
//uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
/* Send Data over USB CDC are stored in this buffer */
//uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete =0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
struct USBD_SetupReqTypedef* request = (USBD_SetupReqTypedef*)pbuf;
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
cmd = pbuf[0];
cmd++;
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete =1;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
void CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return;
}
while(vcp_initialized == 0){
}
while(size > 0){
while(rx_buffer.read_complete == 0){
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,333 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(const T& value){
uint32_t rx;
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(&tx_buffer[0], sizeof(tx_buffer))){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,82 @@
/**
*****************************************************************************
**
** File : sysmem.c
**
** Author : Ac6
**
** Abstract : System Workbench Minimal System Memory calls file
**
** For more information about which c-functions
** need which of these lowlevel functions
** please consult the Newlib libc-manual
**
** Environment : System Workbench for MCU
**
** Distribution: The file is distributed “as is,” without any warranty
** of any kind.
**
*****************************************************************************
**
** <h2><center>&copy; COPYRIGHT(c) 2014 Ac6</center></h2>
**
** Redistribution and use in source and binary forms, with or without modification,
** are permitted provided that the following conditions are met:
** 1. Redistributions of source code must retain the above copyright notice,
** this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright notice,
** this list of conditions and the following disclaimer in the documentation
** and/or other materials provided with the distribution.
** 3. Neither the name of Ac6 nor the names of its contributors
** may be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
*****************************************************************************
*/
/* Includes */
#include <errno.h>
#include <stdio.h>
/* Variables */
extern int errno;
register char * stack_ptr asm("sp");
/* Functions */
/**
_sbrk
Increase program data space. Malloc and related functions depend on this
**/
caddr_t _sbrk(int incr)
{
extern char end asm("end");
static char *heap_end;
char *prev_heap_end;
if (heap_end == 0)
heap_end = &end;
prev_heap_end = heap_end;
if (heap_end + incr > stack_ptr)
{
errno = ENOMEM;
return (caddr_t) -1;
}
heap_end += incr;
return (caddr_t) prev_heap_end;
}
@@ -0,0 +1,343 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
struct UsbRxBuffer rx_buffer;
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete =0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = Len;
rx_buffer.read_complete =1;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
void CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return;
}
while(vcp_initialized == 0){
}
while(size > 0){
while(rx_buffer.read_complete == 0){
}
if(rx_buffer.position >= rx_buffer.size){
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
rx_buffer.read_complete = 0;
while(rx_buffer.read_complete == 0){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position];
rx_buffer.position++;
buffer += block_size;
}
}
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,340 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(tx_buffer)){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct CmdEcho : public Command{
bool Execute(IRequest* request, IResponse* response) override {
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,323 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
};
struct UsbRxBuffer rx_buffer;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = Len;
return (USBD_OK);
/* USER CODE END 6 */
}
static uint32_t CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return 0;
}
while(size > 0){
if(rx_buffer.position >= rx_buffer.size){
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.position >= rx_buffer.size){
}
}
}
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,355 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(tx_buffer)){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct CmdEcho : public Command{
bool Execute(IRequest* request, IResponse* response) override {
uint32_t data;
if(!request->Read(data)){
return false;
}
if(!response->Write((uint8_t*)&data, sizeof(data))){
return false;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
CmdEcho cmd_echo;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
case CommandId::Echo:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,343 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length) = 0;
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(&tx_buffer[0], sizeof(tx_buffer))){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
while(true){
switch(cmd){
case CommandId::EEPROMReadBuffer:{
}
break;
case CommandId::EEPROMWriteBuffer:{
}
break;
}
HAL_GPIO_TogglePin(LD4_GPIO_Port, LD4_Pin);
}
}
@@ -0,0 +1,28 @@
/*
* commands.h
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#ifndef COMMANDS_H_
#define COMMANDS_H_
#include <cstdint>
enum class CommandId : uint32_t{
EEPROMReadBuffer,
EEPROMWriteBuffer
};
struct CmdEEPROMReadBufferArgs {
uint32_t startAddress;
uint32_t size;
};
struct CmdEEPROMReadBufferArgs {
uint32_t startAddress;
uint32_t size;
};
#endif /* COMMANDS_H_ */
@@ -0,0 +1,328 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
};
struct UsbRxBuffer rx_buffer;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = Len;
return (USBD_OK);
/* USER CODE END 6 */
}
static uint32_t CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return 0;
}
while(size > 0){
if(rx_buffer.position >= rx_buffer.size){
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.position >= rx_buffer.size){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position];
}
}
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,323 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
};
struct UsbRxBuffer rx_buffer;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = Len;
return (USBD_OK);
/* USER CODE END 6 */
}
static uint32_t CDC_Read(uint8_t* buffer, uint32_t size){
size_t i;
size_t i;
if(size == 0){
return 0;
}
while(size > 0){
if(rx_buffer.position >= rx_buffer.size){
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.position >= rx_buffer.size){
}
}
}
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,22 @@
/*
* commands.h
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#ifndef COMMANDS_H_
#define COMMANDS_H_
#include <cstdint>
enum class CommandId : uint32_t{
EEPROMReadBuffer,
EEPROMWriteBuffer
};
struct CmdEEPROMReadBufferArgs {
size_t address;
};
#endif /* COMMANDS_H_ */
@@ -0,0 +1,22 @@
/*
* commands.h
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#ifndef COMMANDS_H_
#define COMMANDS_H_
#include <cstdint>
enum class CommandId : uint32_t{
EEPROMReadBuffer,
EEPROMWriteBuffer
};
struct CmdEEPROMReadBufferArgs {
};
#endif /* COMMANDS_H_ */
@@ -0,0 +1,307 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
#include "usbd_def.h"
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
//uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
/* Send Data over USB CDC are stored in this buffer */
//uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
__weak void OnCdcDisconnect(){
}
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
USBD_SetupReqTypedef* req = (USBD_SetupReqTypedef*)pbuf;
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
if(req->wValue == 0){
OnCdcDisconnect();
}
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete =1;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,352 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(tx_buffer)){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct CmdEcho : public Command{
bool Execute(IRequest* request, IResponse* response) override {
uint32_t data;
if(!request->Read(data)){
return false;
}
if(!response->Write((uint8_t*)&data, sizeof(data))){
return false;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,353 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(tx_buffer)){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct CmdEcho : public Command{
bool Execute(IRequest* request, IResponse* response) override {
/*uint32_t size;
if(!request->Read(size)){
return false;
}*/
uint32_t data;
if(!request->Read(data)){
return false;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,15 @@
/*
* commands.h
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#ifndef COMMANDS_H_
#define COMMANDS_H_
#endif /* COMMANDS_H_ */
@@ -0,0 +1,317 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
#include "usbd_def.h"
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
struct UsbRxBuffer rx_buffer;
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
//uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
/* Send Data over USB CDC are stored in this buffer */
//uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
__weak void OnCdcDisconnect(){
}
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete =0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
USBD_SetupReqTypedef* req = (USBD_SetupReqTypedef*)pbuf;
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
if(req->wValue == 0){
OnCdcDisconnect();
}
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete =1;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,361 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(tx_buffer)){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct CmdEcho : public Command{
bool Execute(IRequest* request, IResponse* response) override {
uint32_t data;
if(!request->Read(data)){
return false;
}
if(!response->Write((uint8_t*)&data, sizeof(data))){
return false;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
CmdEcho cmd_echo;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
case CommandId::Echo:
return &cmd_echo;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 1;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
if(!_connected){
return false;
}
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,362 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(tx_buffer)){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct CmdEcho : public Command{
bool Execute(IRequest* request, IResponse* response) override {
uint32_t data;
if(!request->Read(data)){
return false;
}
if(!response->Write((uint8_t*)&data, sizeof(data))){
return false;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
CmdEcho cmd_echo;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
case CommandId::Echo:
return &cmd_echo;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 1;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
if(!_connected){
return false;
}
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
UsbRxBuffer rx_buffer;
bool _connected;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,337 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(&tx_buffer[0], sizeof(tx_buffer))){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,345 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
struct UsbRxBuffer rx_buffer;
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete =0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete =1;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
void CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return;
}
while(vcp_initialized == 0){
}
while(size > 0){
while(rx_buffer.read_complete == 0){
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position];
rx_buffer.position++;
buffer += block_size;
size -= block_size;
}
}
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,327 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
};
struct UsbRxBuffer rx_buffer;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = Len;
return (USBD_OK);
/* USER CODE END 6 */
}
static void CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return 0;
}
while(size > 0){
if(rx_buffer.position >= rx_buffer.size){
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.position >= rx_buffer.size){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position];
rx_buffer.position++;
buffer += block_size;
}
}
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,341 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length) = 0;
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(&tx_buffer[0], sizeof(tx_buffer))){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if((_bits_transmitted) % 8 != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _bits_buffer & 0xff;
--length;
received++;
_bits_buffer >>= 8;
}
}
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
while(true){
switch(cmd){
case CommandId::EEPROMReadBuffer:{
}
break;
case CommandId::EEPROMWriteBuffer:{
}
break;
}
HAL_GPIO_TogglePin(LD4_GPIO_Port, LD4_Pin);
}
}
@@ -0,0 +1,328 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
};
struct UsbRxBuffer rx_buffer;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = Len;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
void CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return;
}
while(size > 0){
if(rx_buffer.position >= rx_buffer.size){
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.position >= rx_buffer.size){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position];
rx_buffer.position++;
buffer += block_size;
}
}
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,335 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
struct UsbRxBuffer rx_buffer;
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = Len;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
void CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return;
}
while(vcp_initialized == 0){
}
while(size > 0){
if(rx_buffer.position >= rx_buffer.size){
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.position >= rx_buffer.size){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position];
rx_buffer.position++;
buffer += block_size;
}
}
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,336 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
}
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(&tx_buffer[0], sizeof(tx_buffer))){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,346 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(tx_buffer)){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct CmdEcho : public Command{
bool Execute(IRequest* request, IResponse* response) override {
uint32_t size;
if(!request->Read(size)){
return false;
}
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,309 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
#include "usbd_def.h"
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
//uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
/* Send Data over USB CDC are stored in this buffer */
//uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
__weak void OnCdcDisconnect(){}
__weak void OnCdcInit(){}
__weak void OnCdcReceive(uint8_t* Buf, uint32_t *Len){}
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
OnCdcInit();
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
USBD_SetupReqTypedef* req = (USBD_SetupReqTypedef*)pbuf;
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
if(req->wValue == 0){
OnCdcDisconnect();
}
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete =1;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,337 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(tx_buffer)){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,346 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
struct UsbRxBuffer rx_buffer;
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
/* Send Data over USB CDC are stored in this buffer */
uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete =0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete =1;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
void CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return;
}
while(vcp_initialized == 0){
}
while(size > 0){
while(rx_buffer.read_complete == 0){
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,310 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
#include "usbd_def.h"
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
//uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
/* Send Data over USB CDC are stored in this buffer */
//uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
__weak void OnCdcDisconnect(){
}
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete =0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
USBD_SetupReqTypedef* req = (USBD_SetupReqTypedef*)pbuf;
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
if(req->wValue == 0){
OnCdcDisconnect();
}
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete =1;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,334 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
};
struct UsbRxBuffer rx_buffer;
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = Len;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
void CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return;
}
while(vcp_initialized == 0){
}
while(size > 0){
if(rx_buffer.position >= rx_buffer.size){
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.position >= rx_buffer.size){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position];
rx_buffer.position++;
buffer += block_size;
}
}
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,343 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
struct UsbRxBuffer rx_buffer;
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete =0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = Len;
rx_buffer.read_complete =1;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
void CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return;
}
while(vcp_initialized == 0){
}
while(size > 0){
while(rx_buffer.read_complete == 0){
}
if(rx_buffer.position >= rx_buffer.size){
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
rx_buffer.read_complete = 0;
while(rx_buffer.read_complete == 0){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position];
rx_buffer.position++;
buffer += block_size;
}
}
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,342 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length) = 0;
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(&tx_buffer[0], sizeof(tx_buffer))){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
while(true){
switch(cmd){
case CommandId::EEPROMReadBuffer:{
}
break;
case CommandId::EEPROMWriteBuffer:{
}
break;
}
HAL_GPIO_TogglePin(LD4_GPIO_Port, LD4_Pin);
}
}
@@ -0,0 +1,346 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
struct UsbRxBuffer rx_buffer;
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
//uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
/* Send Data over USB CDC are stored in this buffer */
//uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete =0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
cmd++;
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete =1;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
void CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return;
}
while(vcp_initialized == 0){
}
while(size > 0){
while(rx_buffer.read_complete == 0){
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,246 @@
/**
******************************************************************************
* @file startup_stm32.s
* @author Ac6
* @version V1.0.0
* @date 12-June-2014
******************************************************************************
*/
.syntax unified
.cpu cortex-m0
.thumb
.global g_pfnVectors
.global Default_Handler
/* start address for the initialization values of the .data section.
defined in linker script */
.word _sidata
/* start address for the .data section. defined in linker script */
.word _sdata
/* end address for the .data section. defined in linker script */
.word _edata
/* start address for the .bss section. defined in linker script */
.word _sbss
/* end address for the .bss section. defined in linker script */
.word _ebss
.equ BootRAM, 0xF1E0F85F
/**
* @brief This is the code that gets called when the processor first
* starts execution following a reset event. Only the absolutely
* necessary set is performed, after which the application
* supplied main() routine is called.
* @param None
* @retval : None
*/
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
/* Copy the data segment initializers from flash to SRAM */
movs r1, #0
b LoopCopyDataInit
CopyDataInit:
ldr r3, =_sidata
ldr r3, [r3, r1]
str r3, [r0, r1]
adds r1, r1, #4
LoopCopyDataInit:
ldr r0, =_sdata
ldr r3, =_edata
adds r2, r0, r1
cmp r2, r3
bcc CopyDataInit
ldr r2, =_sbss
b LoopFillZerobss
/* Zero fill the bss segment. */
FillZerobss:
movs r3, #0
str r3, [r2]
adds r2, r2, #4
LoopFillZerobss:
ldr r3, = _ebss
cmp r2, r3
bcc FillZerobss
/* Call the clock system intitialization function.*/
bl SystemInit
/* Call static constructors */
bl __libc_init_array
/* Call the application's entry point.*/
bl main
LoopForever:
b LoopForever
.size Reset_Handler, .-Reset_Handler
/**
* @brief This is the code that gets called when the processor receives an
* unexpected interrupt. This simply enters an infinite loop, preserving
* the system state for examination by a debugger.
*
* @param None
* @retval : None
*/
.section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
b Infinite_Loop
.size Default_Handler, .-Default_Handler
/******************************************************************************
*
* The minimal vector table for a Cortex-M. Note that the proper constructs
* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
*
******************************************************************************/
.section .isr_vector,"a",%progbits
.type g_pfnVectors, %object
.size g_pfnVectors, .-g_pfnVectors
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
.word UsageFault_Handler
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word DebugMon_Handler
.word 0
.word PendSV_Handler
.word SysTick_Handler
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
/*******************************************************************************
*
* Provide weak aliases for each Exception handler to the Default_Handler.
* As they are weak aliases, any function with the same name will override
* this definition.
*
*******************************************************************************/
.weak NMI_Handler
.thumb_set NMI_Handler,Default_Handler
.weak HardFault_Handler
.thumb_set HardFault_Handler,Default_Handler
.weak MemManage_Handler
.thumb_set MemManage_Handler,Default_Handler
.weak BusFault_Handler
.thumb_set BusFault_Handler,Default_Handler
.weak UsageFault_Handler
.thumb_set UsageFault_Handler,Default_Handler
.weak SVC_Handler
.thumb_set SVC_Handler,Default_Handler
.weak DebugMon_Handler
.thumb_set DebugMon_Handler,Default_Handler
.weak PendSV_Handler
.thumb_set PendSV_Handler,Default_Handler
.weak SysTick_Handler
.thumb_set SysTick_Handler,Default_Handler
.weak SystemInit
/************************ (C) COPYRIGHT Ac6 *****END OF FILE****/
@@ -0,0 +1,349 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
struct UsbRxBuffer rx_buffer;
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
//uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
/* Send Data over USB CDC are stored in this buffer */
//uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete =0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
struct USBD_SetupReqTypedef* req = (USBD_SetupReqTypedef*)pbuf;
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
cmd = req->wValue;
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete =1;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
void CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return;
}
while(vcp_initialized == 0){
}
while(size > 0){
while(rx_buffer.read_complete == 0){
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,342 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length) = 0;
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(&tx_buffer[0], sizeof(tx_buffer))){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_tx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _bits_buffer & 0xff;
--length;
received++;
_bits_buffer >>= 8;
}
}
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
while(true){
switch(cmd){
case CommandId::EEPROMReadBuffer:{
}
break;
case CommandId::EEPROMWriteBuffer:{
}
break;
}
HAL_GPIO_TogglePin(LD4_GPIO_Port, LD4_Pin);
}
}
@@ -0,0 +1,343 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
struct UsbRxBuffer rx_buffer;
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete =0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = Len;
rx_buffer.read_complete =1;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
void CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return;
}
while(vcp_initialized == 0){
}
while(size > 0){
while(rx_buffer.read_complete == 0){
}
if(rx_buffer.position >= rx_buffer.size){
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
rx_buffer.read_complete = 0;
while(rx_buffer.position >= rx_buffer.size){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position];
rx_buffer.position++;
buffer += block_size;
}
}
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,348 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(tx_buffer)){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct CmdEcho : public Command{
bool Execute(IRequest* request, IResponse* response) override {
uint32_t size;
if(!request->Read(size)){
return false;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,121 @@
/**
******************************************************************************
* @file : usbd_cdc_if.h
* @brief : Header for usbd_cdc_if file.
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_CDC_IF_H
#define __USBD_CDC_IF_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC_IF
* @brief header
* @{
*/
/** @defgroup USBD_CDC_IF_Exported_Defines
* @{
*/
/* USER CODE BEGIN EXPORTED_DEFINES */
/* USER CODE END EXPORTED_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Types
* @{
*/
/* USER CODE BEGIN EXPORTED_TYPES */
/* USER CODE END EXPORTED_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Macros
* @{
*/
/* USER CODE BEGIN EXPORTED_MACRO */
/* USER CODE END EXPORTED_MACRO */
/**
* @}
*/
/** @defgroup USBD_AUDIO_IF_Exported_Variables
* @{
*/
extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_FunctionsPrototype
* @{
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len);
/* USER CODE BEGIN EXPORTED_FUNCTIONS */
/* USER CODE END EXPORTED_FUNCTIONS */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_CDC_IF_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,329 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(&tx_buffer[0], sizeof(tx_buffer))){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,306 @@
/**
******************************************************************************
* File Name : main.c
* Description : Main program body
******************************************************************************
*
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f0xx_hal.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void Error_Handler(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/** System Clock Configuration
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInit;
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL6;
RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C1;
PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_HSI;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/* I2C1 init function */
static void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0x2000090E;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
/**Configure Analogue filter
*/
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
{
Error_Handler();
}
}
/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
PA2 ------> TSC_G1_IO3
PA3 ------> TSC_G1_IO4
PA6 ------> TSC_G2_IO3
PA7 ------> TSC_G2_IO4
PB0 ------> TSC_G3_IO2
PB1 ------> TSC_G3_IO3
PB10 ------> I2C2_SCL
PB11 ------> I2C2_SDA
PB13 ------> SPI2_SCK
PB14 ------> SPI2_MISO
PB15 ------> SPI2_MOSI
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, NCS_MEMS_SPI_Pin|EXT_RESET_Pin|LD3_Pin|LD6_Pin
|LD4_Pin|LD5_Pin, GPIO_PIN_RESET);
/*Configure GPIO pins : NCS_MEMS_SPI_Pin EXT_RESET_Pin LD3_Pin LD6_Pin
LD4_Pin LD5_Pin */
GPIO_InitStruct.Pin = NCS_MEMS_SPI_Pin|EXT_RESET_Pin|LD3_Pin|LD6_Pin
|LD4_Pin|LD5_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pins : MEMS_INT1_Pin MEMS_INT2_Pin */
GPIO_InitStruct.Pin = MEMS_INT1_Pin|MEMS_INT2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_EVT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pin : B1_Pin */
GPIO_InitStruct.Pin = B1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_EVT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : PA2 PA3 PA6 PA7 */
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF3_TSC;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PB0 PB1 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF3_TSC;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pins : PB10 PB11 */
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_I2C2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pins : PB13 PB14 PB15 */
GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF0_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @param None
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler */
/* User can add his own implementation to report the HAL error return state */
while(1)
{
}
/* USER CODE END Error_Handler */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,337 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
struct UsbRxBuffer rx_buffer;
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete =0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = Len;
rx_buffer.read_complete =1;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
void CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return;
}
while(vcp_initialized == 0){
}
while(size > 0){
if(rx_buffer.position >= rx_buffer.size){
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.position >= rx_buffer.size){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position];
rx_buffer.position++;
buffer += block_size;
}
}
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,350 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
#include "usbd_def.h"
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
struct UsbRxBuffer rx_buffer;
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
//uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
/* Send Data over USB CDC are stored in this buffer */
//uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete =0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
USBD_SetupReqTypedef* req = (USBD_SetupReqTypedef*)pbuf;
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
cmd = req->wValue;
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete =1;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
void CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return;
}
while(vcp_initialized == 0){
}
while(size > 0){
while(rx_buffer.read_complete == 0){
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,353 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
#include "usbd_def.h"
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
struct UsbRxBuffer rx_buffer;
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
//uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
/* Send Data over USB CDC are stored in this buffer */
//uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
__weak void OnCdcDisconnect(){
}
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete =0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
USBD_SetupReqTypedef* req = (USBD_SetupReqTypedef*)pbuf;
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
cmd = req->wValue;
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete =1;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
void CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return;
}
while(vcp_initialized == 0){
}
while(size > 0){
while(rx_buffer.read_complete == 0){
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,28 @@
/*
* commands.h
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#ifndef COMMANDS_H_
#define COMMANDS_H_
#include <cstdint>
enum class CommandId : uint32_t{
EEPROMReadBuffer,
EEPROMWriteBuffer
};
struct CmdEEPROMReadBufferArgs {
uint32_t startAddress;
uint32_t size;
};
struct CmdEEPROMWriteBufferArgs {
uint32_t startAddress;
uint32_t size;
};
#endif /* COMMANDS_H_ */
@@ -0,0 +1,349 @@
/**
******************************************************************************
* @file : usbd_cdc_if.c
* @brief :
******************************************************************************
* COPYRIGHT(c) 2016 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
struct UsbRxBuffer rx_buffer;
uint32_t vcp_initialized = 0;
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
//uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
/* Send Data over USB CDC are stored in this buffer */
//uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete =0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
vcp_initialized = 1;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
vcp_initialized = 0;
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
struct USBD_SetupReqTypedef* req = (USBD_SetupReqTypedef*)pbuf;
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
case CDC_SET_LINE_CODING:
break;
case CDC_GET_LINE_CODING:
break;
case CDC_SET_CONTROL_LINE_STATE:
cmd = request->
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill exiting this function. If you exit this function before transfer
* is complete on CDC interface (ie. using DMA controller) it will result
* in receiving more data while previous ones are still not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete =1;
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
void CDC_Read(uint8_t* buffer, uint32_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return;
}
while(vcp_initialized == 0){
}
while(size > 0){
while(rx_buffer.read_complete == 0){
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,355 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(tx_buffer)){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct CmdEcho : public Command{
bool Execute(IRequest* request, IResponse* response) override {
uint32_t data;
if(!request->Read(data)){
return false;
}
if(!response->Write((uint8_t*)&data, sizeof(data))){
return false;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
CmdEcho cmd_echo;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
case CommandId::Echo:
return &cmd_echo;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 1;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,340 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length) = 0;
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read((uint8_t*)&args, sizeof(args))){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(&tx_buffer[0], sizeof(tx_buffer))){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
default:
return &cmd_unknown;
}
}
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 0;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if((_bits_transmitted) % 8 != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _bits_buffer & 0xff;
--length;
received++;
_bits_buffer >>= 8;
}
}
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
while(true){
switch(cmd){
case CommandId::EEPROMReadBuffer:{
}
break;
case CommandId::EEPROMWriteBuffer:{
}
break;
}
HAL_GPIO_TogglePin(LD4_GPIO_Port, LD4_Pin);
}
}
@@ -0,0 +1,360 @@
/*
* main_cpp.cpp
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#include "stm32f0xx_hal.h"
#include "usbd_cdc_if.h"
#include "commands.h"
#include <algorithm>
extern I2C_HandleTypeDef hi2c1;
#define EEPROM_ADDR 0x50
uint8_t tx_buffer[16];
struct UsbRxBuffer {
uint8_t data[64];
uint8_t size;
uint8_t position;
uint8_t read_complete;
};
extern uint32_t vcp_initialized;
struct IRequest {
virtual ~IRequest() = default;
virtual bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) = 0;
template<typename T>
bool Read(T& value){
uint32_t rx;
if(!Read((uint8_t*)&value, sizeof(value), rx)){
return false;
}
return rx == sizeof(T);
}
};
struct IResponse {
virtual ~IResponse() = default;
virtual bool Write(const uint8_t* buffer, uint32_t length) = 0;
};
struct Command {
virtual ~Command() = default;
virtual bool Execute(IRequest* request, IResponse* response) = 0;
};
struct CmdEEPROMRead : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMReadBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//read and send memory
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
auto result = HAL_I2C_Mem_Read(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
args.startAddress += block_size;
args.size -= block_size;
if(!response->Write(&tx_buffer[0], block_size)){
return false;
}
}
return true;
}
};
struct CmdEEPROMWrite : public Command{
bool Execute(IRequest* request, IResponse* response) override {
CmdEEPROMWriteBufferArgs args;
//read args
if(!request->Read(args)){
return false;
}
//receive and write memory blocks
while(args.size > 0){
auto block_size = std::min<uint32_t>(args.size, sizeof(tx_buffer));
//read block
if(!request->Read(tx_buffer)){
return false;
}
auto result = HAL_I2C_Mem_Write(&hi2c1, (EEPROM_ADDR << 1) | ((args.startAddress >> 7) & 0xE), args.startAddress & 0xff, I2C_MEMADD_SIZE_8BIT, &tx_buffer[0], block_size, 1000);
HAL_Delay(20);
args.startAddress += block_size;
args.size -= block_size;
}
return true;
}
};
struct CmdEcho : public Command{
bool Execute(IRequest* request, IResponse* response) override {
uint32_t data;
if(!request->Read(data)){
return false;
}
if(!response->Write((uint8_t*)&data, sizeof(data))){
return false;
}
return true;
}
};
struct UnknownCommandHandler : public Command {
bool Execute(IRequest* request, IResponse* response) override {
return true;
}
};
CmdEEPROMRead cmd_eeprom_read;
CmdEEPROMRead cmd_eeprom_write;
CmdEcho cmd_echo;
UnknownCommandHandler cmd_unknown;
Command* GetCommandHandler(CommandId id){
switch(id){
case CommandId::EEPROMReadBuffer:
return &cmd_eeprom_read;
case CommandId::EEPROMWriteBuffer:
return &cmd_eeprom_write;
case CommandId::Echo:
return &cmd_echo;
default:
return &cmd_unknown;
}
}
extern USBD_HandleTypeDef hUsbDeviceFS;
struct CommandProcessor : public IRequest, public IResponse{
CommandProcessor():_connected(false), _bits_received(0), _bits_transmitted(0), _last_byte_received(false),_tx_bits_buffered(0),
_rx_bits_buffer(0), _tx_bits_buffer(0){
}
void OnDisconnect(){
_connected = false;
}
void OnCdcInit(){
rx_buffer.position = 0;
rx_buffer.size = 0;
rx_buffer.read_complete = 1;
_connected = false;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
}
void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
rx_buffer.position = 0;
rx_buffer.size = *Len;
rx_buffer.read_complete = 1;
}
void Run(){
while(true){
//do connection
_connected = true;
//execute commands
while(true){
CommandId cmd;
//read header
uint32_t rx_size = 0;
if(!Read((uint8_t*)&cmd, sizeof(cmd), rx_size) || (rx_size != sizeof(cmd))){
break;
}
//execute command
auto cmd_handler = GetCommandHandler(cmd);
if(!cmd_handler->Execute(this, this)){
break;
}
//finalize read
FinalizeRead();
//finalize write
FinalizeWrite();
}
}
}
void FinalizeRead(){
while(!_last_byte_received){
uint8_t buffer;
uint32_t received;
if(!Read(&buffer, sizeof(buffer), received)){
break;
}
}
_last_byte_received = false;
_rx_bits_buffer = 0;
_bits_received = 0;
}
void FinalizeWrite(){
//flush bits
if(_tx_bits_buffered != 0){
CDC_Write((uint8_t*)&_tx_bits_buffer, 1);
}
//write finalization byte
uint8_t finalize_byte = 0xff;
CDC_Write(&finalize_byte, sizeof(finalize_byte));
_tx_bits_buffer = 0;
_tx_bits_buffered = 0;
_bits_received = 0;
}
bool Read(uint8_t* buffer, uint32_t length, uint32_t& received) override {
received = 0;
if(_last_byte_received){
return true;
}
while(length > 0){
uint8_t rx;
if(!CDC_Read(&rx, sizeof(rx))){
return false;
}
auto buffered_bits = _bits_received % 8;
if(rx & 0x80){//if finalization byte received
_last_byte_received = true;
if(buffered_bits){//flush buffered bits
buffer[0] = _rx_bits_buffer & 0xff;
received++;
return true;
}
}
//put bits to buffer
_rx_bits_buffer |= (rx & 0x7f) << buffered_bits;
if(buffered_bits != 0){
buffer[0] = _rx_bits_buffer & 0xff;
--length;
received++;
_rx_bits_buffer >>= 8;
}
}
return true;
}
bool Write(const uint8_t* buffer, uint32_t length) override{
while(length > 0){
_tx_bits_buffer |= (uint16_t)(buffer[0]) << _tx_bits_buffered;
buffer++;
length--;
_tx_bits_buffered += 8;
while(_tx_bits_buffered >= 7){
uint8_t tx_buffer = _tx_bits_buffer & 0x7f;
if(!CDC_Write((uint8_t*)&tx_buffer, 1)){
return false;
}
_bits_transmitted += 7;
_tx_bits_buffered -= 7;
_tx_bits_buffer >>= 7;
}
}
return true;
}
private:
bool CDC_Write(uint8_t* buffer, uint16_t size){
while(vcp_initialized == 0){}
while(USBD_OK != CDC_Transmit_FS(buffer, size)){
if(!_connected){
return false;
}
}
return true;
}
bool CDC_Read(uint8_t* buffer, uint16_t size){
uint32_t i;
uint32_t block_size;
if(size == 0){
return true;
}
while(vcp_initialized == 0){}
while(size > 0){
if(!_connected){
return false;
}
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
if(rx_buffer.position >= rx_buffer.size){
rx_buffer.read_complete = 0;
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &rx_buffer.data[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
while(rx_buffer.read_complete == 0){
if(!_connected){
return false;
}
}
}
block_size = size < (rx_buffer.size - rx_buffer.position) ? size : (rx_buffer.size - rx_buffer.position);
//copy data
for(i = 0; i < block_size; ++i){
buffer[i] = rx_buffer.data[rx_buffer.position++];
}
buffer += block_size;
size -= block_size;
}
return _connected;
}
bool _connected;
UsbRxBuffer rx_buffer;
uint32_t _bits_received;
uint32_t _bits_transmitted;
uint8_t _tx_bits_buffered;
uint16_t _rx_bits_buffer;
uint16_t _tx_bits_buffer;
bool _last_byte_received;
};
CommandProcessor commandProcessor;
extern "C" void OnCdcDisconnect(){
HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
commandProcessor.OnDisconnect();
}
extern "C" void OnCdcInit(){
commandProcessor.OnCdcInit();
}
extern "C" void OnCdcReceive(uint8_t* Buf, uint32_t *Len){
commandProcessor.OnCdcReceive(Buf, Len);
}
extern "C" void main_cpp(){
commandProcessor.Run();
}
@@ -0,0 +1,22 @@
/*
* commands.h
*
* Created on: 11 èþíÿ 2016 ã.
* Author: Sergey
*/
#ifndef COMMANDS_H_
#define COMMANDS_H_
#include <cstdint>
enum class CommandId : uint32_t{
EEPROMReadBuffer,
EEPROMWriteBuffer
};
struct EEPROMReadBufferArgs {
};
#endif /* COMMANDS_H_ */

Some files were not shown because too many files have changed in this diff Show More