mirror of
https://github.com/EFeru/hoverboard-sideboard-hack-GD.git
synced 2025-07-27 01:29:32 +00:00
Added Platformio support
- firmware can now be built in Platformio too - minor bug fixes - added LED board picture
This commit is contained in:
parent
b69942e80e
commit
882d4b0115
5
.gitignore
vendored
5
.gitignore
vendored
@ -3,12 +3,11 @@
|
||||
.vscode/
|
||||
MDK-ARM/Listing/
|
||||
MDK-ARM/Objects/
|
||||
MDK-ARM/*.uvgui
|
||||
MDK-ARM/*.uvgui.*
|
||||
build/
|
||||
!build/VARIANT_DEBUG/firmware.hex
|
||||
!build/VARIANT_DEBUG/firmware.bin
|
||||
!build/VARIANT_DEBUG/firmware.elf
|
||||
!build/VARIANT_DEBUG/firmware.axf
|
||||
!build/VARIANT_HOVERBOARD/firmware.hex
|
||||
!build/VARIANT_HOVERBOARD/firmware.bin
|
||||
!build/VARIANT_HOVERBOARD/firmware.elf
|
||||
!build/VARIANT_HOVERBOARD/firmware.axf
|
11
.travis.yml
11
.travis.yml
@ -45,3 +45,14 @@ jobs:
|
||||
- export PATH=$HOME/arm-gcc-toolchain/bin:$PATH
|
||||
before_script: arm-none-eabi-gcc --version
|
||||
|
||||
# # Not yet supportted, see https://community.platformio.org/t/build-gd32-project-with-platformio/11944
|
||||
# - name: platformio
|
||||
# script: platformio run
|
||||
# language: python
|
||||
# python:
|
||||
# - "2.7"
|
||||
# install:
|
||||
# - pip install -U platformio
|
||||
# - platformio update
|
||||
# cache:
|
||||
# - directories: "~/.platformio"
|
@ -1,19 +1,24 @@
|
||||
/*
|
||||
*
|
||||
* Automatically generated file
|
||||
* PlatformIO default linker script template for STM32 F1/F2/F3/F4/F7/L0/L1/L4
|
||||
*
|
||||
*/
|
||||
|
||||
/* Entry Point */
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
/* Highest address of the user mode stack */
|
||||
_estack = 0x20000400;
|
||||
|
||||
_estack = 0x20001000; /* end of RAM */
|
||||
/* Generate a link error if heap and stack don't fit into RAM */
|
||||
_Min_Heap_Size = 0x400; /* required amount of heap */
|
||||
_Min_Heap_Size = 0x200; /* required amount of heap */
|
||||
_Min_Stack_Size = 0x400; /* required amount of stack */
|
||||
|
||||
/* Specify the memory areas */
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 32K
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 4K
|
||||
MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K
|
||||
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K
|
||||
}
|
||||
|
||||
/* Define output sections */
|
||||
@ -33,10 +38,9 @@ SECTIONS
|
||||
. = ALIGN(4);
|
||||
*(.text) /* .text sections (code) */
|
||||
*(.text*) /* .text* sections (code) */
|
||||
*(.rodata) /* .rodata sections (constants, strings, etc.) */
|
||||
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
|
||||
*(.glue_7) /* glue arm to thumb code */
|
||||
*(.glue_7t) /* glue thumb to arm code */
|
||||
*(.eh_frame)
|
||||
|
||||
KEEP (*(.init))
|
||||
KEEP (*(.fini))
|
||||
@ -45,6 +49,14 @@ SECTIONS
|
||||
_etext = .; /* define a global symbols at end of code */
|
||||
} >FLASH
|
||||
|
||||
/* Constant data goes into FLASH */
|
||||
.rodata :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.rodata) /* .rodata sections (constants, strings, etc.) */
|
||||
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
|
||||
.ARM : {
|
||||
@ -53,8 +65,6 @@ SECTIONS
|
||||
__exidx_end = .;
|
||||
} >FLASH
|
||||
|
||||
.ARM.attributes 0 : { *(.ARM.attributes) }
|
||||
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
@ -71,16 +81,16 @@ SECTIONS
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(.fini_array*))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
KEEP (*(.fini_array*))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
} >FLASH
|
||||
|
||||
/* used by the startup to initialize data */
|
||||
_sidata = .;
|
||||
_sidata = LOADADDR(.data);
|
||||
|
||||
/* Initialized data sections goes into RAM, load LMA copy after code */
|
||||
.data : AT ( _sidata )
|
||||
.data :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sdata = .; /* create a global symbol at data start */
|
||||
@ -89,7 +99,7 @@ SECTIONS
|
||||
|
||||
. = ALIGN(4);
|
||||
_edata = .; /* define a global symbol at data end */
|
||||
} >RAM
|
||||
} >RAM AT> FLASH
|
||||
|
||||
/* Uninitialized data section */
|
||||
. = ALIGN(4);
|
||||
@ -107,27 +117,18 @@ SECTIONS
|
||||
__bss_end__ = _ebss;
|
||||
} >RAM
|
||||
|
||||
PROVIDE ( end = _ebss );
|
||||
PROVIDE ( _end = _ebss );
|
||||
|
||||
/* User_heap_stack section, used to check that there is enough RAM left */
|
||||
._user_heap_stack :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE ( end = . );
|
||||
PROVIDE ( _end = . );
|
||||
. = . + _Min_Heap_Size;
|
||||
. = . + _Min_Stack_Size;
|
||||
. = ALIGN(4);
|
||||
} >RAM
|
||||
|
||||
/* MEMORY_bank1 section, code must be located here explicitly */
|
||||
/* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */
|
||||
.memory_b1_text :
|
||||
{
|
||||
*(.mb1text) /* .mb1text sections (code) */
|
||||
*(.mb1text*) /* .mb1text* sections (code) */
|
||||
*(.mb1rodata) /* read-only data (constants) */
|
||||
*(.mb1rodata*)
|
||||
} >MEMORY_B1
|
||||
|
||||
|
||||
/* Remove information from the standard libraries */
|
||||
/DISCARD/ :
|
||||
@ -136,4 +137,8 @@ SECTIONS
|
||||
libm.a ( * )
|
||||
libgcc.a ( * )
|
||||
}
|
||||
|
||||
.ARM.attributes 0 : { *(.ARM.attributes) }
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
#define MPU_ACCEL_FSR 2 // [g] Set Acceleromenter Full Scale Range: 2g, 4g, 8g, 16g. !! DMP sensor fusion works only with 2g !!
|
||||
#define MPU_I2C_SPEED 400000 // [bit/s] Define I2C speed for communicating with the MPU6050
|
||||
#define DELAY_IN_MAIN_LOOP 1 // [ms] Delay in the main loop
|
||||
// #define PRINTF_FLOAT_SUPPORT // [-] Uncomment this for printf to support float on Serial Debug. It will increase code size! Better to avoid it!
|
||||
/* =============================================================================================== */
|
||||
|
||||
|
||||
|
@ -26,6 +26,10 @@
|
||||
#include "gd32f1x0.h"
|
||||
#include "config.h"
|
||||
|
||||
#if defined(PRINTF_FLOAT_SUPPORT) && defined(SERIAL_DEBUG) && defined(__GNUC__)
|
||||
asm(".global _printf_float"); // this is the magic trick for printf to support float. Warning: It will increase code considerably! Better to avoid!
|
||||
#endif
|
||||
|
||||
/* =========================== Defines General =========================== */
|
||||
// #define _BV(bit) (1 << (bit))
|
||||
// #define ARRAYNUM(arr_nanme) (uint32_t)(sizeof(arr_nanme) / sizeof(*(arr_nanme)))
|
||||
@ -49,6 +53,12 @@
|
||||
#define LED5_GPIO_Port GPIOB
|
||||
#define LED5_Pin GPIO_PIN_4 // BLUE2
|
||||
|
||||
#define LED1_SET (0x01)
|
||||
#define LED2_SET (0x02)
|
||||
#define LED3_SET (0x04)
|
||||
#define LED4_SET (0x08)
|
||||
#define LED5_SET (0x10)
|
||||
|
||||
|
||||
/* =========================== Defines SENSORS =========================== */
|
||||
#define SENSOR1_GPIO_Port GPIOA
|
||||
|
@ -48,7 +48,8 @@ extern volatile int8_t i2c_aux_nRABytes;
|
||||
|
||||
/* general functions */
|
||||
void consoleLog(char *message);
|
||||
void introDemoLED(uint32_t tDelay);
|
||||
void toggle_led(uint32_t gpio_periph, uint32_t pin);
|
||||
void intro_demo_led(uint32_t tDelay);
|
||||
|
||||
/* i2c write/read functions */
|
||||
int8_t i2c_writeBytes(uint8_t slaveAddr, uint8_t regAddr, uint8_t length, uint8_t *data);
|
||||
|
@ -29,7 +29,7 @@
|
||||
<CLKADS>8000000</CLKADS>
|
||||
<OPTTT>
|
||||
<gFlags>1</gFlags>
|
||||
<BeepAtEnd>1</BeepAtEnd>
|
||||
<BeepAtEnd>0</BeepAtEnd>
|
||||
<RunSim>1</RunSim>
|
||||
<RunTarget>0</RunTarget>
|
||||
<RunAbUc>0</RunAbUc>
|
||||
@ -115,6 +115,11 @@
|
||||
<pMon>STLink\ST-LINKIII-KEIL_SWO.dll</pMon>
|
||||
</DebugOpt>
|
||||
<TargetDriverDllRegistry>
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
<Key>ST-LINKIII-KEIL_SWO</Key>
|
||||
<Name>-U -O207 -S0 -C0 -A0 -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO15 -FD20000000 -FC800 -FN1 -FF0GD32F1x0_32 -FS08000000 -FL08000</Name>
|
||||
</SetRegEntry>
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
<Key>UL2CM3</Key>
|
||||
|
@ -77,9 +77,9 @@
|
||||
<nStopB2X>0</nStopB2X>
|
||||
</BeforeMake>
|
||||
<AfterMake>
|
||||
<RunUserProg1>0</RunUserProg1>
|
||||
<RunUserProg1>1</RunUserProg1>
|
||||
<RunUserProg2>0</RunUserProg2>
|
||||
<UserProg1Name></UserProg1Name>
|
||||
<UserProg1Name>$K\ARM\ARMCC\bin\fromelf.exe --bin --output=.\Objects\@L.bin !L</UserProg1Name>
|
||||
<UserProg2Name></UserProg2Name>
|
||||
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
|
||||
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
|
||||
|
2
Makefile
2
Makefile
@ -150,7 +150,7 @@ CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"
|
||||
# LDFLAGS
|
||||
#######################################
|
||||
# link script
|
||||
LDSCRIPT = GD32F130C6_FLASH.ld
|
||||
LDSCRIPT = GD32F130C6T_FLASH.ld
|
||||
|
||||
# libraries
|
||||
LIBS = -lc -lm -lnosys
|
||||
|
30
README.md
30
README.md
@ -14,6 +14,9 @@ This repository implements the firmware for the hoveboard sideboards. The hovebo
|
||||
The original sideboard hardware supports one 4-pin cable that originally was connected to the hoveboard mainboard. It breaks out GND, 12/15V and USART. Additionally, two ports are used to connect to the LED boards. On the back of the board, two Photo Interrupter Optical Switches can be found, originally used to detect if a human is standing on the hoverboard.
|
||||

|
||||
|
||||
The LED boards consist of colored LEDs (blue, red, green, orange) used for design and to inform the user about the current hoverboard state.
|
||||

|
||||
|
||||
The heart of the sideboard is a [GD32F130C6T6](/docs/GD32F130xx-Datasheet_Rev3.3.pdf) with the pinout shown in the follwing figure:
|
||||

|
||||
|
||||
@ -40,13 +43,34 @@ If you have never flashed your sideboard before, the MCU is probably locked. To
|
||||
|
||||
To build and flash choose one of the following methods:
|
||||
|
||||
### Method 1: Using Keil uVision (recommended)
|
||||
### Method 1: Using PlatformIO
|
||||
|
||||
Because this board is not yet supported by [PlatformIO](https://platformio.org/), we have to make two extra steps. These steps can be skipped once the board is supported (see [this thread](https://community.platformio.org/t/build-gd32-project-with-platformio/11944)).
|
||||
|
||||
- go to your PlatformIO home folder (Windows: `C:\Users\<user>\.platformio`, Unix/Max: `/home/<user>/.platformio`). Then go into `packages`. If the folder `framework-spl` exists, delete it.
|
||||
|
||||
- unpack the `framework-spl.zip` in the `packages` folder so that the directory structure is now:
|
||||
```
|
||||
packages/
|
||||
| - framework-spl/
|
||||
| |-- gd32/
|
||||
| |-- platformio/
|
||||
| |-- stm32/
|
||||
| |-- package.json
|
||||
```
|
||||
(This folder contains the `GD32F1x0_Firmware_Library_v3.1.0` files)
|
||||
|
||||
- open the project folder in the IDE of choice (vscode or Atom)
|
||||
- press the 'PlatformIO:Build' or the 'PlatformIO:Upload' button (bottom left in vscode).
|
||||
|
||||
### Method 2: Using Keil uVision
|
||||
|
||||
- in [Keil uVision](https://www.keil.com/download/product/), open the [sideboard-hack.uvproj](/MDK-ARM/)
|
||||
- if you are asked to install missing package, click `Yes`
|
||||
- click Build Target (or press F7) to build the firmware
|
||||
- click Load Code (or press F8) to flash the firmware.
|
||||
|
||||
### Method 2: Using Ubuntu
|
||||
### Method 3: Using Ubuntu
|
||||
|
||||
- prerequisites: install [ST-Flash utility](https://github.com/texane/stlink).
|
||||
|
||||
@ -59,8 +83,6 @@ make
|
||||
make flash
|
||||
```
|
||||
|
||||
*Note: If someone finds a way to build and flash the GD32 MCU via [Platformio](https://platformio.org/) let me know.*
|
||||
|
||||
|
||||
---
|
||||
## Example Variants
|
||||
|
24
Src/i2c_it.c
24
Src/i2c_it.c
@ -24,6 +24,7 @@
|
||||
#include "systick.h"
|
||||
#include "config.h"
|
||||
|
||||
|
||||
void I2C0_EventIRQ_Handler(void)
|
||||
{
|
||||
uint16_t k;
|
||||
@ -52,10 +53,18 @@ void I2C0_EventIRQ_Handler(void)
|
||||
if (i2c_nDABytes > 0) {
|
||||
i2c_data_transmit(I2C0, *i2c_txbuffer++); // the master sends a data byte
|
||||
i2c_nDABytes--;
|
||||
for(k=0; k<500; k++); // make some clock cycles delay (otherwise DMP writing will fail!! Reason unknown yet.. could be that writing to MPU6050 memory takes a bit more time)
|
||||
if (0 == i2c_nDABytes) {
|
||||
i2c_status = 0; // 0 = Success
|
||||
}
|
||||
for(k=0; k<500; k++) {
|
||||
#ifdef __GNUC__
|
||||
asm volatile ("nop"); // unoptimizable NOP loop, 500 times to make some clock cycles delay (otherwise DMP writing will fail!! Reason unknown yet.. could be that writing to MPU6050 memory takes a bit more time)
|
||||
#else
|
||||
__asm volatile ("nop");
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
i2c_stop_on_bus(I2C0); // the master sends a stop condition to I2C bus
|
||||
i2c_status = 0; // 0 = Success
|
||||
i2c_interrupt_disable(I2C0, I2C_INT_ERR | I2C_INT_BUF | I2C_INT_EV); // disable the I2C0 interrupt
|
||||
}
|
||||
}
|
||||
@ -209,10 +218,17 @@ void I2C1_EventIRQ_Handler(void)
|
||||
if (i2c_aux_nDABytes > 0) {
|
||||
i2c_data_transmit(I2C1, *i2c_aux_txbuffer++); // the master sends a data byte
|
||||
i2c_aux_nDABytes--;
|
||||
for(k=0; k<500; k++); // make some clock cycles delay (otherwise DMP writing will fail!! Reason unknown yet.. could be that writing to MPU6050 memory takes a bit more time)
|
||||
for(k=0; k<500; k++);
|
||||
if (0 == i2c_aux_nDABytes) {
|
||||
i2c_aux_status = 0; // 0 = Success
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
asm volatile ("nop"); // unoptimizable NOP loop, 500 times to make some clock cycles delay (otherwise DMP writing will fail!! Reason unknown yet.. could be that writing to MPU6050 memory takes a bit more time)
|
||||
#else
|
||||
__asm volatile ("nop");
|
||||
#endif
|
||||
} else {
|
||||
i2c_stop_on_bus(I2C1); // the master sends a stop condition to I2C bus
|
||||
i2c_aux_status = 0; // 0 = Success
|
||||
i2c_interrupt_disable(I2C1, I2C_INT_ERR | I2C_INT_BUF | I2C_INT_EV); // disable the I2C0 interrupt
|
||||
}
|
||||
}
|
||||
|
66
Src/main.c
66
Src/main.c
@ -52,7 +52,8 @@ typedef struct{
|
||||
int16_t speedL_meas;
|
||||
int16_t batVoltage;
|
||||
int16_t boardTemp;
|
||||
int16_t checksum;
|
||||
uint16_t cmdLed;
|
||||
uint16_t checksum;
|
||||
} SerialFeedback;
|
||||
SerialFeedback Feedback;
|
||||
SerialFeedback NewFeedback;
|
||||
@ -65,7 +66,8 @@ extern MPU_Data mpu; // holds the MPU-6050 data
|
||||
ErrStatus mpuStatus = SUCCESS; // holds the MPU-6050 status: SUCCESS or ERROR
|
||||
|
||||
uint8_t userCommand; // holds the user command input
|
||||
uint8_t sensor1, sensor2; // holds the sensor1 and sensor 2 values
|
||||
FlagStatus sensor1, sensor2; // holds the sensor1 and sensor 2 values
|
||||
FlagStatus sensor1_read, sensor2_read; // holds the instantaneous Read for sensor1 and sensor 2
|
||||
|
||||
static uint32_t main_loop_counter; // main loop counter to perform task squeduling inside main()
|
||||
|
||||
@ -85,23 +87,32 @@ int main(void)
|
||||
usart_Rx_DMA_config(USART_MAIN, (uint8_t *)&NewFeedback, sizeof(NewFeedback));
|
||||
#endif
|
||||
|
||||
introDemoLED(100); // Short LEDs intro demo with 100 ms delay. This also gives some time for the MPU-6050 to initialize.
|
||||
intro_demo_led(100); // Short LEDs intro demo with 100 ms delay. This also gives some time for the MPU-6050 to power-up.
|
||||
if(mpu_config()) { // IMU MPU-6050 config
|
||||
mpuStatus = ERROR;
|
||||
gpio_bit_set(LED1_GPIO_Port, LED1_Pin); // Turn on RED LED
|
||||
}
|
||||
else {
|
||||
gpio_bit_set(LED2_GPIO_Port, LED2_Pin); // Turn on GREEN LED
|
||||
}
|
||||
mpu_handle_input('h'); // Print the User Help commands to serial
|
||||
|
||||
while(1){
|
||||
while(1) {
|
||||
|
||||
delay_1ms(DELAY_IN_MAIN_LOOP);
|
||||
|
||||
// ==================================== LEDs Handling ====================================
|
||||
// gpio_bit_write(LED4_GPIO_Port, LED4_Pin, (bit_status)(1-gpio_input_bit_get(LED4_GPIO_Port, LED4_Pin))); // Toggle BLUE1 LED
|
||||
if (SUCCESS == mpuStatus) {
|
||||
gpio_bit_set(LED2_GPIO_Port, LED2_Pin); // Turn on GREEN LED
|
||||
} else {
|
||||
gpio_bit_set(LED1_GPIO_Port, LED1_Pin); // Turn on RED LED
|
||||
// toggle_led(LED4_GPIO_Port, LED4_Pin); // Toggle BLUE1 LED
|
||||
#ifdef SERIAL_FEEDBACK
|
||||
if (!timeoutFlagSerial) {
|
||||
if (Feedback.cmdLed & LED1_SET) { gpio_bit_set(LED1_GPIO_Port, LED1_Pin); } else { gpio_bit_reset(LED1_GPIO_Port, LED1_Pin); }
|
||||
if (Feedback.cmdLed & LED2_SET) { gpio_bit_set(LED2_GPIO_Port, LED2_Pin); } else { gpio_bit_reset(LED2_GPIO_Port, LED2_Pin); }
|
||||
if (Feedback.cmdLed & LED3_SET) { gpio_bit_set(LED3_GPIO_Port, LED3_Pin); } else { gpio_bit_reset(LED3_GPIO_Port, LED3_Pin); }
|
||||
if (Feedback.cmdLed & LED4_SET) { gpio_bit_set(LED4_GPIO_Port, LED4_Pin); } else { gpio_bit_reset(LED4_GPIO_Port, LED4_Pin); }
|
||||
if (Feedback.cmdLed & LED5_SET) { gpio_bit_set(LED5_GPIO_Port, LED5_Pin); } else { gpio_bit_reset(LED5_GPIO_Port, LED5_Pin); }
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// ==================================== USER Handling ====================================
|
||||
#ifdef SERIAL_DEBUG
|
||||
@ -122,36 +133,43 @@ int main(void)
|
||||
mpu_get_data();
|
||||
}
|
||||
// Print MPU data to Console
|
||||
if (main_loop_counter % 50 == 0 && SUCCESS == mpuStatus) {
|
||||
if (main_loop_counter % 50 == 0) {
|
||||
mpu_print_to_console();
|
||||
}
|
||||
|
||||
|
||||
// ==================================== SENSORS Handling ====================================
|
||||
sensor1_read = gpio_input_bit_get(SENSOR1_GPIO_Port, SENSOR1_Pin);
|
||||
sensor2_read = gpio_input_bit_get(SENSOR2_GPIO_Port, SENSOR2_Pin);
|
||||
|
||||
// SENSOR1
|
||||
if (gpio_input_bit_get(SENSOR1_GPIO_Port, SENSOR1_Pin)) {
|
||||
sensor1 = 1;
|
||||
// Sensor ACTIVE: Do something here
|
||||
if (sensor1 == RESET && sensor1_read == SET) {
|
||||
sensor1 = SET;
|
||||
// Sensor ACTIVE: Do something here (one time task on activation)
|
||||
gpio_bit_set(LED4_GPIO_Port, LED4_Pin);
|
||||
consoleLog("-- SENSOR 1 Active --\n");
|
||||
delay_1ms(50);
|
||||
} else {
|
||||
sensor1 = 0;
|
||||
} else if(sensor1 == SET && sensor1_read == RESET) {
|
||||
sensor1 = RESET;
|
||||
gpio_bit_reset(LED4_GPIO_Port, LED4_Pin);
|
||||
}
|
||||
|
||||
// SENSOR2
|
||||
if (gpio_input_bit_get(SENSOR2_GPIO_Port, SENSOR2_Pin)) {
|
||||
sensor2 = 1;
|
||||
// Sensor ACTIVE: Do something here
|
||||
if (sensor2 == RESET && sensor2_read == SET) {
|
||||
sensor2 = SET;
|
||||
// Sensor ACTIVE: Do something here (one time task on activation)
|
||||
gpio_bit_set(LED5_GPIO_Port, LED5_Pin);
|
||||
consoleLog("-- SENSOR 2 Active --\n");
|
||||
delay_1ms(50);
|
||||
} else {
|
||||
sensor2 = 0;
|
||||
} else if (sensor2 == SET && sensor2_read == RESET) {
|
||||
sensor2 = RESET;
|
||||
gpio_bit_reset(LED5_GPIO_Port, LED5_Pin);
|
||||
}
|
||||
|
||||
if (sensor1 == SET) {
|
||||
// Sensor ACTIVE: Do something here (continuous task)
|
||||
}
|
||||
if (sensor2 == SET) {
|
||||
// Sensor ACTIVE: Do something here (continuous task)
|
||||
}
|
||||
|
||||
|
||||
// ==================================== SERIAL Tx/Rx Handling ====================================
|
||||
#ifdef SERIAL_CONTROL
|
||||
@ -175,7 +193,7 @@ int main(void)
|
||||
#ifdef SERIAL_FEEDBACK
|
||||
uint16_t checksum;
|
||||
checksum = (uint16_t)(NewFeedback.start ^ NewFeedback.cmd1 ^ NewFeedback.cmd2 ^ NewFeedback.speedR ^ NewFeedback.speedL
|
||||
^ NewFeedback.speedR_meas ^ NewFeedback.speedL_meas ^ NewFeedback.batVoltage ^ NewFeedback.boardTemp);
|
||||
^ NewFeedback.speedR_meas ^ NewFeedback.speedL_meas ^ NewFeedback.batVoltage ^ NewFeedback.boardTemp ^ NewFeedback.cmdLed);
|
||||
if (NewFeedback.start == SERIAL_START_FRAME && NewFeedback.checksum == checksum) {
|
||||
if (timeoutFlagSerial) { // Check for previous timeout flag
|
||||
if (timeoutCntSerial-- <= 0) // Timeout de-qualification
|
||||
|
@ -2183,17 +2183,17 @@ static int accel_6500_self_test(long *bias_regular, long *bias_st, int debug)
|
||||
for (i = 0; i < 3; i++) {
|
||||
st_shift_cust[i] = bias_st[i] - bias_regular[i];
|
||||
if(debug) {
|
||||
log_i("Bias_Shift=%7.4f, Bias_Reg=%7.4f, Bias_HWST=%7.4f\r\n",
|
||||
st_shift_cust[i]/1.f, bias_regular[i]/1.f,
|
||||
bias_st[i]/1.f);
|
||||
log_i("OTP value: %7.4f\r\n", ct_shift_prod[i]/1.f);
|
||||
log_i("Bias_Shift=%ld, Bias_Reg=%ld, Bias_HWST=%ld\r\n",
|
||||
(long)st_shift_cust[i], bias_regular[i],
|
||||
bias_st[i]);
|
||||
log_i("OTP value: %ld\r\n", (long)ct_shift_prod[i]);
|
||||
}
|
||||
|
||||
st_shift_ratio[i] = st_shift_cust[i] / ct_shift_prod[i] - 1.f;
|
||||
|
||||
if(debug)
|
||||
log_i("ratio=%7.4f, threshold=%7.4f\r\n", st_shift_ratio[i]/1.f,
|
||||
test.max_accel_var/1.f);
|
||||
log_i("ratio=%ld, threshold=%ld\r\n", (long)st_shift_ratio[i],
|
||||
(long)test.max_accel_var);
|
||||
|
||||
if (fabs(st_shift_ratio[i]) > test.max_accel_var) {
|
||||
if(debug)
|
||||
@ -2209,15 +2209,15 @@ static int accel_6500_self_test(long *bias_regular, long *bias_st, int debug)
|
||||
|
||||
if(debug) {
|
||||
log_i("ACCEL:CRITERIA B\r\n");
|
||||
log_i("Min MG: %7.4f\r\n", accel_st_al_min/1.f);
|
||||
log_i("Max MG: %7.4f\r\n", accel_st_al_max/1.f);
|
||||
log_i("Min MG: %ld\r\n", (long)accel_st_al_min);
|
||||
log_i("Max MG: %ld\r\n", (long)accel_st_al_max);
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
st_shift_cust[i] = bias_st[i] - bias_regular[i];
|
||||
|
||||
if(debug)
|
||||
log_i("Bias_shift=%7.4f, st=%7.4f, reg=%7.4f\n", st_shift_cust[i]/1.f, bias_st[i]/1.f, bias_regular[i]/1.f);
|
||||
log_i("Bias_shift=%ld, st=%ld, reg=%ld\n", (long)st_shift_cust[i], bias_st[i], bias_regular[i]);
|
||||
if(st_shift_cust[i] < accel_st_al_min || st_shift_cust[i] > accel_st_al_max) {
|
||||
if(debug)
|
||||
log_i("Accel FAIL axis:%d <= 225mg or >= 675mg\n", i);
|
||||
@ -2230,7 +2230,7 @@ static int accel_6500_self_test(long *bias_regular, long *bias_st, int debug)
|
||||
/* Self Test Pass/Fail Criteria C */
|
||||
accel_offset_max = test.max_g_offset * 65536.f;
|
||||
if(debug)
|
||||
log_i("Accel:CRITERIA C: bias less than %7.4f\n", accel_offset_max/1.f);
|
||||
log_i("Accel:CRITERIA C: bias less than %ld\n", (long)accel_offset_max);
|
||||
for (i = 0; i < 3; i++) {
|
||||
if(fabs(bias_regular[i]) > accel_offset_max) {
|
||||
if(debug)
|
||||
@ -2279,17 +2279,17 @@ static int gyro_6500_self_test(long *bias_regular, long *bias_st, int debug)
|
||||
st_shift_cust[i] = bias_st[i] - bias_regular[i];
|
||||
|
||||
if(debug) {
|
||||
log_i("Bias_Shift=%7.4f, Bias_Reg=%7.4f, Bias_HWST=%7.4f\r\n",
|
||||
st_shift_cust[i]/1.f, bias_regular[i]/1.f,
|
||||
bias_st[i]/1.f);
|
||||
log_i("OTP value: %7.4f\r\n", ct_shift_prod[i]/1.f);
|
||||
log_i("Bias_Shift=%ld, Bias_Reg=%ld, Bias_HWST=%ld\r\n",
|
||||
(long)st_shift_cust[i], bias_regular[i],
|
||||
bias_st[i]);
|
||||
log_i("OTP value: %ld\r\n", (long)ct_shift_prod[i]);
|
||||
}
|
||||
|
||||
st_shift_ratio[i] = st_shift_cust[i] / ct_shift_prod[i];
|
||||
|
||||
if(debug)
|
||||
log_i("ratio=%7.4f, threshold=%7.4f\r\n", st_shift_ratio[i]/1.f,
|
||||
test.max_gyro_var/1.f);
|
||||
log_i("ratio=%ld, threshold=%ld\r\n", (long)st_shift_ratio[i],
|
||||
(long)test.max_gyro_var);
|
||||
|
||||
if (fabs(st_shift_ratio[i]) < test.max_gyro_var) {
|
||||
if(debug)
|
||||
@ -2304,14 +2304,14 @@ static int gyro_6500_self_test(long *bias_regular, long *bias_st, int debug)
|
||||
|
||||
if(debug) {
|
||||
log_i("GYRO:CRITERIA B\r\n");
|
||||
log_i("Max DPS: %7.4f\r\n", gyro_st_al_max/1.f);
|
||||
log_i("Max DPS: %ld\r\n", (long)gyro_st_al_max);
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
st_shift_cust[i] = bias_st[i] - bias_regular[i];
|
||||
|
||||
if(debug)
|
||||
log_i("Bias_shift=%7.4f, st=%7.4f, reg=%7.4f\n", st_shift_cust[i]/1.f, bias_st[i]/1.f, bias_regular[i]/1.f);
|
||||
log_i("Bias_shift=%ld, st=%ld, reg=%ld\n", (long)st_shift_cust[i], bias_st[i], bias_regular[i]);
|
||||
if(st_shift_cust[i] < gyro_st_al_max) {
|
||||
if(debug)
|
||||
log_i("GYRO FAIL axis:%d greater than 60dps\n", i);
|
||||
@ -2324,7 +2324,7 @@ static int gyro_6500_self_test(long *bias_regular, long *bias_st, int debug)
|
||||
/* Self Test Pass/Fail Criteria C */
|
||||
gyro_offset_max = test.min_dps * 65536.f;
|
||||
if(debug)
|
||||
log_i("Gyro:CRITERIA C: bias less than %7.4f\n", gyro_offset_max/1.f);
|
||||
log_i("Gyro:CRITERIA C: bias less than %ld\n", (long)gyro_offset_max);
|
||||
for (i = 0; i < 3; i++) {
|
||||
if(fabs(bias_regular[i]) > gyro_offset_max) {
|
||||
if(debug)
|
||||
@ -2456,8 +2456,8 @@ static int get_st_6500_biases(long *gyro, long *accel, unsigned char hw_test, in
|
||||
|
||||
|
||||
if(debug) {
|
||||
log_i("Accel offset data HWST bit=%d: %7.4f %7.4f %7.4f\r\n", hw_test, accel[0]/65536.f, accel[1]/65536.f, accel[2]/65536.f);
|
||||
log_i("Gyro offset data HWST bit=%d: %7.4f %7.4f %7.4f\r\n", hw_test, gyro[0]/65536.f, gyro[1]/65536.f, gyro[2]/65536.f);
|
||||
log_i("Accel offset data HWST bit=%d: %ld %ld %ld\r\n", hw_test, accel[0], accel[1], accel[2]);
|
||||
log_i("Gyro offset data HWST bit=%d: %ld %ld %ld\r\n", hw_test, gyro[0], gyro[1], gyro[2]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -3229,14 +3229,14 @@ void mpu_start_self_test(void)
|
||||
if (result == 0x7) {
|
||||
#ifdef SERIAL_DEBUG
|
||||
consoleLog("Passed!\n");
|
||||
log_i("accel: %7.4f %7.4f %7.4f\n",
|
||||
accel[0]/65536.f,
|
||||
accel[1]/65536.f,
|
||||
accel[2]/65536.f);
|
||||
log_i("gyro: %7.4f %7.4f %7.4f\n",
|
||||
gyro[0]/65536.f,
|
||||
gyro[1]/65536.f,
|
||||
gyro[2]/65536.f);
|
||||
log_i("accel: %ld %ld %ld\n",
|
||||
accel[0],
|
||||
accel[1],
|
||||
accel[2]);
|
||||
log_i("gyro: %ld %ld %ld\n",
|
||||
gyro[0],
|
||||
gyro[1],
|
||||
gyro[2]);
|
||||
/* Test passed. We can trust the gyro data here, so now we need to update calibrated data*/
|
||||
#endif
|
||||
|
||||
|
@ -29,15 +29,15 @@
|
||||
extern volatile ErrStatus status;
|
||||
|
||||
// Private variables
|
||||
static rcu_periph_enum USART_CLK[USARTn] = {USART_AUX_CLK,
|
||||
static rcu_periph_enum USART_CLK[USARTn] = { USART_AUX_CLK,
|
||||
USART_MAIN_CLK
|
||||
};
|
||||
|
||||
static uint32_t USART_TX_PIN[USARTn] = {USART_AUX_TX_PIN,
|
||||
static uint32_t USART_TX_PIN[USARTn] = { USART_AUX_TX_PIN,
|
||||
USART_MAIN_TX_PIN
|
||||
};
|
||||
|
||||
static uint32_t USART_RX_PIN[USARTn] = {USART_AUX_RX_PIN,
|
||||
static uint32_t USART_RX_PIN[USARTn] = { USART_AUX_RX_PIN,
|
||||
USART_MAIN_RX_PIN
|
||||
};
|
||||
|
||||
|
27
Src/util.c
27
Src/util.c
@ -61,15 +61,34 @@ void consoleLog(char *message)
|
||||
|
||||
|
||||
/* retarget the C library printf function to the USART */
|
||||
int fputc(int ch, FILE *f)
|
||||
{
|
||||
#ifdef SERIAL_DEBUG
|
||||
#ifdef __GNUC__
|
||||
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
|
||||
#else
|
||||
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
|
||||
#endif
|
||||
PUTCHAR_PROTOTYPE {
|
||||
usart_data_transmit(USART_MAIN, (uint8_t)ch);
|
||||
while(RESET == usart_flag_get(USART_MAIN, USART_FLAG_TBE));
|
||||
return ch;
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
int _write(int file, char *data, int len) {
|
||||
int i;
|
||||
for (i = 0; i < len; i++) { __io_putchar( *data++ );}
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
void toggle_led(uint32_t gpio_periph, uint32_t pin)
|
||||
{
|
||||
GPIO_OCTL(gpio_periph) ^= pin;
|
||||
}
|
||||
|
||||
|
||||
void introDemoLED(uint32_t tDelay)
|
||||
void intro_demo_led(uint32_t tDelay)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
2
add_nanolib.py
Normal file
2
add_nanolib.py
Normal file
@ -0,0 +1,2 @@
|
||||
Import("env")
|
||||
env.Append(LINKFLAGS=["--specs=nano.specs"])
|
40
boards/gd32f130c6.json
Normal file
40
boards/gd32f130c6.json
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"build": {
|
||||
"core": "gd32",
|
||||
"cpu": "cortex-m3",
|
||||
"extra_flags": "-DGD32F1x0 -DGD32F130_150 -D__GD32F130_SUBFAMILY -D__GD32F1x0_FAMILY",
|
||||
"f_cpu": "72000000L",
|
||||
"mcu": "gd32f130c6t6"
|
||||
},
|
||||
"connectivity": [
|
||||
],
|
||||
"debug": {
|
||||
"default_tools": [
|
||||
"stlink"
|
||||
],
|
||||
"jlink_device": "GD32F130C6",
|
||||
"onboard_tools": [
|
||||
"stlink"
|
||||
],
|
||||
"openocd_target": "stm32f1x",
|
||||
"svd_path": "STM32F10x.svd"
|
||||
},
|
||||
"frameworks": [
|
||||
"stm32cube",
|
||||
"spl"
|
||||
],
|
||||
"name": "Generic GD32F130C6T6",
|
||||
"upload": {
|
||||
"maximum_ram_size": 4096,
|
||||
"maximum_size": 32768,
|
||||
"protocol": "stlink",
|
||||
"protocols": [
|
||||
"jlink",
|
||||
"stlink",
|
||||
"blackmagic",
|
||||
"mbed"
|
||||
]
|
||||
},
|
||||
"url": "https://www.gigadevice.com/microcontroller/gd32f130c6t6/",
|
||||
"vendor": "GigaDevices"
|
||||
}
|
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 2.5 MiB |
Binary file not shown.
Before Width: | Height: | Size: 2.9 MiB |
BIN
docs/pictures/ledboard_pinout.png
Normal file
BIN
docs/pictures/ledboard_pinout.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 361 KiB |
BIN
framework-spl.zip
Normal file
BIN
framework-spl.zip
Normal file
Binary file not shown.
69
platformio.ini
Normal file
69
platformio.ini
Normal file
@ -0,0 +1,69 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
|
||||
[platformio]
|
||||
include_dir = Inc
|
||||
src_dir = Src
|
||||
|
||||
;=================== VARIANT SELECTION ==========================
|
||||
;default_envs = VARIANT_DEBUG ; DEFAULT Variant
|
||||
;default_envs = VARIANT_HOVERBOARD ; HOVERBOARD Variant
|
||||
;================================================================
|
||||
|
||||
;================================================================
|
||||
|
||||
[env:VARIANT_DEBUG]
|
||||
platform = ststm32
|
||||
board = gd32f130c6
|
||||
debug_tool = stlink
|
||||
upload_protocol = stlink
|
||||
framework = spl
|
||||
extra_scripts = add_nanolib.py ; adds nanolib to reduce printf memory foot print
|
||||
|
||||
|
||||
; Serial Port settings (make sure the COM port is correct)
|
||||
monitor_port = COM5
|
||||
monitor_speed = 38400
|
||||
|
||||
build_flags =
|
||||
-IInc
|
||||
-ISrc
|
||||
-DUSE_STDPERIPH_DRIVER
|
||||
-DGD32F130_150
|
||||
-Wl,-T./GD32F130C6T_FLASH.ld
|
||||
-Wl,-lc
|
||||
-Wl,-lm
|
||||
-g -ggdb
|
||||
-D VARIANT_DEBUG
|
||||
|
||||
;================================================================
|
||||
|
||||
[env:VARIANT_HOVERBOARD]
|
||||
platform = ststm32
|
||||
board = gd32f130c6
|
||||
debug_tool = stlink
|
||||
upload_protocol = stlink
|
||||
framework = spl
|
||||
extra_scripts = add_nanolib.py
|
||||
|
||||
build_flags =
|
||||
-IInc
|
||||
-ISrc
|
||||
-DUSE_STDPERIPH_DRIVER
|
||||
-DGD32F130_150
|
||||
-Wl,-T./GD32F130C6T_FLASH.ld
|
||||
-Wl,-lc
|
||||
-Wl,-lm
|
||||
-g -ggdb
|
||||
-D VARIANT_HOVERBOARD
|
||||
|
||||
;================================================================
|
||||
|
@ -77,7 +77,8 @@ LoopFillZerobss:
|
||||
/* Call the clock system intitialization function.*/
|
||||
bl SystemInit
|
||||
/* Call static constructors */
|
||||
bl __libc_init_array
|
||||
// nope no C++ code today
|
||||
// bl __libc_init_array
|
||||
/* Call the application's entry point.*/
|
||||
bl main
|
||||
bx lr
|
||||
|
Loading…
x
Reference in New Issue
Block a user