From 1aa97d805324d078ab171d00821407857084b52a Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Thu, 12 Mar 2020 15:56:23 +0300 Subject: [PATCH] Add starting sources to CANbus_stepper --- F0-nolib/CANbus_stepper/kicad/stm32.csv | 122 +++++ F0-nolib/CANbus_stepper/kicad/stm32.sch | 4 +- F0-nolib/CANbus_stepper/kicad/stm32.sch-bak | 6 +- F0-nolib/CANbus_stepper/src/Makefile | 155 +++++++ F0-nolib/CANbus_stepper/src/Readme.md | 4 + F0-nolib/CANbus_stepper/src/adc.c | 156 +++++++ F0-nolib/CANbus_stepper/src/adc.h | 31 ++ F0-nolib/CANbus_stepper/src/canstepper.bin | Bin 0 -> 7448 bytes F0-nolib/CANbus_stepper/src/hardware.c | 96 ++++ F0-nolib/CANbus_stepper/src/hardware.h | 54 +++ F0-nolib/CANbus_stepper/src/main.c | 94 ++++ F0-nolib/CANbus_stepper/src/proto.c | 184 ++++++++ F0-nolib/CANbus_stepper/src/proto.h | 50 ++ F0-nolib/CANbus_stepper/src/usart.c | 260 +++++++++++ F0-nolib/CANbus_stepper/src/usart.h | 49 ++ F0-nolib/CANbus_stepper/src/usb.c | 181 ++++++++ F0-nolib/CANbus_stepper/src/usb.h | 37 ++ F0-nolib/CANbus_stepper/src/usb_defs.h | 106 +++++ F0-nolib/CANbus_stepper/src/usb_lib.c | 487 ++++++++++++++++++++ F0-nolib/CANbus_stepper/src/usb_lib.h | 202 ++++++++ F0-nolib/Snippets/Jump2Boot.c | 42 +- F0-nolib/inc/F0/stm32f0.h | 6 +- 22 files changed, 2303 insertions(+), 23 deletions(-) create mode 100644 F0-nolib/CANbus_stepper/kicad/stm32.csv create mode 100644 F0-nolib/CANbus_stepper/src/Makefile create mode 100644 F0-nolib/CANbus_stepper/src/Readme.md create mode 100644 F0-nolib/CANbus_stepper/src/adc.c create mode 100644 F0-nolib/CANbus_stepper/src/adc.h create mode 100755 F0-nolib/CANbus_stepper/src/canstepper.bin create mode 100644 F0-nolib/CANbus_stepper/src/hardware.c create mode 100644 F0-nolib/CANbus_stepper/src/hardware.h create mode 100644 F0-nolib/CANbus_stepper/src/main.c create mode 100644 F0-nolib/CANbus_stepper/src/proto.c create mode 100644 F0-nolib/CANbus_stepper/src/proto.h create mode 100644 F0-nolib/CANbus_stepper/src/usart.c create mode 100644 F0-nolib/CANbus_stepper/src/usart.h create mode 100644 F0-nolib/CANbus_stepper/src/usb.c create mode 100644 F0-nolib/CANbus_stepper/src/usb.h create mode 100644 F0-nolib/CANbus_stepper/src/usb_defs.h create mode 100644 F0-nolib/CANbus_stepper/src/usb_lib.c create mode 100644 F0-nolib/CANbus_stepper/src/usb_lib.h diff --git a/F0-nolib/CANbus_stepper/kicad/stm32.csv b/F0-nolib/CANbus_stepper/kicad/stm32.csv new file mode 100644 index 0000000..c8f0f39 --- /dev/null +++ b/F0-nolib/CANbus_stepper/kicad/stm32.csv @@ -0,0 +1,122 @@ +"Source:","/home/eddy/Yandex.Disk/Projects/stm32samples/F0-nolib/CANbus_stepper/kicad/stm32.sch" +"Date:","๗ิ 10 อมา 2020 09:31:14" +"Tool:","Eeschema 5.1.4" +"Generator:","/usr/local/share/kicad/plugins/bom_csv_grouped_by_value.py" +"Component Count:","66" + +"Individual Components:" + +"Item","Qty","Reference(s)","Value","LibPart","Footprint","Datasheet" +"","","C1","0.1","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"","","C2","100uF","Device:CP","Capacitor_THT:CP_Radial_D8.0mm_P3.50mm","~" +"","","C3","0.1","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"","","C4","47uF, 10V","Device:CP","Capacitor_Tantalum_SMD:CP_EIA-6032-28_Kemet-C_Pad2.25x2.35mm_HandSolder","~" +"","","C5","0.1","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"","","C6","47uF, 10V","Device:CP","Capacitor_Tantalum_SMD:CP_EIA-6032-28_Kemet-C_Pad2.25x2.35mm_HandSolder","~" +"","","C7","0.1","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"","","C8","0.1","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"","","C9","0.1","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"","","C10","0.1","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"","","C11","0.1","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"","","C12","0.1","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"","","D1","MBRS130L","Device:D_Schottky","Diode_SMD:D_SMB_Handsoldering","" +"","","D2","MBRS130L","Device:D_Schottky","Diode_SMD:D_SMB_Handsoldering","" +"","","D3","PESD3V3L4UG","Power_Protection:PESD3V3L4UG","TO_SOT_Packages_SMD:SOT-363_SC-70-6_Handsoldering","https://assets.nexperia.com/documents/data-sheet/PESDXL4UF_G_W.pdf" +"","","D4","PESD1CAN","elements:PESD1CAN","TO_SOT_Packages_SMD:SOT-23_Handsoldering","" +"","","D5","MM3Z7V5","Device:D_Zener","Diode_SMD:D_0805_2012Metric_Pad1.15x1.40mm_HandSolder","~" +"","","D6","USB6B1","Power_Protection:USB6B1","Package_SO:SOIC-8_3.9x4.9mm_P1.27mm","" +"","","D7","MM3Z3V9","Device:D_Zener","Diode_SMD:D_0805_2012Metric_Pad1.15x1.40mm_HandSolder","" +"","","D8","MM3Z3V9","Device:D_Zener","Diode_SMD:D_0805_2012Metric_Pad1.15x1.40mm_HandSolder","" +"","","F1","1A","Device:Fuse","MyFootprints:FuseHolder","~" +"","","J1","A","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal","" +"","","J2","B","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal","" +"","","J3","Conn_01x08_Female","Connector:Conn_01x08_Female","Connector_PinSocket_2.54mm:PinSocket_1x08_P2.54mm_Vertical","~" +"","","J4","Conn_01x08_Female","Connector:Conn_01x08_Female","Connector_PinSocket_2.54mm:PinSocket_1x08_P2.54mm_Vertical","~" +"","","J5","+/-","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal","" +"","","J6","CONN_02X03","Switch:SW_DIP_x04","Button_Switch_THT:SW_DIP_SPSTx04_Slide_9.78x12.34mm_W7.62mm_P2.54mm","" +"","","J7","0/1","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal","" +"","","J8","2/3","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal","" +"","","J9","DB9_Female","Connector:DB9_Female","Connector_Dsub:DSUB-9_Female_Horizontal_P2.77x2.84mm_EdgePinOffset4.94mm_Housed_MountingHolesOffset7.48mm","" +"","","J10","12v","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal","" +"","","J11","DB9_Male","Connector:DB9_Male","Connector_Dsub:DSUB-9_Male_Horizontal_P2.77x2.84mm_EdgePinOffset4.94mm_Housed_MountingHolesOffset7.48mm","" +"","","J12","RS-485","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal","" +"","","J13","Conn_01x06","Connector_Generic:Conn_01x06","Connector_PinSocket_2.54mm:PinSocket_1x06_P2.54mm_Vertical","~" +"","","P1","USB_A","Connector:USB_B","Connectors_USB:USB_B_OST_USB-B1HSxx_Horizontal","" +"","","P2","Hole","Connector_Generic:Conn_01x01","MountingHole:MountingHole_3.2mm_M3","" +"","","P3","Hole","Connector_Generic:Conn_01x01","MountingHole:MountingHole_3.2mm_M3","" +"","","P4","Hole","Connector_Generic:Conn_01x01","MountingHole:MountingHole_3.2mm_M3","" +"","","P5","Hole","Connector_Generic:Conn_01x01","MountingHole:MountingHole_3.2mm_M3","" +"","","Q1","SI2305","Device:Q_PMOS_GSD","TO_SOT_Packages_SMD:SOT-23_Handsoldering","~" +"","","Q2","AO3407","Device:Q_PMOS_GSD","TO_SOT_Packages_SMD:SOT-23_Handsoldering","" +"","","R1","330","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~" +"","","R2","10k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~" +"","","R3","120","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~" +"","","R4","15k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"","","R5","330","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~" +"","","R6","330","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~" +"","","R7","330","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~" +"","","R8","330","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~" +"","","R9","120","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"","","R10","10k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~" +"","","R11","22","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"","","R12","22","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"","","R13","220k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"","","R14","56k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"","","R15","47k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"","","R16","47k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"","","R17","47k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"","","R18","22","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~" +"","","SW1","SW_DIP_x01","Switch:SW_DIP_x01","Button_Switch_THT:SW_DIP_SPSTx01_Slide_6.7x4.1mm_W7.62mm_P2.54mm_LowProfile","~" +"","","U1","ISO1050DUB","Interface_CAN_LIN:ISO1050DUB","Package_SO:SOP-8_6.62x9.15mm_P2.54mm","http://www.ti.com/lit/ds/symlink/iso1050.pdf" +"","","U2","LM1117-5.0","Regulator_Linear:LM1117-3.3","TO_SOT_Packages_SMD:SOT-223-3_TabPin2","" +"","","U3","LM1117-3.3","Regulator_Linear:LM1117-3.3","TO_SOT_Packages_SMD:SOT-223-3_TabPin2","" +"","","U4","MCP2551-I/SN","Interface_CAN_LIN:MCP2551-I-SN","Package_SO:SOIC-8_3.9x4.9mm_P1.27mm","" +"","","U5","STM32F072CBTx","MCU_ST_STM32F0:STM32F072CBTx","Package_QFP:LQFP-48_7x7mm_P0.5mm","http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00090510.pdf" +"","","U6","MAX3485","Interface_UART:MAX3485","Package_SO:SO-8_3.9x4.9mm_P1.27mm","https://datasheets.maximintegrated.com/en/ds/MAX3483-MAX3491.pdf" + + + +"Collated Components:" + +"Item","Qty","Reference(s)","Value","LibPart","Footprint","Datasheet" +"1","9","C1, C3, C5, C7, C8, C9, C10, C11, C12","0.1","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"2","1","C2","100uF","Device:CP","Capacitor_THT:CP_Radial_D8.0mm_P3.50mm","~" +"3","2","C4, C6","47uF, 10V","Device:CP","Capacitor_Tantalum_SMD:CP_EIA-6032-28_Kemet-C_Pad2.25x2.35mm_HandSolder","~" +"4","2","D1, D2","MBRS130L","Device:D_Schottky","Diode_SMD:D_SMB_Handsoldering","" +"5","1","D3","PESD3V3L4UG","Power_Protection:PESD3V3L4UG","TO_SOT_Packages_SMD:SOT-363_SC-70-6_Handsoldering","https://assets.nexperia.com/documents/data-sheet/PESDXL4UF_G_W.pdf" +"6","1","D4","PESD1CAN","elements:PESD1CAN","TO_SOT_Packages_SMD:SOT-23_Handsoldering","" +"7","1","D5","MM3Z7V5","Device:D_Zener","Diode_SMD:D_0805_2012Metric_Pad1.15x1.40mm_HandSolder","~" +"8","1","D6","USB6B1","Power_Protection:USB6B1","Package_SO:SOIC-8_3.9x4.9mm_P1.27mm","" +"9","2","D7, D8","MM3Z3V9","Device:D_Zener","Diode_SMD:D_0805_2012Metric_Pad1.15x1.40mm_HandSolder","" +"10","1","F1","1A","Device:Fuse","MyFootprints:FuseHolder","~" +"11","1","J1","A","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal","" +"12","1","J2","B","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal","" +"13","2","J3, J4","Conn_01x08_Female","Connector:Conn_01x08_Female","Connector_PinSocket_2.54mm:PinSocket_1x08_P2.54mm_Vertical","~" +"14","1","J5","+/-","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal","" +"15","1","J6","CONN_02X03","Switch:SW_DIP_x04","Button_Switch_THT:SW_DIP_SPSTx04_Slide_9.78x12.34mm_W7.62mm_P2.54mm","" +"16","1","J7","0/1","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal","" +"17","1","J8","2/3","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal","" +"18","1","J9","DB9_Female","Connector:DB9_Female","Connector_Dsub:DSUB-9_Female_Horizontal_P2.77x2.84mm_EdgePinOffset4.94mm_Housed_MountingHolesOffset7.48mm","" +"19","1","J10","12v","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal","" +"20","1","J11","DB9_Male","Connector:DB9_Male","Connector_Dsub:DSUB-9_Male_Horizontal_P2.77x2.84mm_EdgePinOffset4.94mm_Housed_MountingHolesOffset7.48mm","" +"21","1","J12","RS-485","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal","" +"22","1","J13","Conn_01x06","Connector_Generic:Conn_01x06","Connector_PinSocket_2.54mm:PinSocket_1x06_P2.54mm_Vertical","~" +"23","1","P1","USB_A","Connector:USB_B","Connectors_USB:USB_B_OST_USB-B1HSxx_Horizontal","" +"24","4","P2, P3, P4, P5","Hole","Connector_Generic:Conn_01x01","MountingHole:MountingHole_3.2mm_M3","" +"25","1","Q1","SI2305","Device:Q_PMOS_GSD","TO_SOT_Packages_SMD:SOT-23_Handsoldering","~" +"26","1","Q2","AO3407","Device:Q_PMOS_GSD","TO_SOT_Packages_SMD:SOT-23_Handsoldering","" +"27","5","R1, R5, R6, R7, R8","330","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~" +"28","2","R2, R10","10k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~" +"29","2","R3, R9","120","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~" +"30","1","R4","15k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"31","3","R11, R12, R18","22","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~" +"32","1","R13","220k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"33","1","R14","56k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"34","3","R15, R16, R17","47k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" +"35","1","SW1","SW_DIP_x01","Switch:SW_DIP_x01","Button_Switch_THT:SW_DIP_SPSTx01_Slide_6.7x4.1mm_W7.62mm_P2.54mm_LowProfile","~" +"36","1","U1","ISO1050DUB","Interface_CAN_LIN:ISO1050DUB","Package_SO:SOP-8_6.62x9.15mm_P2.54mm","http://www.ti.com/lit/ds/symlink/iso1050.pdf" +"37","1","U2","LM1117-5.0","Regulator_Linear:LM1117-3.3","TO_SOT_Packages_SMD:SOT-223-3_TabPin2","" +"38","1","U3","LM1117-3.3","Regulator_Linear:LM1117-3.3","TO_SOT_Packages_SMD:SOT-223-3_TabPin2","" +"39","1","U4","MCP2551-I/SN","Interface_CAN_LIN:MCP2551-I-SN","Package_SO:SOIC-8_3.9x4.9mm_P1.27mm","" +"40","1","U5","STM32F072CBTx","MCU_ST_STM32F0:STM32F072CBTx","Package_QFP:LQFP-48_7x7mm_P0.5mm","http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00090510.pdf" +"41","1","U6","MAX3485","Interface_UART:MAX3485","Package_SO:SO-8_3.9x4.9mm_P1.27mm","https://datasheets.maximintegrated.com/en/ds/MAX3483-MAX3491.pdf" diff --git a/F0-nolib/CANbus_stepper/kicad/stm32.sch b/F0-nolib/CANbus_stepper/kicad/stm32.sch index 1b283e8..493bf7c 100644 --- a/F0-nolib/CANbus_stepper/kicad/stm32.sch +++ b/F0-nolib/CANbus_stepper/kicad/stm32.sch @@ -445,7 +445,7 @@ L Device:D_Zener D7 U 1 1 59684468 P 9140 1520 F 0 "D7" H 9140 1620 50 0000 C CNN -F 1 "MM3Z3V9" H 9140 1420 50 0000 C CNN +F 1 "MM3Z4V7" H 9140 1420 50 0000 C CNN F 2 "Diode_SMD:D_0805_2012Metric_Pad1.15x1.40mm_HandSolder" H 9140 1520 50 0001 C CNN F 3 "" H 9140 1520 50 0000 C CNN 1 9140 1520 @@ -1056,7 +1056,7 @@ L Device:D_Zener D8 U 1 1 5E7D7999 P 10080 1510 F 0 "D8" H 10080 1610 50 0000 C CNN -F 1 "MM3Z3V9" H 10080 1410 50 0000 C CNN +F 1 "MM3Z4V7" H 10080 1410 50 0000 C CNN F 2 "Diode_SMD:D_0805_2012Metric_Pad1.15x1.40mm_HandSolder" H 10080 1510 50 0001 C CNN F 3 "" H 10080 1510 50 0000 C CNN 1 10080 1510 diff --git a/F0-nolib/CANbus_stepper/kicad/stm32.sch-bak b/F0-nolib/CANbus_stepper/kicad/stm32.sch-bak index cb6455f..1b283e8 100644 --- a/F0-nolib/CANbus_stepper/kicad/stm32.sch-bak +++ b/F0-nolib/CANbus_stepper/kicad/stm32.sch-bak @@ -1876,14 +1876,16 @@ NoConn ~ 6140 5560 NoConn ~ 6140 5660 NoConn ~ 6140 5760 $Comp -L power:+5V #PWR? +L power:+5V #PWR0102 U 1 1 5E623E4A P 1600 2240 -F 0 "#PWR?" H 1600 2090 50 0001 C CNN +F 0 "#PWR0102" H 1600 2090 50 0001 C CNN F 1 "+5V" H 1600 2380 50 0000 C CNN F 2 "" H 1600 2240 50 0000 C CNN F 3 "" H 1600 2240 50 0000 C CNN 1 1600 2240 1 0 0 -1 $EndComp +Text Label 1200 4540 2 60 ~ 0 +12Vin $EndSCHEMATC diff --git a/F0-nolib/CANbus_stepper/src/Makefile b/F0-nolib/CANbus_stepper/src/Makefile new file mode 100644 index 0000000..e21163d --- /dev/null +++ b/F0-nolib/CANbus_stepper/src/Makefile @@ -0,0 +1,155 @@ +# make debug adds -DEBUG -Werror +# make ADDEFS="additional defs" +BINARY = canstepper +BOOTPORT ?= /dev/ttyUSB0 +BOOTSPEED ?= 115200 +# MCU FAMILY +FAMILY ?= F0 +# MCU code (STM32F072xx) +MCU ?= F072xB +# change this linking script depending on particular MCU model, +LDSCRIPT ?= stm32f0728.ld +DEFS = ${ADDEFS} -DVERSION=\"0.0.1\" -DUSARTNUM=1 +TARGET := RELEASE + +FP_FLAGS ?= -msoft-float +ASM_FLAGS ?= -mthumb -mcpu=cortex-m0 -march=armv6-m -mtune=cortex-m0 +ARCH_FLAGS = $(ASM_FLAGS) $(FP_FLAGS) + +############################################################################### +# Executables +#PREFIX ?= arm-none-eabi +# gcc from arm web site +PREFIX ?= /opt/bin/arm-none-eabi +RM := rm -f +RMDIR := rmdir +CC := $(PREFIX)-gcc +LD := $(PREFIX)-gcc +AR := $(PREFIX)-ar +AS := $(PREFIX)-as +SIZE := $(PREFIX)-size +OBJCOPY := $(PREFIX)-objcopy +OBJDUMP := $(PREFIX)-objdump +GDB := $(PREFIX)-gdb +STFLASH := $(shell which st-flash) +STBOOT := $(shell which stm32flash) +DFUUTIL := $(shell which dfu-util) + +############################################################################### +# Source files +OBJDIR = mk +SRC := $(wildcard *.c) +OBJS := $(addprefix $(OBJDIR)/, $(SRC:%.c=%.o)) +STARTUP = $(OBJDIR)/startup.o +OBJS += $(STARTUP) +# dependencies: we need them to recompile files if their headers-dependencies changed +DEPS := $(OBJS:.o=.d) + +INC_DIR ?= ../inc + +INCLUDE := -I$(INC_DIR)/F0 -I$(INC_DIR)/cm +LIB_DIR := $(INC_DIR)/ld + +############################################################################### +# C flags +CFLAGS += -O2 -g -MD -D__thumb2__=1 +CFLAGS += -Wall -Wextra -Wshadow +CFLAGS += -fno-common -ffunction-sections -fdata-sections + +############################################################################### +# Linker flags +LDFLAGS += --static -nostartfiles --specs=nano.specs +LDFLAGS += -L$(LIB_DIR) +LDFLAGS += -T$(LDSCRIPT) +LDFLAGS += -Wl,-Map=$(OBJDIR)/$(BINARY).map +LDFLAGS += -Wl,--gc-sections + +############################################################################### +# Used libraries +LDLIBS += -Wl,--start-group -lc -lgcc -Wl,--end-group +LDLIBS += $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) +DEFS += -DSTM32$(FAMILY) -DSTM32$(MCU) + +ELF := $(OBJDIR)/$(BINARY).elf +LIST := $(OBJDIR)/$(BINARY).list +BIN := $(BINARY).bin +HEX := $(BINARY).hex + +all: $(OBJDIR)/RELEASE bin list size +release: all + +debug: CFLAGS += -DEBUG -Werror -W -Wimplicit-function-declaration +debug: $(OBJDIR)/DEBUG bin list size + +$(OBJDIR)/DEBUG: + @rm -rf $(OBJDIR) + @mkdir $(OBJDIR) + @> $(OBJDIR)/DEBUG + @echo "TARGET: DEBUG" + echo "CFLAGS += -DEBUG -Werror -W -Wimplicit-function-declaration" > $(OBJDIR)/CFLAGS +$(OBJDIR)/RELEASE: + @rm -rf $(OBJDIR) + @mkdir $(OBJDIR) + @> $(OBJDIR)/RELEASE + @echo "TARGET: RELEASE" + echo "" > $(OBJDIR)/CFLAGS + +elf: $(ELF) +bin: $(BIN) +hex: $(HEX) +list: $(LIST) + +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPS) +-include $(OBJDIR)/CFLAGS +endif + +$(OBJDIR): + mkdir $(OBJDIR) + +$(STARTUP): $(INC_DIR)/startup/vector.c + @echo " CC startup" + $(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -o $@ -c $< + +$(OBJDIR)/%.o: %.c + @echo " CC $<" + $(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -o $@ -c $< + +$(BIN): $(ELF) + @echo " OBJCOPY $(BIN)" + $(OBJCOPY) -Obinary $(ELF) $(BIN) + +$(HEX): $(ELF) + @echo " OBJCOPY $(HEX)" + $(OBJCOPY) -Oihex $(ELF) $(HEX) + +$(LIST): $(ELF) + @echo " OBJDUMP $(LIST)" + $(OBJDUMP) -S $(ELF) > $(LIST) + +$(ELF): $(OBJDIR) $(OBJS) + @echo " LD $(ELF)" + $(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJS) $(LDLIBS) -o $(ELF) + +size: $(ELF) + $(SIZE) $(ELF) + +clean: + @echo " CLEAN" + @$(RM) $(HEX) + @$(RM) -rf $(OBJDIR) 2>/dev/null || true + + +flash: $(BIN) + @echo " FLASH $(BIN)" + $(STFLASH) --reset write $(BIN) 0x8000000 + +boot: $(BIN) + @echo " LOAD $(BIN) through bootloader" + $(STBOOT) -b$(BOOTSPEED) $(BOOTPORT) -w $(BIN) + +dfuboot: $(BIN) + @echo " LOAD $(BIN) THROUGH DFU" + $(DFUUTIL) -a0 -D $(BIN) -s 0x08000000 + +.PHONY: clean flash boot diff --git a/F0-nolib/CANbus_stepper/src/Readme.md b/F0-nolib/CANbus_stepper/src/Readme.md new file mode 100644 index 0000000..364dd7e --- /dev/null +++ b/F0-nolib/CANbus_stepper/src/Readme.md @@ -0,0 +1,4 @@ +Development board for TMC2130/DRV8825 stepper driver modules +============================================================ + +Stepper control over CAN bus, RS-485 and USB. diff --git a/F0-nolib/CANbus_stepper/src/adc.c b/F0-nolib/CANbus_stepper/src/adc.c new file mode 100644 index 0000000..86fa11c --- /dev/null +++ b/F0-nolib/CANbus_stepper/src/adc.c @@ -0,0 +1,156 @@ +/* + * This file is part of the TSYS_controller project. + * Copyright 2019 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "adc.h" + +/** + * @brief ADC_array - array for ADC channels with median filtering: + * 0..3 - external channels + * 4 - internal Tsens + * 5 - Vref + */ +#define TSENS_CHAN (NUMBER_OF_ADC_CHANNELS-2) +#define VREF_CHAN (NUMBER_OF_ADC_CHANNELS-1) +static uint16_t ADC_array[NUMBER_OF_ADC_CHANNELS*9]; + +/* + * ADC channels: + * IN0 - V12 + * IN1 - V5 + * IN16- temperature sensor + * IN17- vref + */ +void adc_setup(){ + uint16_t ctr = 0; // 0xfff0 - more than 1.3ms + // Enable clocking + /* (1) Enable the peripheral clock of the ADC */ + /* (2) Start HSI14 RC oscillator */ + /* (3) Wait HSI14 is ready */ + RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; /* (1) */ + RCC->CR2 |= RCC_CR2_HSI14ON; /* (2) */ + while ((RCC->CR2 & RCC_CR2_HSI14RDY) == 0 && ++ctr < 0xfff0){}; /* (3) */ + // calibration + /* (1) Ensure that ADEN = 0 */ + /* (2) Clear ADEN */ + /* (3) Launch the calibration by setting ADCAL */ + /* (4) Wait until ADCAL=0 */ + if ((ADC1->CR & ADC_CR_ADEN) != 0){ /* (1) */ + ADC1->CR &= (uint32_t)(~ADC_CR_ADEN); /* (2) */ + } + ADC1->CR |= ADC_CR_ADCAL; /* (3) */ + ctr = 0; // ADC calibration time is 5.9us + while ((ADC1->CR & ADC_CR_ADCAL) != 0 && ++ctr < 0xfff0){}; /* (4) */ + // enable ADC + ctr = 0; + do{ + ADC1->CR |= ADC_CR_ADEN; + }while ((ADC1->ISR & ADC_ISR_ADRDY) == 0 && ++ctr < 0xfff0); + // configure ADC + /* (1) Select HSI14 by writing 00 in CKMODE (reset value) */ + /* (2) Select the continuous mode */ + /* (3) Select CHSEL0,1 - ADC inputs, 16,17 - t. sensor and vref */ + /* (4) Select a sampling mode of 111 i.e. 239.5 ADC clk to be greater than 17.1us */ + /* (5) Wake-up the VREFINT and Temperature sensor (only for VBAT, Temp sensor and VRefInt) */ + // ADC1->CFGR2 &= ~ADC_CFGR2_CKMODE; /* (1) */ + ADC1->CFGR1 |= ADC_CFGR1_CONT; /* (2)*/ + ADC1->CHSELR = ADC_CHSELR_CHSEL0 | ADC_CHSELR_CHSEL1 | ADC_CHSELR_CHSEL16 | ADC_CHSELR_CHSEL17; /* (3)*/ + ADC1->SMPR |= ADC_SMPR_SMP_0 | ADC_SMPR_SMP_1 | ADC_SMPR_SMP_2; /* (4) */ + ADC->CCR |= ADC_CCR_TSEN | ADC_CCR_VREFEN; /* (5) */ + // configure DMA for ADC + // DMA for AIN + /* (1) Enable the peripheral clock on DMA */ + /* (2) Enable DMA transfer on ADC and circular mode */ + /* (3) Configure the peripheral data register address */ + /* (4) Configure the memory address */ + /* (5) Configure the number of DMA tranfer to be performs on DMA channel 1 */ + /* (6) Configure increment, size, interrupts and circular mode */ + /* (7) Enable DMA Channel 1 */ + RCC->AHBENR |= RCC_AHBENR_DMA1EN; /* (1) */ + ADC1->CFGR1 |= ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG; /* (2) */ + DMA1_Channel1->CPAR = (uint32_t) (&(ADC1->DR)); /* (3) */ + DMA1_Channel1->CMAR = (uint32_t)(ADC_array); /* (4) */ + DMA1_Channel1->CNDTR = NUMBER_OF_ADC_CHANNELS * 9; /* (5) */ + DMA1_Channel1->CCR |= DMA_CCR_MINC | DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0 | DMA_CCR_CIRC; /* (6) */ + DMA1_Channel1->CCR |= DMA_CCR_EN; /* (7) */ + ADC1->CR |= ADC_CR_ADSTART; /* start the ADC conversions */ +} + + +/** + * @brief getADCval - calculate median value for `nch` channel + * @param nch - number of channel + * @return + */ +uint16_t getADCval(int nch){ + int i, addr = nch; + register uint16_t temp; +#define PIX_SORT(a,b) { if ((a)>(b)) PIX_SWAP((a),(b)); } +#define PIX_SWAP(a,b) { temp=(a);(a)=(b);(b)=temp; } + uint16_t p[9]; + for(i = 0; i < 9; ++i, addr += NUMBER_OF_ADC_CHANNELS) // first we should prepare array for optmed + p[i] = ADC_array[addr]; + PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ; + PIX_SORT(p[0], p[1]) ; PIX_SORT(p[3], p[4]) ; PIX_SORT(p[6], p[7]) ; + PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ; + PIX_SORT(p[0], p[3]) ; PIX_SORT(p[5], p[8]) ; PIX_SORT(p[4], p[7]) ; + PIX_SORT(p[3], p[6]) ; PIX_SORT(p[1], p[4]) ; PIX_SORT(p[2], p[5]) ; + PIX_SORT(p[4], p[7]) ; PIX_SORT(p[4], p[2]) ; PIX_SORT(p[6], p[4]) ; + PIX_SORT(p[4], p[2]) ; + return p[4]; +#undef PIX_SORT +#undef PIX_SWAP +} + +// return MCU temperature (degrees of celsius * 10) +int32_t getMCUtemp(){ + int32_t ADval = getADCval(TSENS_CHAN); + int32_t temperature = (int32_t) *TEMP30_CAL_ADDR - ADval; + temperature *= (int32_t)(1100 - 300); + temperature /= (int32_t)(*TEMP30_CAL_ADDR - *TEMP110_CAL_ADDR); + temperature += 300; + return(temperature); +} + +// return Vdd * 100 (V) +uint32_t getVdd(){ + uint32_t vdd = ((uint32_t) *VREFINT_CAL_ADDR) * (uint32_t)330; // 3.3V + vdd /= getADCval(VREF_CHAN); + return vdd; +} + +static inline uint32_t Ufromadu(uint8_t nch, uint32_t vdd){ + uint32_t ADU = getADCval(nch); + ADU *= vdd; + ADU >>= 12; // /4096 + return ADU; +} + +/** + * @brief getUval - calculate U12/U5 + * @return array with members: + * 0 - V12 * 100V (U12 = 12Vin/4.93) + * 1 - V5 * 100V (U5 = 5Vin /2) + */ +uint16_t *getUval(){ + static uint16_t Uval[4]; + uint32_t vdd = getVdd(); + uint32_t val = Ufromadu(0, vdd) * 493; + Uval[0] = (uint16_t)(val / 100); + Uval[1] = (uint16_t)(Ufromadu(1, vdd) << 1); + return Uval; +} diff --git a/F0-nolib/CANbus_stepper/src/adc.h b/F0-nolib/CANbus_stepper/src/adc.h new file mode 100644 index 0000000..e2f37bd --- /dev/null +++ b/F0-nolib/CANbus_stepper/src/adc.h @@ -0,0 +1,31 @@ +/* + * This file is part of the TSYS_controller project. + * Copyright 2019 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef ADC_H +#define ADC_H +#include "stm32f0.h" + +#define NUMBER_OF_ADC_CHANNELS (4) + +int32_t getMCUtemp(); +uint32_t getVdd(); +uint16_t getADCval(int nch); +void adc_setup(); +uint16_t *getUval(); + +#endif // ADC_H diff --git a/F0-nolib/CANbus_stepper/src/canstepper.bin b/F0-nolib/CANbus_stepper/src/canstepper.bin new file mode 100755 index 0000000000000000000000000000000000000000..0ec29b91d4115fd0bf717cad5e059c7fe5eb2547 GIT binary patch literal 7448 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 V$vLZ~1VWe($a(?-yh1QL{5Obrg7yFa literal 0 HcmV?d00001 diff --git a/F0-nolib/CANbus_stepper/src/hardware.c b/F0-nolib/CANbus_stepper/src/hardware.c new file mode 100644 index 0000000..96b6cf2 --- /dev/null +++ b/F0-nolib/CANbus_stepper/src/hardware.c @@ -0,0 +1,96 @@ +/* + * geany_encoding=koi8-r + * hardware.c - hardware-dependent macros & functions + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +#include "hardware.h" + +static uint8_t brdADDR = 0; + +void Jump2Boot(){ + void (*SysMemBootJump)(void); + volatile uint32_t addr = 0x1FFFC800; + // reset systick + SysTick->CTRL = 0; + // reset clocks + RCC->APB1RSTR = RCC_APB1RSTR_CECRST | RCC_APB1RSTR_DACRST | RCC_APB1RSTR_PWRRST | RCC_APB1RSTR_CRSRST | + RCC_APB1RSTR_CANRST | RCC_APB1RSTR_USBRST | RCC_APB1RSTR_I2C2RST | RCC_APB1RSTR_I2C1RST | + RCC_APB1RSTR_USART4RST | RCC_APB1RSTR_USART3RST | RCC_APB1RSTR_USART2RST | RCC_APB1RSTR_SPI2RST | + RCC_APB1RSTR_WWDGRST | RCC_APB1RSTR_TIM14RST | RCC_APB1RSTR_TIM7RST | RCC_APB1RSTR_TIM6RST | + RCC_APB1RSTR_TIM3RST | RCC_APB1RSTR_TIM2RST; + RCC->APB2RSTR = RCC_APB2RSTR_DBGMCURST | RCC_APB2RSTR_TIM17RST | RCC_APB2RSTR_TIM16RST | RCC_APB2RSTR_TIM15RST | + RCC_APB2RSTR_USART1RST | RCC_APB2RSTR_SPI1RST | RCC_APB2RSTR_TIM1RST | RCC_APB2RSTR_ADCRST | RCC_APB2RSTR_SYSCFGRST; + RCC->AHBRSTR = 0; + RCC->APB1RSTR = 0; + RCC->APB2RSTR = 0; + // remap memory to 0 (only for STM32F0) + SYSCFG->CFGR1 = 0x01; __DSB(); __ISB(); + SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4))); + // set main stack pointer + __set_MSP(*((uint32_t *)addr)); + // jump to bootloader + SysMemBootJump(); +} + +void iwdg_setup(){ + uint32_t tmout = 16000000; + /* Enable the peripheral clock RTC */ + /* (1) Enable the LSI (40kHz) */ + /* (2) Wait while it is not ready */ + RCC->CSR |= RCC_CSR_LSION; /* (1) */ + while((RCC->CSR & RCC_CSR_LSIRDY) != RCC_CSR_LSIRDY){if(--tmout == 0) break;} /* (2) */ + /* Configure IWDG */ + /* (1) Activate IWDG (not needed if done in option bytes) */ + /* (2) Enable write access to IWDG registers */ + /* (3) Set prescaler by 64 (1.6ms for each tick) */ + /* (4) Set reload value to have a rollover each 2s */ + /* (5) Check if flags are reset */ + /* (6) Refresh counter */ + IWDG->KR = IWDG_START; /* (1) */ + IWDG->KR = IWDG_WRITE_ACCESS; /* (2) */ + IWDG->PR = IWDG_PR_PR_1; /* (3) */ + IWDG->RLR = 1250; /* (4) */ + tmout = 16000000; + while(IWDG->SR){if(--tmout == 0) break;} /* (5) */ + IWDG->KR = IWDG_REFRESH; /* (6) */ +} + +void gpio_setup(void){ + // here we turn on clocking for all GPIO used + RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN | RCC_AHBENR_GPIOFEN + | RCC_AHBENR_DMAEN; + // PA8 - Tx/Rx + GPIOA->MODER = GPIO_MODER_MODER8_O; + // PB12..15 - board address, pullup input + GPIOB->PUPDR = GPIO_PUPDR_PUPDR12_0 | GPIO_PUPDR_PUPDR13_0 | GPIO_PUPDR_PUPDR14_0 | GPIO_PUPDR_PUPDR15_0; +/* + // Set LEDS (PC13/14) as output + GPIOC->MODER = (GPIOC->MODER & ~(GPIO_MODER_MODER13 | GPIO_MODER_MODER14) + ) | + GPIO_MODER_MODER13_O | GPIO_MODER_MODER14_O; +*/ + brdADDR = READ_BRD_ADDR(); +} + +uint8_t refreshBRDaddr(){ + return (brdADDR = READ_BRD_ADDR()); +} +uint8_t getBRDaddr(){return brdADDR;} diff --git a/F0-nolib/CANbus_stepper/src/hardware.h b/F0-nolib/CANbus_stepper/src/hardware.h new file mode 100644 index 0000000..e125630 --- /dev/null +++ b/F0-nolib/CANbus_stepper/src/hardware.h @@ -0,0 +1,54 @@ +/* + * geany_encoding=koi8-r + * hardware.h + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ +#pragma once +#ifndef __HARDWARE_H__ +#define __HARDWARE_H__ +// Most of hardware-dependendent definitions & functions +#include + +#define CONCAT(a,b) a ## b +#define STR_HELPER(s) #s +#define STR(s) STR_HELPER(s) + +#ifndef USARTNUM +#error "Define USARTNUM 1 or 2" +#endif +#define FORMUSART(X) CONCAT(USART, X) +#define USARTX FORMUSART(USARTNUM) + +// Board address - PB15|14|13|12 +#define READ_BRD_ADDR() ((GPIOB->IDR >> 12) & 0x0f) + +// RS-485 receive/transmit (PA8: 0-Rx, 1-Tx) +#define RS485_TX() do{GPIOA->BSRR = GPIO_BSRR_BS_8;}while(0) +#define RS485_RX() do{GPIOA->BRR = GPIO_BRR_BR_8;}while(0) + +extern volatile uint32_t Tms; + +void Jump2Boot(); +void gpio_setup(void); +void iwdg_setup(); +uint8_t getBRDaddr(); +uint8_t refreshBRDaddr(); + +#endif // __HARDWARE_H__ diff --git a/F0-nolib/CANbus_stepper/src/main.c b/F0-nolib/CANbus_stepper/src/main.c new file mode 100644 index 0000000..098e9d5 --- /dev/null +++ b/F0-nolib/CANbus_stepper/src/main.c @@ -0,0 +1,94 @@ +/* + * main.c + * + * Copyright 2017 Edward V. Emelianoff + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#include "adc.h" +#include "hardware.h" +#include "proto.h" +#include "usart.h" +#include "usb.h" +#include "usb_lib.h" + +volatile uint32_t Tms = 0; + +/* Called when systick fires */ +void sys_tick_handler(void){ + ++Tms; +} + +/* +void linecoding_handler(usb_LineCoding *lc){ + memcpy(&new_lc, lc, sizeof(usb_LineCoding)); +} +void clstate_handler(uint16_t val){ + SEND("change control line state to "); + printu(val); + if(val & CONTROL_DTR) SEND(" (DTR)"); + if(val & CONTROL_RTS) SEND(" (RTS)"); + usart_putchar('\n'); +}*/ + +int main(void){ + uint32_t lastT = 0; + char tmpbuf[129]; + sysreset(); + SysTick_Config(6000, 1); + gpio_setup(); + usart_setup(); + adc_setup(); + if(RCC->CSR & RCC_CSR_IWDGRSTF){ // watchdog reset occured + usart_send_blocking("WDGRESET=1\n", 11); + } + if(RCC->CSR & RCC_CSR_SFTRSTF){ // software reset occured + usart_send_blocking("SOFTRESET=1\n", 12); + } + RCC->CSR |= RCC_CSR_RMVF; // remove reset flags + USB_setup(); + //iwdg_setup(); + + while (1){ + IWDG->KR = IWDG_REFRESH; // refresh watchdog + if(lastT > Tms || Tms - lastT > 499){ + lastT = Tms; + } + usb_proc(); + usart_proc(); // switch RS-485 to Rx after last byte sent + uint8_t r = 0; + if((r = USB_receive(tmpbuf, 128))){ + tmpbuf[r] = 0; + cmd_parser(tmpbuf, TARGET_USB); + } + if(usartrx()){ // usart1 received data, store in in buffer + char *txt = NULL; + r = usart_getline(&txt); +/* +buftgt(TARGET_USB); +addtobuf("got "); +printu(r); +addtobuf(" bytes over USART:\n"); +addtobuf(txt); +addtobuf("\n====\n"); +sendbuf(); +*/ + cmd_parser(txt, TARGET_USART); + } + } + return 0; +} + diff --git a/F0-nolib/CANbus_stepper/src/proto.c b/F0-nolib/CANbus_stepper/src/proto.c new file mode 100644 index 0000000..3f15f39 --- /dev/null +++ b/F0-nolib/CANbus_stepper/src/proto.c @@ -0,0 +1,184 @@ +/* + * geany_encoding=koi8-r + * proto.c + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ +#include "adc.h" +#include "hardware.h" +#include "proto.h" +#include "usart.h" +#include "usb.h" +#include // strlen, strcpy( + +extern volatile uint8_t canerror; + +#define BUFSZ UARTBUFSZ + +static char buff[BUFSZ+1], *bptr = buff; +static uint8_t blen = 0, // length of data in `buff` + USBcmd = 0; // ==1 if buffer prepared for USB + +void buftgt(uint8_t isUSB){ + USBcmd = isUSB; +} + +void sendbuf(){ + IWDG->KR = IWDG_REFRESH; + if(blen == 0) return; + if(USBcmd){ + *bptr = 0; + USB_send(buff); + }else while(LINE_BUSY == usart_send(buff, blen)){IWDG->KR = IWDG_REFRESH;} + bptr = buff; + blen = 0; +} + +void addtobuf(const char *txt){ + IWDG->KR = IWDG_REFRESH; + int l = strlen(txt); + if(l > BUFSZ){ + sendbuf(); + if(USBcmd) USB_send(txt); + else usart_send_blocking(txt, l); + }else{ + if(blen+l > BUFSZ){ + sendbuf(); + } + strcpy(bptr, txt); + bptr += l; + } + blen += l; +} + +void bufputchar(char ch){ + if(blen > BUFSZ-1){ + sendbuf(); + } + *bptr++ = ch; + ++blen; +} + +// show all ADC values +static inline void showADCvals(){ + char msg[] = "ADCn="; + for(int n = 0; n < NUMBER_OF_ADC_CHANNELS; ++n){ + msg[3] = n + '0'; + addtobuf(msg); + printu(getADCval(n)); + newline(); + } +} + +static inline void printmcut(){ + SEND("MCUT="); + int32_t T = getMCUtemp(); + if(T < 0){ + bufputchar('-'); + T = -T; + } + printu(T); + newline(); +} + +static inline void showUIvals(){ + uint16_t *vals = getUval(); + SEND("V12="); printu(vals[0]); + SEND("\nV5="); printu(vals[1]); + SEND("\nV33="); printu(getVdd()); + newline(); +} + +/** + * @brief cmd_parser - command parsing + * @param txt - buffer with commands & data + * @param isUSB - == 1 if data got from USB + */ +void cmd_parser(const char *txt, uint8_t isUSB){ + sendbuf(); + USBcmd = isUSB; + //int16_t L = strlen(txt); + char _1st = txt[0]; + switch(_1st){ + case 'a': + showADCvals(); + break; + case 'D': + SEND("Jump to bootloader.\n"); + sendbuf(); + Jump2Boot(); + break; + case 'g': + SEND("Board address: "); + printuhex(refreshBRDaddr()); + newline(); + break; + case 'j': + printmcut(); + break; + case 'k': + showUIvals(); + break; + case 't': + if(ALL_OK != usart_send("TEST test\n", 10)) + addtobuf("Can't send data over RS485\n"); + else addtobuf("Sent\n"); + break; + default: // help + SEND( + "a - get raw ADC values\n" + "D - switch to bootloader\n" + "g - get board address\n" + "j - get MCU temperature\n" + "k - get U values\n" + "t - send test sequence over RS-485\n" + ); + break; + } + sendbuf(); +} + +// print 32bit unsigned int +void printu(uint32_t val){ + char buf[11], *bufptr = &buf[10]; + *bufptr = 0; + if(!val){ + *(--bufptr) = '0'; + }else{ + while(val){ + *(--bufptr) = val % 10 + '0'; + val /= 10; + } + } + addtobuf(bufptr); +} + +// print 32bit unsigned int as hex +void printuhex(uint32_t val){ + addtobuf("0x"); + uint8_t *ptr = (uint8_t*)&val + 3; + int i, j; + for(i = 0; i < 4; ++i, --ptr){ + for(j = 1; j > -1; --j){ + uint8_t half = (*ptr >> (4*j)) & 0x0f; + if(half < 10) bufputchar(half + '0'); + else bufputchar(half - 10 + 'a'); + } + } +} diff --git a/F0-nolib/CANbus_stepper/src/proto.h b/F0-nolib/CANbus_stepper/src/proto.h new file mode 100644 index 0000000..8283ec8 --- /dev/null +++ b/F0-nolib/CANbus_stepper/src/proto.h @@ -0,0 +1,50 @@ +/* + * geany_encoding=koi8-r + * proto.h + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ +#pragma once +#ifndef __PROTO_H__ +#define __PROTO_H__ + +#include "hardware.h" + +// macro for static strings +#define SEND(str) do{addtobuf(str);}while(0) + +#ifdef EBUG +#define MSG(str) do{addtobuf(__FILE__ " (L" STR(__LINE__) "): " str);}while(0) +#else +#define MSG(str) +#endif + +#define newline() do{bufputchar('\n');}while(0) + +void cmd_parser(const char *buf, uint8_t isUSB); +void addtobuf(const char *txt); +void bufputchar(char ch); +void printu(uint32_t val); +void printuhex(uint32_t val); +void sendbuf(); +#define TARGET_USB 1 +#define TARGET_USART 0 +void buftgt(uint8_t isUSB); + +#endif // __PROTO_H__ diff --git a/F0-nolib/CANbus_stepper/src/usart.c b/F0-nolib/CANbus_stepper/src/usart.c new file mode 100644 index 0000000..b176127 --- /dev/null +++ b/F0-nolib/CANbus_stepper/src/usart.c @@ -0,0 +1,260 @@ +/* + * usart.c + * + * Copyright 2017 Edward V. Emelianoff + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#include "hardware.h" +#include "usart.h" + +#include +#include + +typedef enum{ + READING, + SENDING, + WAITING +} _485_state; +static _485_state st = READING; // RS-485 state: Rx, Tx (DMA), TX last byte + +// switch to Rx/Tx: +#define _485_Rx() do{RS485_RX(); st = READING; USARTX->CR1 = (USARTX->CR1 & ~USART_CR1_TE) | USART_CR1_RE;}while(0) +#define _485_Tx() do{RS485_TX(); st = SENDING; USARTX->CR1 = (USARTX->CR1 & ~USART_CR1_RE) | USART_CR1_TE;}while(0) + +static int datalen[2] = {0,0}; // received data line length (including '\n') + +volatile int + linerdy = 0, // received data ready + bufovr = 0 // input buffer overfull +; + +static volatile int + dlen = 0, // length of data (including '\n') in current buffer + txrdy = 1 // transmission done +; + +static int rbufno = 0; // current rbuf number +static char rbuf[UARTBUFSZ][2], tbuf[UARTBUFSZ]; // receive & transmit buffers +static char *recvdata = NULL; + +/** + * return length of received data (without trailing zero) + */ +int usart_getline(char **line){ + if(!line) return 0; + if(bufovr){ + bufovr = 0; + linerdy = 0; + return 0; + } + *line = recvdata; + line[dlen] = 0; + linerdy = 0; + return dlen; +} + +/** + * @brief usart_send_blocking - blocking send of any message + * @param str - message to send + * @param len - its length + * @return: + * LINE_BUSY if previous message still in transit + * STR_TOO_LONG if len > UARTBUFSZ + * ALL_OK if message is in sending queue + */ +TXstatus usart_send(const char *str, int len){ + if(!txrdy) return LINE_BUSY; + if(len > UARTBUFSZ) return STR_TOO_LONG; + txrdy = 0; + _485_Tx(); // switch to transmission + memcpy(tbuf, str, len); +#if USARTNUM == 2 + DMA1_Channel4->CNDTR = len; + DMA1_Channel4->CCR |= DMA_CCR_EN; // start transmission +#elif USARTNUM == 1 + DMA1_Channel2->CNDTR = len; + DMA1_Channel2->CCR |= DMA_CCR_EN; +#else +#error "Not implemented" +#endif + return ALL_OK; +} + +/** + * @brief usart_send_blocking - blocking send of any message + * @param str - message to send + * @param len - its length + */ +void usart_send_blocking(const char *str, int len){ + uint32_t tmout = 160000; + while(!txrdy){ + IWDG->KR = IWDG_REFRESH; + if(--tmout == 0) return; + } + _485_Tx(); + bufovr = 0; + for(int i = 0; i < len; ++i){ + USARTX -> TDR = *str++; + while(!(USARTX->ISR & USART_ISR_TXE)){IWDG->KR = IWDG_REFRESH;} + } + while(!(USARTX->ISR & USART_ISR_TC)){IWDG->KR = IWDG_REFRESH;} + _485_Rx(); +} + +void usart_setup(){ +#if USARTNUM == 2 + // setup pins: PA2 (Tx - AF1), PA15 (Rx - AF1) + // AF mode (AF1) + GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER2|GPIO_MODER_MODER15))\ + | (GPIO_MODER_MODER2_AF | GPIO_MODER_MODER15_AF); + GPIOA->AFR[0] = (GPIOA->AFR[0] &~GPIO_AFRH_AFRH2) | 1 << (2 * 4); // PA2 + GPIOA->AFR[1] = (GPIOA->AFR[1] &~GPIO_AFRH_AFRH7) | 1 << (7 * 4); // PA15 + // DMA: Tx - Ch4 + DMA1_Channel4->CPAR = (uint32_t) &USART2->TDR; // periph + DMA1_Channel4->CMAR = (uint32_t) tbuf; // mem + DMA1_Channel4->CCR |= DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE; // 8bit, mem++, mem->per, transcompl irq + // Tx CNDTR set @ each transmission due to data size + NVIC_SetPriority(DMA1_Channel4_5_IRQn, 3); + NVIC_EnableIRQ(DMA1_Channel4_5_IRQn); + NVIC_SetPriority(USART2_IRQn, 0); + // setup usart2 + RCC->APB1ENR |= RCC_APB1ENR_USART2EN; // clock + // oversampling by16, 115200bps (fck=48mHz) + //USART2_BRR = 0x1a1; // 48000000 / 115200 + USART2->BRR = 480000 / 1152; + USART2->CR3 = USART_CR3_DMAT; // enable DMA Tx + USART2->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; // 1start,8data,nstop; enable Rx,Tx,USART + while(!(USART2->ISR & USART_ISR_TC)); // polling idle frame Transmission + USART2->ICR |= USART_ICR_TCCF; // clear TC flag + USART2->CR1 |= USART_CR1_RXNEIE; + NVIC_EnableIRQ(USART2_IRQn); +// USART1 of main board +#elif USARTNUM == 1 + // PA9 - Tx, PA10 - Rx (AF1) + GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER9 | GPIO_MODER_MODER10))\ + | (GPIO_MODER_MODER9_AF | GPIO_MODER_MODER10_AF); + GPIOA->AFR[1] = (GPIOA->AFR[1] & ~(GPIO_AFRH_AFRH1 | GPIO_AFRH_AFRH2)) | + 1 << (1 * 4) | 1 << (2 * 4); // PA9, PA10 + // USART1 Tx DMA - Channel2 (default value in SYSCFG_CFGR1) + DMA1_Channel2->CPAR = (uint32_t) &USART1->TDR; // periph + DMA1_Channel2->CMAR = (uint32_t) tbuf; // mem + DMA1_Channel2->CCR |= DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE; // 8bit, mem++, mem->per, transcompl irq + // Tx CNDTR set @ each transmission due to data size + NVIC_SetPriority(DMA1_Channel2_3_IRQn, 3); + NVIC_EnableIRQ(DMA1_Channel2_3_IRQn); + NVIC_SetPriority(USART1_IRQn, 0); + // setup usart1 + RCC->APB2ENR |= RCC_APB2ENR_USART1EN; + USART1->BRR = 480000 / 1152; + USART1->CR3 = USART_CR3_DMAT; // enable DMA Tx + USART1->CR1 = USART_CR1_UE; // 1start,8data,nstop; enable USART + while(!(USART1->ISR & USART_ISR_TC)); // polling idle frame Transmission + USART1->ICR |= USART_ICR_TCCF; // clear TC flag + USART1->CR1 |= USART_CR1_RXNEIE; + NVIC_EnableIRQ(USART1_IRQn); +#else +#error "Not implemented" +#endif + _485_Rx(); // turn RX on (enable Rx, disable Tx) +} + +#if USARTNUM == 2 +void usart2_isr(){ +// USART1 +#elif USARTNUM == 1 +void usart1_isr(){ +#else +#error "Not implemented" +#endif + #ifdef CHECK_TMOUT + static uint32_t tmout = 0; + #endif + if(USARTX->ISR & USART_ISR_RXNE){ // RX not emty - receive next char + #ifdef CHECK_TMOUT + if(tmout && Tms >= tmout){ // set overflow flag + bufovr = 1; + datalen[rbufno] = 0; + } + tmout = Tms + TIMEOUT_MS; + if(!tmout) tmout = 1; // prevent 0 + #endif + // read RDR clears flag + uint8_t rb = USARTX->RDR; + if(datalen[rbufno] < UARTBUFSZ-1){ // put next char into buf + rbuf[rbufno][datalen[rbufno]++] = rb; + if(rb == '\n'){ // got newline - line ready + linerdy = 1; + dlen = datalen[rbufno]; + recvdata = rbuf[rbufno]; + // prepare other buffer + rbufno = !rbufno; + datalen[rbufno] = 0; + #ifdef CHECK_TMOUT + // clear timeout at line end + tmout = 0; + #endif + } + }else{ // buffer overfull + bufovr = 1; + datalen[rbufno] = 0; + #ifdef CHECK_TMOUT + tmout = 0; + #endif + } + } +} + + +/** + * @brief usart_proc - switch 485 to Rx when all data received + */ +void usart_proc(){ + switch(st){ + case SENDING: + if(txrdy) st = WAITING; + break; + case WAITING: + if(USARTX->ISR & USART_ISR_TC){ // last byte done -> Rx + _485_Rx(); + } + break; + default: + break; + } +} + +#if USARTNUM == 2 +void dma1_channel4_5_isr(){ + if(DMA1->ISR & DMA_ISR_TCIF4){ // Tx + DMA1->IFCR |= DMA_IFCR_CTCIF4; // clear TC flag + DMA1_Channel4->CCR &= ~DMA_CCR_EN; + txrdy = 1; + RS485_RX(); // switch to Rx + } +} +// USART1 +#elif USARTNUM == 1 +void dma1_channel2_3_isr(){ + if(DMA1->ISR & DMA_ISR_TCIF2){ // Tx + DMA1->IFCR |= DMA_IFCR_CTCIF2; // clear TC flag + DMA1_Channel2->CCR &= ~DMA_CCR_EN; + txrdy = 1; + } +} +#else +#error "Not implemented" +#endif diff --git a/F0-nolib/CANbus_stepper/src/usart.h b/F0-nolib/CANbus_stepper/src/usart.h new file mode 100644 index 0000000..cbf011a --- /dev/null +++ b/F0-nolib/CANbus_stepper/src/usart.h @@ -0,0 +1,49 @@ +/* + * usart.h + * + * Copyright 2017 Edward V. Emelianoff + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#pragma once +#ifndef __USART_H__ +#define __USART_H__ + +// input and output buffers size +#define UARTBUFSZ (64) +// timeout between data bytes +#ifndef TIMEOUT_MS +#define TIMEOUT_MS (1500) +#endif + +typedef enum{ + ALL_OK, + LINE_BUSY, + STR_TOO_LONG +} TXstatus; + +#define usartrx() (linerdy) +#define usartovr() (bufovr) + +extern volatile int linerdy, bufovr; + +void usart_setup(); +int usart_getline(char **line); +TXstatus usart_send(const char *str, int len); +void usart_send_blocking(const char *str, int len); +void usart_proc(); + +#endif // __USART_H__ diff --git a/F0-nolib/CANbus_stepper/src/usb.c b/F0-nolib/CANbus_stepper/src/usb.c new file mode 100644 index 0000000..a63b728 --- /dev/null +++ b/F0-nolib/CANbus_stepper/src/usb.c @@ -0,0 +1,181 @@ +/* + * geany_encoding=koi8-r + * usb.c - base functions for different USB types + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +#include "usb.h" +#include "usb_lib.h" +#include // memcpy, memmove + +// incoming buffer size +#define IDATASZ (256) +static uint8_t incoming_data[IDATASZ]; +static uint8_t ovfl = 0; +static uint16_t idatalen = 0; +static int8_t usbON = 0; // ==1 when USB fully configured +static volatile uint8_t tx_succesfull = 0; + +// interrupt IN handler (never used?) +static uint16_t EP1_Handler(ep_t ep){ + uint8_t ep0buf[11]; + if (ep.rx_flag){ + EP_Read(1, ep0buf); + ep.status = SET_VALID_TX(ep.status); + ep.status = KEEP_STAT_RX(ep.status); + }else if (ep.tx_flag){ + ep.status = SET_VALID_RX(ep.status); + ep.status = SET_STALL_TX(ep.status); + } + return ep.status; +} + +// data IN/OUT handler +static uint16_t EP23_Handler(ep_t ep){ + if(ep.rx_flag){ + int rd = ep.rx_cnt, rest = IDATASZ - idatalen; + if(rd){ + if(rd <= rest){ + idatalen += EP_Read(2, &incoming_data[idatalen]); + ovfl = 0; + }else{ + ep.status = SET_NAK_RX(ep.status); + ovfl = 1; + return ep.status; + } + } + ep.status = CLEAR_DTOG_RX(ep.status); + ep.status = CLEAR_DTOG_TX(ep.status); + ep.status = SET_STALL_TX(ep.status); + }else if (ep.tx_flag){ + ep.status = KEEP_STAT_TX(ep.status); + tx_succesfull = 1; + } + ep.status = SET_VALID_RX(ep.status); + return ep.status; +} + +void USB_setup(){ + RCC->APB1ENR |= RCC_APB1ENR_CRSEN | RCC_APB1ENR_USBEN; // enable CRS (hsi48 sync) & USB + RCC->CFGR3 &= ~RCC_CFGR3_USBSW; // reset USB + RCC->CR2 |= RCC_CR2_HSI48ON; // turn ON HSI48 + uint32_t tmout = 16000000; + while(!(RCC->CR2 & RCC_CR2_HSI48RDY)){if(--tmout == 0) break; IWDG->KR = IWDG_REFRESH;} + FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY; + CRS->CFGR &= ~CRS_CFGR_SYNCSRC; + CRS->CFGR |= CRS_CFGR_SYNCSRC_1; // USB SOF selected as sync source + CRS->CR |= CRS_CR_AUTOTRIMEN; // enable auto trim + CRS->CR |= CRS_CR_CEN; // enable freq counter & block CRS->CFGR as read-only + RCC->CFGR |= RCC_CFGR_SW; + // allow RESET and CTRM interrupts + USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM; + // clear flags + USB->ISTR = 0; + // and activate pullup + USB->BCDR |= USB_BCDR_DPPU; + NVIC_EnableIRQ(USB_IRQn); +} + +void usb_proc(){ + if(USB_GetState() == USB_CONFIGURE_STATE){ // USB configured - activate other endpoints + if(!usbON){ // endpoints not activated + // make new BULK endpoint + // Buffer have 1024 bytes, but last 256 we use for CAN bus (30.2 of RM: USB main features) + EP_Init(1, EP_TYPE_INTERRUPT, 10, 0, EP1_Handler); // IN1 - transmit + EP_Init(2, EP_TYPE_BULK, 0, USB_RXBUFSZ, EP23_Handler); // OUT2 - receive data + EP_Init(3, EP_TYPE_BULK, USB_TXBUFSZ, 0, EP23_Handler); // IN3 - transmit data + usbON = 1; + } + }else{ + usbON = 0; + } +} + +void USB_send(const char *buf){ + uint16_t l = 0, ctr = 0; + const char *p = buf; + while(*p++) ++l; + while(l){ + IWDG->KR = IWDG_REFRESH; + uint16_t s = (l > USB_TXBUFSZ) ? USB_TXBUFSZ : l; + tx_succesfull = 0; + EP_Write(3, (uint8_t*)&buf[ctr], s); + uint32_t ctra = 1000000; + while(--ctra && tx_succesfull == 0){IWDG->KR = IWDG_REFRESH;} + l -= s; + ctr += s; + } +} + +/** + * @brief USB_receive - read first received text string + * @param buf (i) - buffer for received data + * @param bufsize - its size + * @return amount of received bytes + */ +int USB_receive(char *buf, int bufsize){ + if(bufsize<1 || !idatalen) return 0; + IWDG->KR = IWDG_REFRESH; + int stlen = 0, i; + for(i = 0; i < idatalen; ++i){ + if(incoming_data[i] == '\n'){ + stlen = i+1; + break; + } + } + if(i == idatalen || stlen == 0) return 0; + /* + char x[] = "USB got x:\n"; + x[8] = '0' + stlen; + usart_send_blck(x); + usart_send_blck((char*)incoming_data); + usart_send_blck("\n"); + */ + USB->CNTR = 0; + int sz = (stlen > bufsize) ? bufsize : stlen, rest = idatalen - sz; + memcpy(buf, incoming_data, sz); + buf[sz] = 0; + /* + usart_send_blck("buf:\n"); + usart_send_blck((char*)buf); + usart_send_blck("\n"); + */ + if(rest > 0){ + memmove(incoming_data, &incoming_data[sz], rest); + idatalen = rest; + }else idatalen = 0; + if(ovfl){ + EP23_Handler(endpoints[2]); + uint16_t epstatus = USB->EPnR[2]; + epstatus = CLEAR_DTOG_RX(epstatus); + epstatus = SET_VALID_RX(epstatus); + USB->EPnR[2] = epstatus; + } + USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM; + return sz; +} + +/** + * @brief USB_configured + * @return 1 if USB is in configured state + */ +int USB_configured(){ + return usbON; +} diff --git a/F0-nolib/CANbus_stepper/src/usb.h b/F0-nolib/CANbus_stepper/src/usb.h new file mode 100644 index 0000000..75d22b4 --- /dev/null +++ b/F0-nolib/CANbus_stepper/src/usb.h @@ -0,0 +1,37 @@ +/* + * geany_encoding=koi8-r + * usb.h + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ +#pragma once +#ifndef __USB_H__ +#define __USB_H__ + +#include "hardware.h" + +#define BUFFSIZE (64) + +void USB_setup(); +void usb_proc(); +void USB_send(const char *buf); +int USB_receive(char *buf, int bufsize); +int USB_configured(); + +#endif // __USB_H__ diff --git a/F0-nolib/CANbus_stepper/src/usb_defs.h b/F0-nolib/CANbus_stepper/src/usb_defs.h new file mode 100644 index 0000000..6ac673c --- /dev/null +++ b/F0-nolib/CANbus_stepper/src/usb_defs.h @@ -0,0 +1,106 @@ +/* + * geany_encoding=koi8-r + * usb_defs.h + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +#pragma once +#ifndef __USB_DEFS_H__ +#define __USB_DEFS_H__ + +#include + +/** + * Buffers size definition + **/ +// !!! when working with CAN bus change USB_BTABLE_SIZE to 768 !!! +#define USB_BTABLE_SIZE 1024 +// first 64 bytes of USB_BTABLE are registers! +#define USB_EP0_BASEADDR 64 +// for USB FS EP0 buffers are from 8 to 64 bytes long (64 for PL2303) +#define USB_EP0_BUFSZ 64 +// USB transmit buffer size (64 for PL2303) +#define USB_TXBUFSZ 64 +// USB receive buffer size (64 for PL2303) +#define USB_RXBUFSZ 64 + +#define USB_BTABLE_BASE 0x40006000 +#undef USB_BTABLE +#define USB_BTABLE ((USB_BtableDef *)(USB_BTABLE_BASE)) +#define USB_ISTR_EPID 0x0000000F +#define USB_FNR_LSOF_0 0x00000800 +#define USB_FNR_lSOF_1 0x00001000 +#define USB_LPMCSR_BESL_0 0x00000010 +#define USB_LPMCSR_BESL_1 0x00000020 +#define USB_LPMCSR_BESL_2 0x00000040 +#define USB_LPMCSR_BESL_3 0x00000080 +#define USB_EPnR_CTR_RX 0x00008000 +#define USB_EPnR_DTOG_RX 0x00004000 +#define USB_EPnR_STAT_RX 0x00003000 +#define USB_EPnR_STAT_RX_0 0x00001000 +#define USB_EPnR_STAT_RX_1 0x00002000 +#define USB_EPnR_SETUP 0x00000800 +#define USB_EPnR_EP_TYPE 0x00000600 +#define USB_EPnR_EP_TYPE_0 0x00000200 +#define USB_EPnR_EP_TYPE_1 0x00000400 +#define USB_EPnR_EP_KIND 0x00000100 +#define USB_EPnR_CTR_TX 0x00000080 +#define USB_EPnR_DTOG_TX 0x00000040 +#define USB_EPnR_STAT_TX 0x00000030 +#define USB_EPnR_STAT_TX_0 0x00000010 +#define USB_EPnR_STAT_TX_1 0x00000020 +#define USB_EPnR_EA 0x0000000F +#define USB_COUNTn_RX_BLSIZE 0x00008000 +#define USB_COUNTn_NUM_BLOCK 0x00007C00 +#define USB_COUNTn_RX 0x0000003F + +#define USB_TypeDef USB_TypeDef_custom + +typedef struct{ + __IO uint32_t EPnR[8]; + __IO uint32_t RESERVED1; + __IO uint32_t RESERVED2; + __IO uint32_t RESERVED3; + __IO uint32_t RESERVED4; + __IO uint32_t RESERVED5; + __IO uint32_t RESERVED6; + __IO uint32_t RESERVED7; + __IO uint32_t RESERVED8; + __IO uint32_t CNTR; + __IO uint32_t ISTR; + __IO uint32_t FNR; + __IO uint32_t DADDR; + __IO uint32_t BTABLE; + __IO uint32_t LPMCSR; + __IO uint32_t BCDR; +} USB_TypeDef; + +typedef struct{ + __IO uint16_t USB_ADDR_TX; + __IO uint16_t USB_COUNT_TX; + __IO uint16_t USB_ADDR_RX; + __IO uint16_t USB_COUNT_RX; +} USB_EPDATA_TypeDef; + +typedef struct{ + __IO USB_EPDATA_TypeDef EP[8]; +} USB_BtableDef; + +#endif // __USB_DEFS_H__ diff --git a/F0-nolib/CANbus_stepper/src/usb_lib.c b/F0-nolib/CANbus_stepper/src/usb_lib.c new file mode 100644 index 0000000..689af3e --- /dev/null +++ b/F0-nolib/CANbus_stepper/src/usb_lib.c @@ -0,0 +1,487 @@ +/* + * geany_encoding=koi8-r + * usb_lib.c + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ +#include "usb_lib.h" +#include +#include // memcpy + +#ifdef EBUG +#undef EBUG +#endif + +ep_t endpoints[ENDPOINTS_NUM]; + +static usb_dev_t USB_Dev; +static usb_LineCoding lineCoding = {115200, 0, 0, 8}; +static config_pack_t setup_packet; +static uint8_t ep0databuf[EP0DATABUF_SIZE]; +static uint8_t ep0dbuflen = 0; + +usb_LineCoding getLineCoding(){return lineCoding;} + +// definition of parts common for USB_DeviceDescriptor & USB_DeviceQualifierDescriptor +#define bcdUSB_L 0x10 +#define bcdUSB_H 0x01 +#define bDeviceClass 0 +#define bDeviceSubClass 0 +#define bDeviceProtocol 0 +#define bNumConfigurations 1 + +static const uint8_t USB_DeviceDescriptor[] = { + 18, // bLength + 0x01, // bDescriptorType - Device descriptor + bcdUSB_L, // bcdUSB_L - 1.10 + bcdUSB_H, // bcdUSB_H + bDeviceClass, // bDeviceClass - USB_COMM + bDeviceSubClass, // bDeviceSubClass + bDeviceProtocol, // bDeviceProtocol + USB_EP0_BUFSZ, // bMaxPacketSize + 0x7b, // idVendor_L PL2303: VID=0x067b, PID=0x2303 + 0x06, // idVendor_H + 0x03, // idProduct_L + 0x23, // idProduct_H + 0x00, // bcdDevice_Ver_L + 0x03, // bcdDevice_Ver_H + 0x01, // iManufacturer + 0x02, // iProduct + 0x00, // iSerialNumber + bNumConfigurations // bNumConfigurations +}; + +static const uint8_t USB_DeviceQualifierDescriptor[] = { + 10, //bLength + 0x06, // bDescriptorType - Device qualifier + bcdUSB_L, // bcdUSB_L + bcdUSB_H, // bcdUSB_H + bDeviceClass, // bDeviceClass + bDeviceSubClass, // bDeviceSubClass + bDeviceProtocol, // bDeviceProtocol + USB_EP0_BUFSZ, // bMaxPacketSize0 + bNumConfigurations, // bNumConfigurations + 0x00 // Reserved +}; + +static const uint8_t USB_ConfigDescriptor[] = { + /*Configuration Descriptor*/ + 0x09, /* bLength: Configuration Descriptor size */ + 0x02, /* bDescriptorType: Configuration */ + 39, /* wTotalLength:no of returned bytes */ + 0x00, + 0x01, /* bNumInterfaces: 1 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ + 0xa0, /* bmAttributes - Bus powered, Remote wakeup */ + 0x32, /* MaxPower 100 mA */ + + /*---------------------------------------------------------------------------*/ + + /*Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + 0x04, /* bDescriptorType: Interface */ + 0x00, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x03, /* bNumEndpoints: 3 endpoints used */ + 0xff, /* bInterfaceClass */ + 0x00, /* bInterfaceSubClass */ + 0x00, /* bInterfaceProtocol */ + 0x00, /* iInterface: */ +/////////////////////////////////////////////////// + /*Endpoint 1 Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + 0x05, /* bDescriptorType: Endpoint */ + 0x81, /* bEndpointAddress IN1 */ + 0x03, /* bmAttributes: Interrupt */ + 0x0a, /* wMaxPacketSize LO: */ + 0x00, /* wMaxPacketSize HI: */ + 0x01, /* bInterval: */ + + /*Endpoint OUT2 Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + 0x05, /* bDescriptorType: Endpoint */ + 0x02, /* bEndpointAddress: OUT2 */ + 0x02, /* bmAttributes: Bulk */ + (USB_RXBUFSZ & 0xff), /* wMaxPacketSize: 64 */ + (USB_RXBUFSZ >> 8), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /*Endpoint IN3 Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + 0x05, /* bDescriptorType: Endpoint */ + 0x83, /* bEndpointAddress IN3 */ + 0x02, /* bmAttributes: Bulk */ + (USB_TXBUFSZ & 0xff), /* wMaxPacketSize: 64 */ + (USB_TXBUFSZ >> 8), + 0x00, /* bInterval: ignore for Bulk transfer */ +}; + +_USB_LANG_ID_(USB_StringLangDescriptor, LANG_US); +// these descriptors are not used in PL2303 emulator! +_USB_STRING_(USB_StringSerialDescriptor, u"0"); +_USB_STRING_(USB_StringManufacturingDescriptor, u"Prolific Technology Inc."); +_USB_STRING_(USB_StringProdDescriptor, u"USB-Serial Controller"); + +/* + * default handlers + */ +// SET_LINE_CODING +void WEAK linecoding_handler(usb_LineCoding __attribute__((unused)) *lc){ +} + +// SET_CONTROL_LINE_STATE +void WEAK clstate_handler(uint16_t __attribute__((unused)) val){ +} + +// SEND_BREAK +void WEAK break_handler(){ +} + +// handler of vendor requests +void WEAK vendor_handler(config_pack_t *packet){ + if(packet->bmRequestType & 0x80){ // read + //SEND("Read"); + uint8_t c; + switch(packet->wValue){ + case 0x8484: + c = 2; + break; + case 0x0080: + c = 1; + break; + case 0x8686: + c = 0xaa; + break; + default: + c = 0; + } + EP_WriteIRQ(0, &c, 1); + }else{ // write ZLP + EP_WriteIRQ(0, (uint8_t *)0, 0); + } +} + +static void wr0(const uint8_t *buf, uint16_t size){ + if(setup_packet.wLength < size) size = setup_packet.wLength; + EP_WriteIRQ(0, buf, size); +} + +static inline void get_descriptor(){ + switch(setup_packet.wValue){ + case DEVICE_DESCRIPTOR: + wr0(USB_DeviceDescriptor, sizeof(USB_DeviceDescriptor)); + break; + case CONFIGURATION_DESCRIPTOR: + wr0(USB_ConfigDescriptor, sizeof(USB_ConfigDescriptor)); + break; + case STRING_LANG_DESCRIPTOR: + wr0((const uint8_t *)&USB_StringLangDescriptor, STRING_LANG_DESCRIPTOR_SIZE_BYTE); + break; + case STRING_MAN_DESCRIPTOR: + wr0((const uint8_t *)&USB_StringManufacturingDescriptor, USB_StringManufacturingDescriptor.bLength); + break; + case STRING_PROD_DESCRIPTOR: + wr0((const uint8_t *)&USB_StringProdDescriptor, USB_StringProdDescriptor.bLength); + break; + case STRING_SN_DESCRIPTOR: + wr0((const uint8_t *)&USB_StringSerialDescriptor, USB_StringSerialDescriptor.bLength); + break; + case DEVICE_QUALIFIER_DESCRIPTOR: + wr0(USB_DeviceQualifierDescriptor, USB_DeviceQualifierDescriptor[0]); + break; + default: + ; + break; + } +} + +static uint8_t configuration = 0; // reply for GET_CONFIGURATION (==1 if configured) +static inline void std_d2h_req(){ + uint16_t status = 0; // bus powered + switch(setup_packet.bRequest){ + case GET_DESCRIPTOR: + get_descriptor(); + break; + case GET_STATUS: + EP_WriteIRQ(0, (uint8_t *)&status, 2); // send status: Bus Powered + break; + case GET_CONFIGURATION: + EP_WriteIRQ(0, &configuration, 1); + break; + default: + ; + break; + } +} + +static inline void std_h2d_req(){ + switch(setup_packet.bRequest){ + case SET_ADDRESS: + // new address will be assigned later - after acknowlegement or request to host + USB_Dev.USB_Addr = setup_packet.wValue; + break; + case SET_CONFIGURATION: + // Now device configured + USB_Dev.USB_Status = USB_CONFIGURE_STATE; + configuration = setup_packet.wValue; + break; + default: + ; + break; + } +} + +/* +bmRequestType: 76543210 +7 direction: 0 - host->device, 1 - device->host +65 type: 0 - standard, 1 - class, 2 - vendor +4..0 getter: 0 - device, 1 - interface, 2 - endpoint, 3 - other +*/ +/** + * Endpoint0 (control) handler + * @param ep - endpoint state + * @return data written to EP0R + */ +static uint16_t EP0_Handler(ep_t ep){ + uint16_t epstatus = ep.status; // EP0R on input -> return this value after modifications + uint8_t reqtype = setup_packet.bmRequestType & 0x7f; + uint8_t dev2host = (setup_packet.bmRequestType & 0x80) ? 1 : 0; + if ((ep.rx_flag) && (ep.setup_flag)){ + switch(reqtype){ + case STANDARD_DEVICE_REQUEST_TYPE: // standard device request + if(dev2host){ + std_d2h_req(); + }else{ + std_h2d_req(); + EP_WriteIRQ(0, (uint8_t *)0, 0); + } + epstatus = SET_NAK_RX(epstatus); + epstatus = SET_VALID_TX(epstatus); + break; + case STANDARD_ENDPOINT_REQUEST_TYPE: // standard endpoint request + if(setup_packet.bRequest == CLEAR_FEATURE){ + EP_WriteIRQ(0, (uint8_t *)0, 0); + epstatus = SET_NAK_RX(epstatus); + epstatus = SET_VALID_TX(epstatus); + } + break; + case VENDOR_REQUEST_TYPE: + vendor_handler(&setup_packet); + epstatus = SET_NAK_RX(epstatus); + epstatus = SET_VALID_TX(epstatus); + break; + case CONTROL_REQUEST_TYPE: + switch(setup_packet.bRequest){ + case GET_LINE_CODING: + EP_WriteIRQ(0, (uint8_t*)&lineCoding, sizeof(lineCoding)); + break; + case SET_LINE_CODING: // omit this for next stage, when data will come + break; + case SET_CONTROL_LINE_STATE: + clstate_handler(setup_packet.wValue); + break; + case SEND_BREAK: + break_handler(); + break; + default: + break; + } + //if(!dev2host) EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement + if(setup_packet.bRequest != GET_LINE_CODING) EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement + epstatus = SET_VALID_RX(epstatus); + epstatus = SET_VALID_TX(epstatus); + break; + default: + EP_WriteIRQ(0, (uint8_t *)0, 0); + epstatus = SET_NAK_RX(epstatus); + epstatus = SET_VALID_TX(epstatus); + } + }else if (ep.rx_flag){ // got data over EP0 or host acknowlegement + if(ep.rx_cnt){ + //EP_WriteIRQ(0, (uint8_t *)0, 0); + if(setup_packet.bRequest == SET_LINE_CODING){ + linecoding_handler((usb_LineCoding*)ep0databuf); + } + } + // wait for new data from host + epstatus = SET_VALID_RX(epstatus); + epstatus = SET_VALID_TX(epstatus); + } else if (ep.tx_flag){ // package transmitted + // now we can change address after enumeration + if ((USB->DADDR & USB_DADDR_ADD) != USB_Dev.USB_Addr){ + USB->DADDR = USB_DADDR_EF | USB_Dev.USB_Addr; + // change state to ADRESSED + USB_Dev.USB_Status = USB_ADRESSED_STATE; + } + // end of transaction + epstatus = CLEAR_DTOG_RX(epstatus); + epstatus = CLEAR_DTOG_TX(epstatus); + epstatus = SET_VALID_RX(epstatus); + epstatus = SET_VALID_TX(epstatus); + } + return epstatus; +} + +static uint16_t lastaddr = USB_EP0_BASEADDR; +/** + * Endpoint initialisation + * !!! when working with CAN bus change USB_BTABLE_SIZE to 768 !!! + * @param number - EP num (0...7) + * @param type - EP type (EP_TYPE_BULK, EP_TYPE_CONTROL, EP_TYPE_ISO, EP_TYPE_INTERRUPT) + * @param txsz - transmission buffer size @ USB/CAN buffer + * @param rxsz - reception buffer size @ USB/CAN buffer + * @param uint16_t (*func)(ep_t *ep) - EP handler function + * @return 0 if all OK + */ +int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, uint16_t (*func)(ep_t ep)){ + if(number >= ENDPOINTS_NUM) return 4; // out of configured amount + if(txsz > USB_BTABLE_SIZE || rxsz > USB_BTABLE_SIZE) return 1; // buffer too large + if(lastaddr + txsz + rxsz >= USB_BTABLE_SIZE) return 2; // out of btable + USB->EPnR[number] = (type << 9) | (number & USB_EPnR_EA); + USB->EPnR[number] ^= USB_EPnR_STAT_RX | USB_EPnR_STAT_TX_1; + if(rxsz & 1 || rxsz > 992) return 3; // wrong rx buffer size + uint16_t countrx = 0; + if(rxsz < 64) countrx = rxsz / 2; + else{ + if(rxsz & 0x1f) return 3; // should be multiple of 32 + countrx = 31 + rxsz / 32; + } + USB_BTABLE->EP[number].USB_ADDR_TX = lastaddr; + endpoints[number].tx_buf = (uint16_t *)(USB_BTABLE_BASE + lastaddr); + lastaddr += txsz; + USB_BTABLE->EP[number].USB_COUNT_TX = 0; + USB_BTABLE->EP[number].USB_ADDR_RX = lastaddr; + endpoints[number].rx_buf = (uint8_t *)(USB_BTABLE_BASE + lastaddr); + lastaddr += rxsz; + // buffer size: Table127 of RM + USB_BTABLE->EP[number].USB_COUNT_RX = countrx << 10; + endpoints[number].func = func; + return 0; +} + +// standard IRQ handler +void usb_isr(){ + if (USB->ISTR & USB_ISTR_RESET){ + // Reinit registers + USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM; + USB->ISTR = 0; + // Endpoint 0 - CONTROL + // ON USB LS size of EP0 may be 8 bytes, but on FS it should be 64 bytes! + lastaddr = USB_EP0_BASEADDR; // roll back to beginning of buffer + // clear address, leave only enable bit + USB->DADDR = USB_DADDR_EF; + USB_Dev.USB_Status = USB_DEFAULT_STATE; + if(EP_Init(0, EP_TYPE_CONTROL, USB_EP0_BUFSZ, USB_EP0_BUFSZ, EP0_Handler)){ + return; + } + } + if(USB->ISTR & USB_ISTR_CTR){ + // EP number + uint8_t n = USB->ISTR & USB_ISTR_EPID; + // copy status register + uint16_t epstatus = USB->EPnR[n]; + // Calculate flags + endpoints[n].rx_flag = (epstatus & USB_EPnR_CTR_RX) ? 1 : 0; + endpoints[n].setup_flag = (epstatus & USB_EPnR_SETUP) ? 1 : 0; + endpoints[n].tx_flag = (epstatus & USB_EPnR_CTR_TX) ? 1 : 0; + // copy received bytes amount + endpoints[n].rx_cnt = USB_BTABLE->EP[n].USB_COUNT_RX & 0x3FF; // low 10 bits is counter + // check direction + if(USB->ISTR & USB_ISTR_DIR){ // OUT interrupt - receive data, CTR_RX==1 (if CTR_TX == 1 - two pending transactions: receive following by transmit) + if(n == 0){ // control endpoint + if(epstatus & USB_EPnR_SETUP){ // setup packet -> copy data to conf_pack + memcpy(&setup_packet, endpoints[0].rx_buf, sizeof(setup_packet)); + ep0dbuflen = 0; + // interrupt handler will be called later + }else if(epstatus & USB_EPnR_CTR_RX){ // data packet -> push received data to ep0databuf + ep0dbuflen = endpoints[0].rx_cnt; + memcpy(ep0databuf, endpoints[0].rx_buf, ep0dbuflen); + } + } + }else{ // IN interrupt - transmit data, only CTR_TX == 1 + // enumeration end could be here (if EP0) + } + // prepare status field for EP handler + endpoints[n].status = epstatus; + // call EP handler (even if it will change EPnR, it should return new status) + epstatus = endpoints[n].func(endpoints[n]); + // keep DTOG state + epstatus = KEEP_DTOG_TX(epstatus); + epstatus = KEEP_DTOG_RX(epstatus); + // clear all RX/TX flags + epstatus = CLEAR_CTR_RX(epstatus); + epstatus = CLEAR_CTR_TX(epstatus); + // refresh EPnR + USB->EPnR[n] = epstatus; + } +} + +/** + * Write data to EP buffer (called from IRQ handler) + * @param number - EP number + * @param *buf - array with data + * @param size - its size + */ +void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size){ + uint8_t i; + if(size > USB_TXBUFSZ) size = USB_TXBUFSZ; + uint16_t N2 = (size + 1) >> 1; + // the buffer is 16-bit, so we should copy data as it would be uint16_t + uint16_t *buf16 = (uint16_t *)buf; + for (i = 0; i < N2; i++){ + endpoints[number].tx_buf[i] = buf16[i]; + } + USB_BTABLE->EP[number].USB_COUNT_TX = size; +} + +/** + * Write data to EP buffer (called outside IRQ handler) + * @param number - EP number + * @param *buf - array with data + * @param size - its size + */ +void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size){ + uint16_t status = USB->EPnR[number]; + EP_WriteIRQ(number, buf, size); + status = SET_NAK_RX(status); + status = SET_VALID_TX(status); + status = KEEP_DTOG_TX(status); + status = KEEP_DTOG_RX(status); + USB->EPnR[number] = status; +} + +/* + * Copy data from EP buffer into user buffer area + * @param *buf - user array for data + * @return amount of data read + */ +int EP_Read(uint8_t number, uint8_t *buf){ + int n = endpoints[number].rx_cnt; + if(n){ + for(int i = 0; i < n; ++i) + buf[i] = endpoints[number].rx_buf[i]; + } + return n; +} + +// USB status +uint8_t USB_GetState(){ + return USB_Dev.USB_Status; +} diff --git a/F0-nolib/CANbus_stepper/src/usb_lib.h b/F0-nolib/CANbus_stepper/src/usb_lib.h new file mode 100644 index 0000000..0651e5f --- /dev/null +++ b/F0-nolib/CANbus_stepper/src/usb_lib.h @@ -0,0 +1,202 @@ +/* + * geany_encoding=koi8-r + * usb_lib.h + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +#pragma once +#ifndef __USB_LIB_H__ +#define __USB_LIB_H__ + +#include +#include "usb_defs.h" + +#define EP0DATABUF_SIZE (64) + +// Max EP amount (EP0 + other used) +#define ENDPOINTS_NUM 4 +// bmRequestType & 0x7f +#define STANDARD_DEVICE_REQUEST_TYPE 0 +#define STANDARD_ENDPOINT_REQUEST_TYPE 2 +#define VENDOR_REQUEST_TYPE 0x40 +#define CONTROL_REQUEST_TYPE 0x21 +// bRequest, standard; for bmRequestType == 0x80 +#define GET_STATUS 0x00 +#define GET_DESCRIPTOR 0x06 +#define GET_CONFIGURATION 0x08 +// for bmRequestType == 0 +#define CLEAR_FEATURE 0x01 +#define SET_FEATURE 0x03 // unused +#define SET_ADDRESS 0x05 +#define SET_DESCRIPTOR 0x07 // unused +#define SET_CONFIGURATION 0x09 +// for bmRequestType == 0x81, 1 or 0xB2 +#define GET_INTERFACE 0x0A // unused +#define SET_INTERFACE 0x0B // unused +#define SYNC_FRAME 0x0C // unused +#define VENDOR_REQUEST 0x01 // unused + +// Class-Specific Control Requests +#define SEND_ENCAPSULATED_COMMAND 0x00 // unused +#define GET_ENCAPSULATED_RESPONSE 0x01 // unused +#define SET_COMM_FEATURE 0x02 // unused +#define GET_COMM_FEATURE 0x03 // unused +#define CLEAR_COMM_FEATURE 0x04 // unused +#define SET_LINE_CODING 0x20 +#define GET_LINE_CODING 0x21 +#define SET_CONTROL_LINE_STATE 0x22 +#define SEND_BREAK 0x23 + +// control line states +#define CONTROL_DTR 0x01 +#define CONTROL_RTS 0x02 + +// wValue +#define DEVICE_DESCRIPTOR 0x100 +#define CONFIGURATION_DESCRIPTOR 0x200 +#define STRING_LANG_DESCRIPTOR 0x300 +#define STRING_MAN_DESCRIPTOR 0x301 +#define STRING_PROD_DESCRIPTOR 0x302 +#define STRING_SN_DESCRIPTOR 0x303 +#define DEVICE_QUALIFIER_DESCRIPTOR 0x600 + +// EPnR bits manipulation +#define CLEAR_DTOG_RX(R) (R & USB_EPnR_DTOG_RX) ? R : (R & (~USB_EPnR_DTOG_RX)) +#define SET_DTOG_RX(R) (R & USB_EPnR_DTOG_RX) ? (R & (~USB_EPnR_DTOG_RX)) : R +#define TOGGLE_DTOG_RX(R) (R | USB_EPnR_DTOG_RX) +#define KEEP_DTOG_RX(R) (R & (~USB_EPnR_DTOG_RX)) +#define CLEAR_DTOG_TX(R) (R & USB_EPnR_DTOG_TX) ? R : (R & (~USB_EPnR_DTOG_TX)) +#define SET_DTOG_TX(R) (R & USB_EPnR_DTOG_TX) ? (R & (~USB_EPnR_DTOG_TX)) : R +#define TOGGLE_DTOG_TX(R) (R | USB_EPnR_DTOG_TX) +#define KEEP_DTOG_TX(R) (R & (~USB_EPnR_DTOG_TX)) +#define SET_VALID_RX(R) ((R & USB_EPnR_STAT_RX) ^ USB_EPnR_STAT_RX) | (R & (~USB_EPnR_STAT_RX)) +#define SET_NAK_RX(R) ((R & USB_EPnR_STAT_RX) ^ USB_EPnR_STAT_RX_1) | (R & (~USB_EPnR_STAT_RX)) +#define SET_STALL_RX(R) ((R & USB_EPnR_STAT_RX) ^ USB_EPnR_STAT_RX_0) | (R & (~USB_EPnR_STAT_RX)) +#define KEEP_STAT_RX(R) (R & (~USB_EPnR_STAT_RX)) +#define SET_VALID_TX(R) ((R & USB_EPnR_STAT_TX) ^ USB_EPnR_STAT_TX) | (R & (~USB_EPnR_STAT_TX)) +#define SET_NAK_TX(R) ((R & USB_EPnR_STAT_TX) ^ USB_EPnR_STAT_TX_1) | (R & (~USB_EPnR_STAT_TX)) +#define SET_STALL_TX(R) ((R & USB_EPnR_STAT_TX) ^ USB_EPnR_STAT_TX_0) | (R & (~USB_EPnR_STAT_TX)) +#define KEEP_STAT_TX(R) (R & (~USB_EPnR_STAT_TX)) +#define CLEAR_CTR_RX(R) (R & (~USB_EPnR_CTR_RX)) +#define CLEAR_CTR_TX(R) (R & (~USB_EPnR_CTR_TX)) +#define CLEAR_CTR_RX_TX(R) (R & (~(USB_EPnR_CTR_TX | USB_EPnR_CTR_RX))) + +// USB state: uninitialized, addressed, ready for use +#define USB_DEFAULT_STATE 0 +#define USB_ADRESSED_STATE 1 +#define USB_CONFIGURE_STATE 2 + +// EP types +#define EP_TYPE_BULK 0x00 +#define EP_TYPE_CONTROL 0x01 +#define EP_TYPE_ISO 0x02 +#define EP_TYPE_INTERRUPT 0x03 + +#define LANG_US (uint16_t)0x0409 + +#define _USB_STRING_(name, str) \ +static const struct name \ +{ \ + uint8_t bLength; \ + uint8_t bDescriptorType; \ + uint16_t bString[(sizeof(str) - 2) / 2]; \ + \ +} \ +name = {sizeof(name), 0x03, str} + +#define _USB_LANG_ID_(name, lng_id) \ + \ +static const struct name \ +{ \ + uint8_t bLength; \ + uint8_t bDescriptorType; \ + uint16_t bString; \ + \ +} \ +name = {0x04, 0x03, lng_id} +#define STRING_LANG_DESCRIPTOR_SIZE_BYTE (4) + +// EP0 configuration packet +typedef struct { + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} config_pack_t; + +// endpoints state +typedef struct __ep_t{ + uint16_t *tx_buf; // transmission buffer address + uint8_t *rx_buf; // reception buffer address + uint16_t (*func)(); // endpoint action function + uint16_t status; // status flags + unsigned rx_cnt : 10; // received data counter + unsigned tx_flag : 1; // transmission flag + unsigned rx_flag : 1; // reception flag + unsigned setup_flag : 1; // this is setup packet (only for EP0) +} ep_t; + +// USB status & its address +typedef struct { + uint8_t USB_Status; + uint16_t USB_Addr; +}usb_dev_t; + +typedef struct { + uint32_t dwDTERate; + uint8_t bCharFormat; + #define USB_CDC_1_STOP_BITS 0 + #define USB_CDC_1_5_STOP_BITS 1 + #define USB_CDC_2_STOP_BITS 2 + uint8_t bParityType; + #define USB_CDC_NO_PARITY 0 + #define USB_CDC_ODD_PARITY 1 + #define USB_CDC_EVEN_PARITY 2 + #define USB_CDC_MARK_PARITY 3 + #define USB_CDC_SPACE_PARITY 4 + uint8_t bDataBits; +} __attribute__ ((packed)) usb_LineCoding; + +typedef struct { + uint8_t bmRequestType; + uint8_t bNotificationType; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} __attribute__ ((packed)) usb_cdc_notification; + +extern ep_t endpoints[]; + +void USB_Init(); +uint8_t USB_GetState(); +int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, uint16_t (*func)(ep_t ep)); +void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size); +void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size); +int EP_Read(uint8_t number, uint8_t *buf); +usb_LineCoding getLineCoding(); + + +void WEAK linecoding_handler(usb_LineCoding *lc); +void WEAK clstate_handler(uint16_t val); +void WEAK break_handler(); +void WEAK vendor_handler(config_pack_t *packet); + +#endif // __USB_LIB_H__ diff --git a/F0-nolib/Snippets/Jump2Boot.c b/F0-nolib/Snippets/Jump2Boot.c index 63dcd64..787ca1c 100644 --- a/F0-nolib/Snippets/Jump2Boot.c +++ b/F0-nolib/Snippets/Jump2Boot.c @@ -6,22 +6,32 @@ #define SYSMEM09x 0x1FFFD800 #define SystemMem SYSMEM07x -typedef void (*pF)(void); -uint32_t JumpAddress = *(volatile uint32_t*) (SystemMem + 4); -pF Jump_To_Boot = (pFunction) JumpAddress; -// first - deinit all peripherial!!!! -/* -// default timing settings -SysTick->CTRL = 0; -SysTick->LOAD = 0; -SysTick->VAL = 0; -*/ -__disable_irq(); // - may not work -// remap memory to 0 -SYSCFG->CFGR1 = 0x01; - -__set_MSP(*(volatile uint32_t*) SystemMem); -Jump_To_Boot(); +void Jump2Boot(){ // for STM32F072 + void (*SysMemBootJump)(void); + volatile uint32_t addr = 0x1FFFC800; + // reset systick + SysTick->CTRL = 0; + // reset clocks + RCC->APB1RSTR = RCC_APB1RSTR_CECRST | RCC_APB1RSTR_DACRST | RCC_APB1RSTR_PWRRST | RCC_APB1RSTR_CRSRST | + RCC_APB1RSTR_CANRST | RCC_APB1RSTR_USBRST | RCC_APB1RSTR_I2C2RST | RCC_APB1RSTR_I2C1RST | + RCC_APB1RSTR_USART4RST | RCC_APB1RSTR_USART3RST | RCC_APB1RSTR_USART2RST | RCC_APB1RSTR_SPI2RST | + RCC_APB1RSTR_WWDGRST | RCC_APB1RSTR_TIM14RST | RCC_APB1RSTR_TIM7RST | RCC_APB1RSTR_TIM6RST | + RCC_APB1RSTR_TIM3RST | RCC_APB1RSTR_TIM2RST; + RCC->APB2RSTR = RCC_APB2RSTR_DBGMCURST | RCC_APB2RSTR_TIM17RST | RCC_APB2RSTR_TIM16RST | RCC_APB2RSTR_TIM15RST | + RCC_APB2RSTR_USART1RST | RCC_APB2RSTR_SPI1RST | RCC_APB2RSTR_TIM1RST | RCC_APB2RSTR_ADCRST | RCC_APB2RSTR_SYSCFGRST; + RCC->AHBRSTR = 0; + RCC->APB1RSTR = 0; + RCC->APB2RSTR = 0; + // Enable the SYSCFG peripheral. + RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; + // remap memory to 0 (only for STM32F0) + SYSCFG->CFGR1 = 0x01; __DSB(); __ISB(); + SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4))); + // set main stack pointer + __set_MSP(*((uint32_t *)addr)); + // jump to bootloader + SysMemBootJump(); +} \ No newline at end of file diff --git a/F0-nolib/inc/F0/stm32f0.h b/F0-nolib/inc/F0/stm32f0.h index 4970cc7..e383438 100644 --- a/F0-nolib/inc/F0/stm32f0.h +++ b/F0-nolib/inc/F0/stm32f0.h @@ -21,7 +21,7 @@ #pragma once #ifndef __STM32F0_H__ #define __STM32F0_H__ - +#include #include "stm32f0xx.h" #ifndef TRUE_INLINE @@ -193,8 +193,8 @@ TRUE_INLINE void StartHSI48(){ gpioport->BSRR = ((__port & gpios) << 16) | (~__port & gpios);}while(0) #define pin_set(gpioport, gpios) do{gpioport->BSRR = gpios;}while(0) -#define pin_clear(gpioport, gpios) do{gpioport->BSRR = (gpios << 16);}while(0) -#define pin_read(gpioport, gpios) (gpioport->IDR & gpios ? 1 : 0) +#define pin_clear(gpioport, gpios) do{gpioport->BRR = gpios;}while(0) +#define pin_read(gpioport, gpios) ((gpioport->IDR & gpios) ? 1 : 0) #define pin_write(gpioport, gpios) do{gpioport->ODR = gpios;}while(0) /************************* ADC *************************/