Commit a8191799 authored by Alexey Hohlov's avatar Alexey Hohlov

First commit. Прошивка для usb-can контроллера для работы по протоколу rhex_proto

parents
BasedOnStyle: LLVM
IndentWidth: 8
UseTab: Always
BreakBeforeBraces: Linux
AllowShortIfStatementsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AlwaysBreakAfterReturnType: AllDefinitions
IndentCaseLabels: false
ColumnLimit: 80
PROJECT(usb_can C)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
ENABLE_LANGUAGE(C ASM)
set(TARGET_TRIPLET arm-none-eabi)
FIND_PACKAGE(CMSIS REQUIRED)
FIND_PACKAGE(STM32HAL COMPONENTS gpio tim uart can dma hcd pcd REQUIRED)
INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR}/src/include
${CMSIS_INCLUDE_DIRS}
${STM32HAL_INCLUDE_DIR}
${RHEX_PROTO_DIR}/include
)
file(GLOB_RECURSE p_headers "include/*.h")
SET(PROJECT_SOURCES
src/main.c
src/init.c
src/system_config.c
src/uart.c
src/can.c
src/usb.c
src/newlib_stubs.c
src/usb/usbd_conf.c
src/usb/usbd_core.c
src/usb/usbd_ctlreq.c
src/usb/usbd_desc.c
src/usb/usb_device.c
src/usb/usbd_ioreq.c
src/usb/usbd_cdc.c
src/usb/stm32f1xx_ll_usb.c
${p_headers}
)
ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${PROJECT_SOURCES} ${CMSIS_SOURCES} ${STM32HAL_SOURCES})
ADD_DEFINITIONS(-D__SOFTFP__)
target_include_directories(${CMAKE_PROJECT_NAME}
PRIVATE src/include)
#target_link_libraries(${CMAKE_PROJECT_NAME}
# c c_nano)
set_property(TARGET ${CMAKE_PROJECT_NAME} PROPERTY C_STANDARD 11)
STM32_SET_TARGET_PROPERTIES(${CMAKE_PROJECT_NAME})
STM32_ADD_HEX_BIN_TARGETS(${CMAKE_PROJECT_NAME})
#include <init.h>
#include <util.h>
#include <can.h>
#define MAX_MESSAGES (32u)
static uint32_t HAL_RCC_CAN1_CLK_ENABLED = 0;
static struct can_packet_t messages[MAX_MESSAGES];
static CAN_TxHeaderTypeDef TxHeader[2];
static uint32_t TxMailbox;
static uint32_t rx_head = 0u;
static uint32_t rx_tail = 0u;
static inline uint32_t
next_idx(uint32_t idx)
{
return (idx + 1u) % MAX_MESSAGES;
}
bool
can_read_msg(struct can_packet_t **msg)
{
bool result = false;
if (rx_head != rx_tail) {
*msg = &messages[rx_head];
rx_head = next_idx(rx_head);
result = true;
}
return result;
}
void
can_send(struct can_packet_t *msg)
{
CAN_HandleTypeDef *can = &hcan1;
if (msg->bus == 1) {
can = &hcan2;
}
union {
can_msg_t *msg;
uint32_t *u32;
} id;
id.msg = &msg->msg_id;
// TxHeader[msg->bus].StdId = msg->msg_id.dest_id;
TxHeader[msg->bus].ExtId = *id.u32;
TxHeader[msg->bus].DLC = msg->len;
if (HAL_CAN_AddTxMessage(can, &TxHeader[msg->bus], msg->data,
&TxMailbox) != HAL_OK) {
/* Transmission request Error */
Error_Handler();
}
}
/* CAN1 init function */
static void
MX_CAN1_Init(void)
{
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 4;
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan1.Init.TimeSeg1 = CAN_BS1_9TQ;
hcan1.Init.TimeSeg2 = CAN_BS2_8TQ;
hcan1.Init.TimeTriggeredMode = DISABLE;
hcan1.Init.AutoBusOff = ENABLE;
hcan1.Init.AutoWakeUp = ENABLE;
hcan1.Init.AutoRetransmission = ENABLE;
hcan1.Init.ReceiveFifoLocked = DISABLE;
hcan1.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan1) != HAL_OK) {
_Error_Handler(__FILE__, __LINE__);
} else {
CAN_FilterTypeDef canFilterConfig;
canFilterConfig.FilterBank = 0;
canFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
canFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
canFilterConfig.FilterIdHigh = 0x0000;
canFilterConfig.FilterIdLow = 0x0000;
canFilterConfig.FilterMaskIdHigh = 0x0000 << 5;
canFilterConfig.FilterMaskIdLow = 0x0000;
canFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
canFilterConfig.FilterActivation = ENABLE;
canFilterConfig.SlaveStartFilterBank = 1;
HAL_CAN_ConfigFilter(&hcan1, &canFilterConfig);
}
if (HAL_CAN_Start(&hcan1) != HAL_OK) {
/* Start Error */
Error_Handler();
}
/* Activate CAN RX notification */
if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) !=
HAL_OK) {
/* Notification Error */
Error_Handler();
}
TxHeader[0].StdId = 0x100;
TxHeader[0].ExtId = 0x01;
TxHeader[0].RTR = CAN_RTR_DATA;
TxHeader[0].IDE = CAN_ID_EXT;
TxHeader[0].DLC = 2;
TxHeader[0].TransmitGlobalTime = DISABLE;
}
/* CAN2 init function */
static void
MX_CAN2_Init(void)
{
hcan2.Instance = CAN2;
hcan2.Init.Prescaler = 4;
hcan2.Init.Mode = CAN_MODE_NORMAL;
hcan2.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan2.Init.TimeSeg1 = CAN_BS1_9TQ;
hcan2.Init.TimeSeg2 = CAN_BS2_8TQ;
hcan2.Init.TimeTriggeredMode = DISABLE;
hcan2.Init.AutoBusOff = ENABLE;
hcan2.Init.AutoWakeUp = ENABLE;
hcan2.Init.AutoRetransmission = ENABLE;
hcan2.Init.ReceiveFifoLocked = DISABLE;
hcan2.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan2) != HAL_OK) {
_Error_Handler(__FILE__, __LINE__);
} else {
CAN_FilterTypeDef canFilterConfig;
// hcan2.Instance = CAN1;
canFilterConfig.FilterBank = 14;
canFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
canFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
canFilterConfig.FilterIdHigh = 0x0000;
canFilterConfig.FilterIdLow = 0x0000;
canFilterConfig.FilterMaskIdHigh = 0x0000 << 5;
canFilterConfig.FilterMaskIdLow = 0x0000;
canFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
canFilterConfig.FilterActivation = ENABLE;
canFilterConfig.SlaveStartFilterBank = 14;
HAL_CAN_ConfigFilter(&hcan2, &canFilterConfig);
}
if (HAL_CAN_Start(&hcan2) != HAL_OK) {
/* Start Error */
Error_Handler();
}
/* Activate CAN RX notification */
if (HAL_CAN_ActivateNotification(&hcan2, CAN_IT_RX_FIFO0_MSG_PENDING) !=
HAL_OK) {
/* Notification Error */
Error_Handler();
}
TxHeader[1].StdId = 0x100;
TxHeader[1].ExtId = 0x01;
TxHeader[1].RTR = CAN_RTR_DATA;
TxHeader[1].IDE = CAN_ID_EXT;
TxHeader[1].DLC = 2;
TxHeader[1].TransmitGlobalTime = DISABLE;
}
void
HAL_CAN_MspInit(CAN_HandleTypeDef *hcan)
{
GPIO_InitTypeDef GPIO_InitStruct;
if (hcan->Instance == CAN1) {
/* Peripheral clock enable */
HAL_RCC_CAN1_CLK_ENABLED++;
if (HAL_RCC_CAN1_CLK_ENABLED == 1) {
__HAL_RCC_CAN1_CLK_ENABLE();
}
__HAL_RCC_AFIO_CLK_ENABLE();
/**CAN1 GPIO Configuration
PB8 ------> CAN1_RX
PB9 ------> CAN1_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
__HAL_AFIO_REMAP_CAN1_2();
/* CAN1 interrupt Init */
HAL_NVIC_SetPriority(CAN1_TX_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(CAN1_TX_IRQn);
HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
HAL_NVIC_SetPriority(CAN1_RX1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(CAN1_RX1_IRQn);
HAL_NVIC_SetPriority(CAN1_SCE_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(CAN1_SCE_IRQn);
} else if (hcan->Instance == CAN2) {
/* Peripheral clock enable */
__HAL_RCC_CAN2_CLK_ENABLE();
HAL_RCC_CAN1_CLK_ENABLED++;
if (HAL_RCC_CAN1_CLK_ENABLED == 1) {
__HAL_RCC_CAN1_CLK_ENABLE();
}
/**CAN2 GPIO Configuration
PB5 ------> CAN2_RX
PB6 ------> CAN2_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
__HAL_AFIO_REMAP_CAN2_ENABLE();
/* CAN2 interrupt Init */
HAL_NVIC_SetPriority(CAN2_TX_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(CAN2_TX_IRQn);
HAL_NVIC_SetPriority(CAN2_RX0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(CAN2_RX0_IRQn);
HAL_NVIC_SetPriority(CAN2_RX1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(CAN2_RX1_IRQn);
HAL_NVIC_SetPriority(CAN2_SCE_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(CAN2_SCE_IRQn);
}
}
void
HAL_CAN_MspDeInit(CAN_HandleTypeDef *hcan)
{
if (hcan->Instance == CAN1) {
/**CAN1 GPIO Configuration
PB8 ------> CAN1_RX
PB9 ------> CAN1_TX
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8 | GPIO_PIN_9);
/* CAN1 interrupt DeInit */
HAL_NVIC_DisableIRQ(CAN1_TX_IRQn);
HAL_NVIC_DisableIRQ(CAN1_RX0_IRQn);
HAL_NVIC_DisableIRQ(CAN1_RX1_IRQn);
HAL_NVIC_DisableIRQ(CAN1_SCE_IRQn);
} else if (hcan->Instance == CAN2) {
/* Peripheral clock disable */
__HAL_RCC_CAN2_CLK_DISABLE();
/**CAN2 GPIO Configuration
PB5 ------> CAN2_RX
PB6 ------> CAN2_TX
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_5 | GPIO_PIN_6);
/* CAN2 interrupt DeInit */
HAL_NVIC_DisableIRQ(CAN2_TX_IRQn);
HAL_NVIC_DisableIRQ(CAN2_RX0_IRQn);
HAL_NVIC_DisableIRQ(CAN2_RX1_IRQn);
HAL_NVIC_DisableIRQ(CAN2_SCE_IRQn);
}
}
/**
* @brief This function handles CAN1 TX interrupt.
*/
void
CAN1_TX_IRQHandler(void)
{
HAL_CAN_IRQHandler(&hcan1);
}
/**
* @brief This function handles CAN1 RX0 interrupt.
*/
void
CAN1_RX0_IRQHandler(void)
{
HAL_CAN_IRQHandler(&hcan1);
}
/**
* @brief This function handles CAN1 RX1 interrupt.
*/
void
CAN1_RX1_IRQHandler(void)
{
HAL_CAN_IRQHandler(&hcan1);
}
/**
* @brief This function handles CAN1 SCE interrupt.
*/
void
CAN1_SCE_IRQHandler(void)
{
HAL_CAN_IRQHandler(&hcan1);
}
/**
* @brief This function handles CAN2 TX interrupt.
*/
void
CAN2_TX_IRQHandler(void)
{
HAL_CAN_IRQHandler(&hcan2);
}
/**
* @brief This function handles CAN2 RX0 interrupt.
*/
void
CAN2_RX0_IRQHandler(void)
{
HAL_CAN_IRQHandler(&hcan2);
}
/**
* @brief This function handles CAN2 RX1 interrupt.
*/
void
CAN2_RX1_IRQHandler(void)
{
HAL_CAN_IRQHandler(&hcan2);
}
/**
* @brief This function handles CAN2 SCE interrupt.
*/
void
CAN2_SCE_IRQHandler(void)
{
HAL_CAN_IRQHandler(&hcan2);
}
static void
make_crc(struct can_packet_t *msg)
{
uint8_t *p = (uint8_t *)msg;
uint32_t i;
uint8_t crc = 0u;
for (i = 0u; i < sizeof(struct can_packet_t) - 1u; i++) {
crc += p[i];
}
msg->crc = ~crc;
}
void
HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
HAL_StatusTypeDef res;
CAN_RxHeaderTypeDef RxHeader;
/* Get RX message */
res = HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader,
messages[rx_tail].data);
if (res != HAL_OK) {
/* Reception Error */
Error_Handler();
}
messages[rx_tail].magic = CAN_MSG_MAGIC;
if (hcan == &hcan1) {
messages[rx_tail].bus = 0u;
} else {
messages[rx_tail].bus = 1u;
}
union {
can_msg_t msg;
uint32_t u32;
} id;
id.u32 = RxHeader.ExtId;
messages[rx_tail].msg_id = id.msg;
messages[rx_tail].len = (uint8_t)RxHeader.DLC;
make_crc(&messages[rx_tail]);
rx_tail = next_idx(rx_tail);
}
void
can_init(void)
{
__HAL_RCC_AFIO_CLK_ENABLE();
__HAL_RCC_PWR_CLK_ENABLE();
MX_CAN1_Init();
MX_CAN2_Init();
}
/**
* @file can.h
* @author Алексей Хохлов <root@amper.me>
* @copyright WTFPL License
* @date 2019
* @brief Работа с CAN
*/
#pragma once
#include <stdbool.h>
#include <stm32f1xx_hal_can.h>
#include <can_proto.h>
#define CAN_MSG_MAGIC (0xAAu)
struct can_packet_t {
uint8_t magic;
uint8_t bus;
can_msg_t msg_id;
uint8_t data[8];
uint8_t len;
uint8_t crc;
};
/**
* @brief Функция настройки CAN
*/
void can_init(void);
/**
* @brief Отослать сообщение CAN
*/
void can_send(struct can_packet_t *msg);
/**
* @brief Получить сообщение CAN из очереди
*/
bool can_read_msg(struct can_packet_t **msg);
#include <stm32f1xx_hal.h>
#ifndef __INIT_H
#define __INIT_H
void setup(void);
extern CAN_HandleTypeDef hcan1;
extern CAN_HandleTypeDef hcan2;
extern I2C_HandleTypeDef hi2c2;
extern SPI_HandleTypeDef hspi1;
extern TIM_HandleTypeDef htim6;
extern TIM_HandleTypeDef htim7;
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
extern DMA_HandleTypeDef hdma_usart1_tx;
extern DMA_HandleTypeDef hdma_usart2_tx;
extern void can_init(void);
extern void uart_init(void);
extern void i2c_init(void);
extern void spi_init(void);
void MX_USB_OTG_FS_PCD_Init(void);
#endif
#include <stdbool.h>
#include <stddef.h>
#ifndef MAIN_H_
#define MAIN_H_
/**
* @brief Макрос функции-ошибки
*/
#define Error_Handler() _Error_Handler(__FILE__, __LINE__)
int printf(const char *format, ...);
void *memset(void *s, int c, size_t n);
void *memcpy(void *dest, const void *src, size_t n);
/**
* @brief Функция-обработчик ошибки выполнения
* @param file [in] - исходный файл
* @param line [in] - строка, на которой произошла ошибка
*/
void __attribute__((noreturn)) _Error_Handler(const char *file, int line);
#endif
This diff is collapsed.
#include <stdint.h>
#include <stm32f1xx_hal.h>
extern uint8_t *uart_read(uint16_t *count);
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
extern DMA_HandleTypeDef hdma_usart1_tx;
extern DMA_HandleTypeDef hdma_usart2_tx;
/**
* @file can.h
* @author Алексей Хохлов <root@amper.me>
* @copyright WTFPL License
* @date 2019
* @brief Работа с USB
*/
#pragma once
#include <can.h>
/**
* @brief Получить сообщение из очереди USB
*/
bool usb_get_msg(struct can_packet_t *msg);
/**
******************************************************************************
* @file : usb_device.h
* @version : v2.0_Cube
* @brief : Header for usb_device.c file.
******************************************************************************
* This notice applies to any and all portions of this file
* that are not between comment pairs USER CODE BEGIN and
* USER CODE END. Other portions of this file, whether
* inserted by the user or by software development tools
* are owned by their respective copyright owners.
*
* Copyright (c) 2019 STMicroelectronics International N.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_DEVICE__H__
#define __USB_DEVICE__H__