Bootloader support, CAN fixes

This commit is contained in:
Benjamin Vedder 2015-05-08 22:53:59 +02:00
parent 5a5ccfb4c3
commit bc7a779632
19 changed files with 340 additions and 76 deletions

View File

@ -118,6 +118,7 @@ CSRC = $(PORTSRC) \
ws2811.c \
led_external.c \
encoder.c \
flash_helper.c \
$(HWSRC) \
$(APPSRC) \
$(NRFSRC)
@ -277,5 +278,3 @@ upload: build/$(PROJECT).bin
debug-start:
openocd -f stm32-bv_openocd.cfg

View File

@ -36,18 +36,25 @@
// Settings
#define CANDx CAND1
#define RX_FRAMES_SIZE 10
// Threads
static WORKING_AREA(cancom_thread_wa, 4096);
static WORKING_AREA(cancom_read_thread_wa, 512);
static WORKING_AREA(cancom_process_thread_wa, 4096);
static WORKING_AREA(cancom_status_thread_wa, 1024);
static msg_t cancom_thread(void *arg);
static msg_t cancom_read_thread(void *arg);
static msg_t cancom_status_thread(void *arg);
static msg_t cancom_process_thread(void *arg);
// Variables
static can_status_msg stat_msgs[CAN_STATUS_MSGS_TO_STORE];
static Mutex can_mtx;
static uint8_t rx_buffer[256];
static uint8_t rx_buffer_last_id;
static CANRxFrame rx_frames[RX_FRAMES_SIZE];
static int rx_frame_read;
static int rx_frame_write;
static Thread *process_tp;
/*
* 500KBaud, automatic wakeup, automatic recover
@ -68,6 +75,9 @@ void comm_can_init(void) {
stat_msgs[i].id = -1;
}
rx_frame_read = 0;
rx_frame_write = 0;
chMtxInit(&can_mtx);
palSetPadMode(GPIOB, 8,
@ -79,27 +89,22 @@ void comm_can_init(void) {
PAL_STM32_OTYPE_PUSHPULL |
PAL_STM32_OSPEED_MID1);
chMtxLock(&can_mtx);
canStart(&CANDx, &cancfg);
chMtxUnlock();
chThdCreateStatic(cancom_thread_wa, sizeof(cancom_thread_wa), NORMALPRIO,
cancom_thread, NULL);
chThdCreateStatic(cancom_read_thread_wa, sizeof(cancom_read_thread_wa), NORMALPRIO + 1,
cancom_read_thread, NULL);
chThdCreateStatic(cancom_status_thread_wa, sizeof(cancom_status_thread_wa), NORMALPRIO,
cancom_status_thread, NULL);
chThdCreateStatic(cancom_process_thread_wa, sizeof(cancom_process_thread_wa), NORMALPRIO,
cancom_process_thread, NULL);
}
static msg_t cancom_thread(void *arg) {
static msg_t cancom_read_thread(void *arg) {
(void)arg;
chRegSetThreadName("CAN");
EventListener el;
CANRxFrame rxmsg;
int32_t ind = 0;
int32_t rxbuf_len;
uint8_t crc_low;
uint8_t crc_high;
bool commands_send;
chEvtRegister(&CANDx.rxfull_event, &el, 0);
@ -108,11 +113,42 @@ static msg_t cancom_thread(void *arg) {
continue;
}
chMtxLock(&can_mtx);
msg_t result = canReceive(&CANDx, CAN_ANY_MAILBOX, &rxmsg, TIME_IMMEDIATE);
chMtxUnlock();
while (result == RDY_OK) {
rx_frames[rx_frame_write++] = rxmsg;
if (rx_frame_write == RX_FRAMES_SIZE) {
rx_frame_write = 0;
}
chEvtSignal(process_tp, (eventmask_t) 1);
result = canReceive(&CANDx, CAN_ANY_MAILBOX, &rxmsg, TIME_IMMEDIATE);
}
}
chEvtUnregister(&CANDx.rxfull_event, &el);
return 0;
}
static msg_t cancom_process_thread(void *arg) {
(void)arg;
chRegSetThreadName("Cancom process");
process_tp = chThdSelf();
int32_t ind = 0;
int32_t rxbuf_len;
uint8_t crc_low;
uint8_t crc_high;
bool commands_send;
for(;;) {
chEvtWaitAny((eventmask_t) 1);
while (rx_frame_read != rx_frame_write) {
CANRxFrame rxmsg = rx_frames[rx_frame_read++];
if (rxmsg.IDE == CAN_IDE_EXT) {
uint8_t id = rxmsg.EID & 0xFF;
CAN_PACKET_ID cmd = rxmsg.EID >> 8;
@ -214,13 +250,12 @@ static msg_t cancom_thread(void *arg) {
}
}
chMtxLock(&can_mtx);
result = canReceive(&CANDx, CAN_ANY_MAILBOX, &rxmsg, TIME_IMMEDIATE);
chMtxUnlock();
if (rx_frame_read == RX_FRAMES_SIZE) {
rx_frame_read = 0;
}
}
}
chEvtUnregister(&CAND1.rxfull_event, &el);
return 0;
}
@ -252,26 +287,17 @@ static msg_t cancom_status_thread(void *arg) {
void comm_can_transmit(uint32_t id, uint8_t *data, uint8_t len) {
#if CAN_ENABLE
CANTxFrame txmsg;
txmsg.IDE = CAN_IDE_EXT;
txmsg.EID = id;
txmsg.RTR = CAN_RTR_DATA;
txmsg.DLC = len;
memcpy(txmsg.data8, data, len);
chMtxLock(&can_mtx);
static CANTxFrame txmsg[10];
static int txmsg_ind = 0;
txmsg[txmsg_ind].IDE = CAN_IDE_EXT;
txmsg[txmsg_ind].EID = id;
txmsg[txmsg_ind].RTR = CAN_RTR_DATA;
txmsg[txmsg_ind].DLC = len;
memcpy(txmsg[txmsg_ind].data8, data, len);
canTransmit(&CAND1, CAN_ANY_MAILBOX, &txmsg[txmsg_ind], MS2ST(50));
txmsg_ind++;
if (txmsg_ind >= 10) {
txmsg_ind = 0;
}
canTransmit(&CANDx, CAN_ANY_MAILBOX, &txmsg, MS2ST(20));
chMtxUnlock();
#else
(void)id;
(void)data;
@ -331,7 +357,7 @@ void comm_can_send_buffer(uint8_t controller_id, uint8_t *data, uint8_t len, boo
send_buffer[ind++] = (uint8_t)(crc >> 8);
send_buffer[ind++] = (uint8_t)(crc & 0xFF);
comm_can_transmit(controller_id | ((uint32_t)CAN_PACKET_PROCESS_RX_BUFFER << 8), send_buffer, 5);
comm_can_transmit(controller_id | ((uint32_t)CAN_PACKET_PROCESS_RX_BUFFER << 8), send_buffer, ind++);
}
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2012-2014 Benjamin Vedder benjamin@vedder.se
Copyright 2012-2015 Benjamin Vedder benjamin@vedder.se
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
@ -37,6 +37,8 @@
#include "timeout.h"
#include "servo_dec.h"
#include "comm_can.h"
#include "flash_helper.h"
#include "utils.h"
#include <math.h>
#include <string.h>
@ -107,6 +109,8 @@ void commands_process_packet(unsigned char *data, unsigned char len) {
bool at_start;
mc_configuration mcconf;
app_configuration appconf;
uint16_t flash_res;
uint32_t new_app_offset;
(void)len;
@ -123,6 +127,31 @@ void commands_process_packet(unsigned char *data, unsigned char len) {
commands_send_packet(send_buffer, ind);
break;
case COMM_JUMP_TO_BOOTLOADER:
utils_jump_to_bootloader();
break;
case COMM_ERASE_NEW_APP:
ind = 0;
flash_res = flash_helper_erase_new_app(buffer_get_uint32(data, &ind));
ind = 0;
send_buffer[ind++] = COMM_ERASE_NEW_APP;
send_buffer[ind++] = flash_res == FLASH_COMPLETE ? 1 : 0;
commands_send_packet(send_buffer, ind);
break;
case COMM_WRITE_NEW_APP_DATA:
ind = 0;
new_app_offset = buffer_get_uint32(data, &ind);
flash_res = flash_helper_write_new_app_data(new_app_offset, data + ind, len - ind);
ind = 0;
send_buffer[ind++] = COMM_WRITE_NEW_APP_DATA;
send_buffer[ind++] = flash_res == FLASH_COMPLETE ? 1 : 0;
commands_send_packet(send_buffer, ind);
break;
case COMM_GET_VALUES:
ind = 0;
send_buffer[ind++] = COMM_GET_VALUES;

View File

@ -25,9 +25,9 @@
#ifndef CONF_GENERAL_H_
#define CONF_GENERAL_H_
// Software version
// Firmware version
#define FW_VERSION_MAJOR 1
#define FW_VERSION_MINOR 0
#define FW_VERSION_MINOR 1
#include "datatypes.h"

View File

@ -257,6 +257,9 @@ typedef struct {
// Communication commands
typedef enum {
COMM_FW_VERSION = 0,
COMM_JUMP_TO_BOOTLOADER,
COMM_ERASE_NEW_APP,
COMM_WRITE_NEW_APP_DATA,
COMM_GET_VALUES,
COMM_SET_DUTY,
COMM_SET_CURRENT,

View File

@ -36,18 +36,18 @@
#define VOLTAGE_RANGE (uint8_t)VoltageRange_3
/* EEPROM start address in Flash */
#define EEPROM_START_ADDRESS ((uint32_t)0x08008000) /* EEPROM emulation start address:
from sector2 : after 16KByte of used
#define EEPROM_START_ADDRESS ((uint32_t)0x08004000) /* EEPROM emulation start address:
from sector1 : after 16KByte of used
Flash memory */
/* Pages 0 and 1 base and end addresses */
#define PAGE0_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + 0x0000))
#define PAGE0_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (PAGE_SIZE - 1)))
#define PAGE0_ID FLASH_Sector_2
#define PAGE0_ID FLASH_Sector_1
#define PAGE1_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + 0x4000))
#define PAGE1_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (2 * PAGE_SIZE - 1)))
#define PAGE1_ID FLASH_Sector_3
#define PAGE1_ID FLASH_Sector_2
/* Used Flash pages for EEPROM emulation */
#define PAGE0 ((uint16_t)0x0000)

130
flash_helper.c Normal file
View File

@ -0,0 +1,130 @@
/*
Copyright 2012-2015 Benjamin Vedder benjamin@vedder.se
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 <http://www.gnu.org/licenses/>.
*/
/*
* flash_helper.c
*
* Created on: 6 maj 2015
* Author: benjamin
*/
#include "flash_helper.h"
#include "ch.h"
#include "hal.h"
#include "stm32f4xx_conf.h"
#include "utils.h"
#include <string.h>
/*
* Defines
*/
#define FLASH_SECTORS 12
#define BOOTLOADER_BASE 11
#define APP_BASE 0
#define NEW_APP_BASE 8
#define NEW_APP_SECTORS 3
// Base address of the Flash sectors
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) // Base @ of Sector 0, 16 Kbytes
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) // Base @ of Sector 1, 16 Kbytes
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) // Base @ of Sector 2, 16 Kbytes
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) // Base @ of Sector 3, 16 Kbytes
#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) // Base @ of Sector 4, 64 Kbytes
#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) // Base @ of Sector 5, 128 Kbytes
#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) // Base @ of Sector 6, 128 Kbytes
#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) // Base @ of Sector 7, 128 Kbytes
#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08080000) // Base @ of Sector 8, 128 Kbytes
#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x080A0000) // Base @ of Sector 9, 128 Kbytes
#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) // Base @ of Sector 10, 128 Kbytes
#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) // Base @ of Sector 11, 128 Kbytes
// Private constants
static const uint32_t flash_addr[FLASH_SECTORS] = {
ADDR_FLASH_SECTOR_0,
ADDR_FLASH_SECTOR_1,
ADDR_FLASH_SECTOR_2,
ADDR_FLASH_SECTOR_3,
ADDR_FLASH_SECTOR_4,
ADDR_FLASH_SECTOR_5,
ADDR_FLASH_SECTOR_6,
ADDR_FLASH_SECTOR_7,
ADDR_FLASH_SECTOR_8,
ADDR_FLASH_SECTOR_9,
ADDR_FLASH_SECTOR_10,
ADDR_FLASH_SECTOR_11
};
static const uint16_t flash_sector[12] = {
FLASH_Sector_0,
FLASH_Sector_1,
FLASH_Sector_2,
FLASH_Sector_3,
FLASH_Sector_4,
FLASH_Sector_5,
FLASH_Sector_6,
FLASH_Sector_7,
FLASH_Sector_8,
FLASH_Sector_9,
FLASH_Sector_10,
FLASH_Sector_11
};
uint16_t flash_helper_erase_new_app(uint32_t new_app_size) {
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR |
FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
new_app_size += flash_addr[NEW_APP_BASE];
utils_sys_lock_cnt();
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, DISABLE);
for (int i = 0;i < NEW_APP_SECTORS;i++) {
if (new_app_size > flash_addr[NEW_APP_BASE + i]) {
uint16_t res = FLASH_EraseSector(flash_sector[NEW_APP_BASE + i], VoltageRange_3);
if (res != FLASH_COMPLETE) {
return res;
}
} else {
break;
}
}
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
utils_sys_unlock_cnt();
return FLASH_COMPLETE;
}
uint16_t flash_helper_write_new_app_data(uint32_t offset, uint8_t *data, uint32_t len) {
FLASH_ClearFlag(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR |
FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
utils_sys_lock_cnt();
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, DISABLE);
for (uint32_t i = 0;i < len;i++) {
uint16_t res = FLASH_ProgramByte(flash_addr[NEW_APP_BASE] + offset + i, data[i]);
if (res != FLASH_COMPLETE) {
return res;
}
}
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
utils_sys_unlock_cnt();
return FLASH_COMPLETE;
}

34
flash_helper.h Normal file
View File

@ -0,0 +1,34 @@
/*
Copyright 2012-2015 Benjamin Vedder benjamin@vedder.se
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 <http://www.gnu.org/licenses/>.
*/
/*
* flash_helper.h
*
* Created on: 6 maj 2015
* Author: benjamin
*/
#ifndef FLASH_HELPER_H_
#define FLASH_HELPER_H_
#include "conf_general.h"
// Functions
uint16_t flash_helper_erase_new_app(uint32_t new_app_size);
uint16_t flash_helper_write_new_app_data(uint32_t offset, uint8_t *data, uint32_t len);
#endif /* FLASH_HELPER_H_ */

View File

@ -32,10 +32,10 @@
#define DCCAL_OFF() palClearPad(GPIOB, 12)
#define IS_DRV_FAULT() (!palReadPad(GPIOC, 12))
#define LED1_ON() palSetPad(GPIOC, 4)
#define LED1_OFF() palClearPad(GPIOC, 4)
#define LED2_ON() palSetPad(GPIOA, 7)
#define LED2_OFF() palClearPad(GPIOA, 7)
#define LED_GREEN_ON() palSetPad(GPIOC, 4)
#define LED_GREEN_OFF() palClearPad(GPIOC, 4)
#define LED_RED_ON() palSetPad(GPIOA, 7)
#define LED_RED_OFF() palClearPad(GPIOA, 7)
/*
* ADC Vector

View File

@ -32,10 +32,10 @@
#define DCCAL_OFF() palClearPad(GPIOB, 12)
#define IS_DRV_FAULT() (!palReadPad(GPIOC, 12))
#define LED1_ON() palSetPad(GPIOC, 4)
#define LED1_OFF() palClearPad(GPIOC, 4)
#define LED2_ON() palSetPad(GPIOA, 7)
#define LED2_OFF() palClearPad(GPIOA, 7)
#define LED_GREEN_ON() palSetPad(GPIOC, 4)
#define LED_GREEN_OFF() palClearPad(GPIOC, 4)
#define LED_RED_ON() palSetPad(GPIOA, 7)
#define LED_RED_OFF() palClearPad(GPIOA, 7)
/*
* ADC Vector

View File

@ -32,10 +32,10 @@
#define DCCAL_OFF() palClearPad(GPIOB, 12)
#define IS_DRV_FAULT() (!palReadPad(GPIOC, 12))
#define LED1_ON() palSetPad(GPIOC, 4)
#define LED1_OFF() palClearPad(GPIOC, 4)
#define LED2_ON() palSetPad(GPIOA, 7)
#define LED2_OFF() palClearPad(GPIOA, 7)
#define LED_GREEN_ON() palSetPad(GPIOC, 4)
#define LED_GREEN_OFF() palClearPad(GPIOC, 4)
#define LED_RED_ON() palSetPad(GPIOA, 7)
#define LED_RED_OFF() palClearPad(GPIOA, 7)
/*
* ADC Vector

View File

@ -32,10 +32,10 @@
#define DCCAL_OFF() palClearPad(GPIOB, 12)
#define IS_DRV_FAULT() (!palReadPad(GPIOC, 12))
#define LED1_ON() palSetPad(GPIOC, 4)
#define LED1_OFF() palClearPad(GPIOC, 4)
#define LED2_ON() palSetPad(GPIOA, 7)
#define LED2_OFF() palClearPad(GPIOA, 7)
#define LED_GREEN_ON() palSetPad(GPIOC, 4)
#define LED_GREEN_OFF() palClearPad(GPIOC, 4)
#define LED_RED_ON() palSetPad(GPIOA, 7)
#define LED_RED_OFF() palClearPad(GPIOA, 7)
/*
* ADC Vector

View File

@ -32,10 +32,10 @@
#define DCCAL_OFF() palClearPad(GPIOB, 12)
#define IS_DRV_FAULT() (!palReadPad(GPIOC, 12))
#define LED1_ON() palSetPad(GPIOB, 6)
#define LED1_OFF() palClearPad(GPIOB, 6)
#define LED2_ON() palSetPad(GPIOB, 7)
#define LED2_OFF() palClearPad(GPIOB, 7)
#define LED_GREEN_ON() palSetPad(GPIOB, 6)
#define LED_GREEN_OFF() palClearPad(GPIOB, 6)
#define LED_RED_ON() palSetPad(GPIOB, 7)
#define LED_RED_OFF() palClearPad(GPIOB, 7)
/*
* ADC Vector

View File

@ -32,10 +32,10 @@
#define DCCAL_OFF() palClearPad(GPIOB, 12)
#define IS_DRV_FAULT() (!palReadPad(GPIOC, 12))
#define LED1_ON() palSetPad(GPIOC, 4)
#define LED1_OFF() palClearPad(GPIOC, 4)
#define LED2_ON() palSetPad(GPIOA, 7)
#define LED2_OFF() palClearPad(GPIOA, 7)
#define LED_GREEN_ON() palSetPad(GPIOC, 4)
#define LED_GREEN_OFF() palClearPad(GPIOC, 4)
#define LED_RED_ON() palSetPad(GPIOA, 7)
#define LED_RED_OFF() palClearPad(GPIOA, 7)
/*
* ADC Vector

View File

@ -27,7 +27,7 @@ __process_stack_size__ = 0x0800;
MEMORY
{
flash : org = 0x08000000, len = 16k
flash2 : org = 0x08020000, len = 896k
flash2 : org = 0x0800C000, len = 480k
ram : org = 0x20000000, len = 128k
ccmram : org = 0x10000000, len = 64k
}

View File

@ -91,14 +91,14 @@ void ledpwm_update_pwm(void) {
}
if (cnt >= led_values[0]) {
LED1_OFF();
LED_GREEN_OFF();
} else {
LED1_ON();
LED_GREEN_ON();
}
if (cnt >= led_values[1]) {
LED2_OFF();
LED_RED_OFF();
} else {
LED2_ON();
LED_RED_ON();
}
}

2
main.c
View File

@ -340,6 +340,6 @@ int main(void) {
chThdCreateStatic(timer_thread_wa, sizeof(timer_thread_wa), NORMALPRIO, timer_thread, NULL);
for(;;) {
chThdSleepMilliseconds(100);
chThdSleepMilliseconds(5000);
}
}

42
utils.c
View File

@ -24,6 +24,8 @@
#include "utils.h"
#include "ch.h"
#include "hal.h"
#include "mcpwm.h"
#include <math.h>
// Private variables
@ -150,4 +152,44 @@ void utils_sys_unlock_cnt(void) {
}
}
/**
* Stop the system and jump to the bootloader.
*/
void utils_jump_to_bootloader(void) {
typedef void (*pFunction)(void);
mcpwm_release_motor();
usbDisconnectBus(&USBD1);
usbStop(&USBD1);
// Disable watchdog
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, DISABLE);
chSysDisable();
pFunction jump_to_bootloader;
// Variable that will be loaded with the start address of the application
vu32* jump_address;
const vu32* bootloader_address = (vu32*)0x080E0000;
// Get jump address from application vector table
jump_address = (vu32*) bootloader_address[1];
// Load this address into function pointer
jump_to_bootloader = (pFunction) jump_address;
// Clear pending interrupts
SCB_ICSR = ICSR_PENDSVCLR;
// Disable all interrupts
for(int i = 0;i < 8;i++) {
NVIC->ICER[i] = NVIC->IABR[i];
}
// Set stack pointer
__set_MSP((u32) (bootloader_address[0]));
// Jump to the bootloader
jump_to_bootloader();
}

View File

@ -34,6 +34,7 @@ void utils_deadband(float *value, float tres, float max);
float utils_angle_difference(float angle1, float angle2);
void utils_sys_lock_cnt(void);
void utils_sys_unlock_cnt(void);
void utils_jump_to_bootloader(void);
// Return the sign of the argument. -1 if negative, 1 if zero or positive.
#define SIGN(x) ((x<0)?-1:1)