*
This commit is contained in:
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 ------------------------------------------
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
+4331
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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 @@
|
||||
|
||||
@@ -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'.
|
||||
+307
@@ -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****/
|
||||
|
||||
+360
@@ -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();
|
||||
}
|
||||
|
||||
+321
@@ -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****/
|
||||
|
||||
+342
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* commands.h
|
||||
*
|
||||
* Created on: 11 èþíÿ 2016 ã.
|
||||
* Author: Sergey
|
||||
*/
|
||||
|
||||
#ifndef COMMANDS_H_
|
||||
#define COMMANDS_H_
|
||||
|
||||
|
||||
enum class CommandId {
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* COMMANDS_H_ */
|
||||
+23
@@ -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_ */
|
||||
+357
@@ -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();
|
||||
}
|
||||
|
||||
+360
@@ -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();
|
||||
}
|
||||
|
||||
+22
@@ -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_ */
|
||||
+342
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+353
@@ -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();
|
||||
}
|
||||
|
||||
+330
@@ -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****/
|
||||
|
||||
+19
@@ -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_ */
|
||||
+331
@@ -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****/
|
||||
|
||||
+358
@@ -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();
|
||||
}
|
||||
|
||||
+19
@@ -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_ */
|
||||
+357
@@ -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();
|
||||
}
|
||||
|
||||
+343
@@ -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();
|
||||
}
|
||||
|
||||
+23
@@ -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_ */
|
||||
+361
@@ -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();
|
||||
}
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* commands.h
|
||||
*
|
||||
* Created on: 11 èþíÿ 2016 ã.
|
||||
* Author: Sergey
|
||||
*/
|
||||
|
||||
#ifndef COMMANDS_H_
|
||||
#define COMMANDS_H_
|
||||
|
||||
|
||||
enum class Commands {
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* COMMANDS_H_ */
|
||||
+344
@@ -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****/
|
||||
|
||||
+346
@@ -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****/
|
||||
|
||||
+330
@@ -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****/
|
||||
|
||||
+360
@@ -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();
|
||||
}
|
||||
|
||||
+360
@@ -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();
|
||||
}
|
||||
|
||||
+341
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+349
@@ -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****/
|
||||
|
||||
+333
@@ -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();
|
||||
}
|
||||
|
||||
+82
@@ -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>© 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;
|
||||
}
|
||||
|
||||
+343
@@ -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****/
|
||||
|
||||
+340
@@ -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();
|
||||
}
|
||||
|
||||
+323
@@ -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****/
|
||||
|
||||
+355
@@ -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();
|
||||
}
|
||||
|
||||
+343
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+28
@@ -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_ */
|
||||
+328
@@ -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****/
|
||||
|
||||
+323
@@ -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****/
|
||||
|
||||
+22
@@ -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_ */
|
||||
+22
@@ -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_ */
|
||||
+307
@@ -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****/
|
||||
|
||||
+352
@@ -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();
|
||||
}
|
||||
|
||||
+353
@@ -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();
|
||||
}
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* commands.h
|
||||
*
|
||||
* Created on: 11 èþíÿ 2016 ã.
|
||||
* Author: Sergey
|
||||
*/
|
||||
|
||||
#ifndef COMMANDS_H_
|
||||
#define COMMANDS_H_
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* COMMANDS_H_ */
|
||||
+317
@@ -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****/
|
||||
|
||||
+361
@@ -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();
|
||||
}
|
||||
|
||||
+362
@@ -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();
|
||||
}
|
||||
|
||||
+337
@@ -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();
|
||||
}
|
||||
|
||||
+345
@@ -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****/
|
||||
|
||||
+327
@@ -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****/
|
||||
|
||||
+341
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+328
@@ -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****/
|
||||
|
||||
+335
@@ -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****/
|
||||
|
||||
+336
@@ -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();
|
||||
}
|
||||
|
||||
+346
@@ -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();
|
||||
}
|
||||
|
||||
+309
@@ -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****/
|
||||
|
||||
+337
@@ -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();
|
||||
}
|
||||
|
||||
+346
@@ -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****/
|
||||
|
||||
+310
@@ -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****/
|
||||
|
||||
+334
@@ -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****/
|
||||
|
||||
+343
@@ -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****/
|
||||
|
||||
+342
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+346
@@ -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****/
|
||||
|
||||
+246
@@ -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****/
|
||||
+349
@@ -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****/
|
||||
|
||||
+342
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+343
@@ -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****/
|
||||
|
||||
+348
@@ -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();
|
||||
}
|
||||
|
||||
+121
@@ -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****/
|
||||
+329
@@ -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();
|
||||
}
|
||||
|
||||
+306
@@ -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****/
|
||||
+337
@@ -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****/
|
||||
|
||||
+350
@@ -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****/
|
||||
|
||||
+353
@@ -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****/
|
||||
|
||||
+28
@@ -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_ */
|
||||
+349
@@ -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****/
|
||||
|
||||
+355
@@ -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();
|
||||
}
|
||||
|
||||
+340
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+360
@@ -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();
|
||||
}
|
||||
|
||||
+22
@@ -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
Reference in New Issue
Block a user