implement can settings

This commit is contained in:
Hubert Denkmair 2016-04-08 22:57:28 +02:00
parent 48bbbbb254
commit b52e20ecb6
5 changed files with 108 additions and 14 deletions

8
include/can.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#include <stdbool.h>
#include "stm32f0xx_hal.h"
void can_set_bittiming(CAN_HandleTypeDef *hcan, uint16_t brp, uint8_t phase_seg1, uint8_t phase_seg2, uint8_t sjw);
void can_enable(CAN_HandleTypeDef *hcan, bool loop_back, bool listen_only, bool one_shot, bool triple_sample);
void can_disable(CAN_HandleTypeDef *hcan);

View File

@ -3,7 +3,9 @@
#include "usbd_def.h"
extern USBD_ClassTypeDef USBD_GS_CAN;
extern USBD_ClassTypeDef USBD_GS_CAN;
void USBD_GS_CAN_SetChannel(USBD_HandleTypeDef *pdev, uint8_t channel, CAN_HandleTypeDef* handle);
void USBD_GS_CAN_SendFrameToHost(
USBD_HandleTypeDef *pdev,

44
src/can.c Normal file
View File

@ -0,0 +1,44 @@
#include "can.h"
void can_set_bittiming(CAN_HandleTypeDef *hcan, uint16_t brp, uint8_t phase_seg1, uint8_t phase_seg2, uint8_t sjw)
{
HAL_CAN_DeInit(hcan);
hcan->Init.Prescaler = brp;
if ((phase_seg1>0) && (phase_seg1<17)) {
hcan->Init.BS1 = (phase_seg1-1)<<16;
}
if ((phase_seg2>0) && (phase_seg2<9)) {
hcan->Init.BS2 = (phase_seg2-1)<<20;
}
if ((sjw>0) && (sjw<5)) {
hcan->Init.SJW = (sjw-1)<<24;
}
HAL_CAN_Init(hcan);
}
void can_enable(CAN_HandleTypeDef *hcan, bool loop_back, bool listen_only, bool one_shot, bool triple_sample)
{
hcan->Init.Mode = 0;
if (loop_back) {
hcan->Init.Mode |= CAN_MODE_LOOPBACK;
}
if (listen_only) {
hcan->Init.Mode |= CAN_MODE_SILENT;
}
hcan->Init.NART = one_shot ? ENABLE : DISABLE;
// tripple sample not supported on bxCAN
HAL_CAN_Init(hcan);
}
void can_disable(CAN_HandleTypeDef *hcan)
{
HAL_CAN_DeInit(hcan);
}

View File

@ -74,6 +74,7 @@ int main(void)
USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS);
USBD_RegisterClass(&hUsbDeviceFS, &USBD_GS_CAN);
USBD_GS_CAN_SetChannel(&hUsbDeviceFS, 0, &hcan);
USBD_Start(&hUsbDeviceFS);
while (1) {

View File

@ -1,27 +1,31 @@
#include "usbd_gs_can.h"
#include "stm32f0xx_hal.h"
#include "usbd_desc.h"
#include "usbd_ctlreq.h"
#include "usbd_ioreq.h"
#include "gs_usb.h"
#include "can.h"
#define CAN_DATA_MAX_PACKET_SIZE 32 /* Endpoint IN & OUT Packet size */
#define CAN_CMD_PACKET_SIZE 64 /* Control Endpoint Packet size */
#define USB_CAN_CONFIG_DESC_SIZ 32
#define NUM_CAN_CHANNEL 1
typedef struct {
__IO uint32_t TxState;
uint8_t req_bRequest;
uint8_t req_wLength;
uint8_t req_bRequest;
uint16_t req_wLength;
uint16_t req_wValue;
uint8_t ep0_buf[CAN_CMD_PACKET_SIZE];
uint8_t ep_out_buf[CAN_DATA_MAX_PACKET_SIZE];
uint8_t ep_in_buf[CAN_DATA_MAX_PACKET_SIZE];
struct gs_host_config host_config;
struct gs_device_mode device_mode;
struct gs_device_bittiming bittiming;
CAN_HandleTypeDef *channels[NUM_CAN_CHANNEL];
} USBD_GS_CAN_HandleTypeDef;
static uint8_t USBD_GS_CAN_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
@ -127,6 +131,13 @@ static uint8_t USBD_GS_CAN_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
return ret;
}
void USBD_GS_CAN_SetChannel(USBD_HandleTypeDef *pdev, uint8_t channel, CAN_HandleTypeDef* handle) {
USBD_GS_CAN_HandleTypeDef *hcan = (USBD_GS_CAN_HandleTypeDef*) pdev->pClassData;
if ((hcan!=NULL) && (channel < NUM_CAN_CHANNEL)) {
hcan->channels[channel] = handle;
}
}
static uint8_t USBD_GS_CAN_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
(void) cfgidx;
@ -148,6 +159,10 @@ static uint8_t USBD_GS_CAN_EP0_RxReady(USBD_HandleTypeDef *pdev) {
USBD_GS_CAN_HandleTypeDef *hcan = (USBD_GS_CAN_HandleTypeDef*) pdev->pClassData;
struct gs_device_bittiming *timing;
struct gs_device_mode *mode;
CAN_HandleTypeDef *ch;
switch (hcan->req_bRequest) {
case GS_USB_BREQ_HOST_FORMAT:
@ -156,20 +171,45 @@ static uint8_t USBD_GS_CAN_EP0_RxReady(USBD_HandleTypeDef *pdev) {
break;
case GS_USB_BREQ_MODE:
// TODO set device mode (flags, start/reset...)
memcpy(&hcan->device_mode, hcan->ep0_buf, sizeof(hcan->device_mode));
if (hcan->req_wValue < NUM_CAN_CHANNEL) {
mode = (struct gs_device_mode*)hcan->ep0_buf;
ch = hcan->channels[hcan->req_wValue];
if (mode->mode == GS_CAN_MODE_RESET) {
can_disable(ch);
} else if (mode->mode == GS_CAN_MODE_START) {
can_enable(ch,
(mode->flags & GS_CAN_MODE_LOOP_BACK) != 0,
(mode->flags & GS_CAN_MODE_LISTEN_ONLY) != 0,
(mode->flags & GS_CAN_MODE_ONE_SHOT) != 0,
(mode->flags & GS_CAN_MODE_TRIPLE_SAMPLE) != 0
);
}
}
break;
case GS_USB_BREQ_BITTIMING:
// TODO set bit timing
memcpy(&hcan->bittiming, hcan->ep0_buf, sizeof(hcan->bittiming));
timing = (struct gs_device_bittiming*)hcan->ep0_buf;
if (hcan->req_wValue < NUM_CAN_CHANNEL) {
can_set_bittiming(
hcan->channels[hcan->req_wValue],
timing->brp,
timing->prop_seg + timing->phase_seg1,
timing->phase_seg2,
timing->sjw
);
}
break;
default:
break;
}
hcan->req_bRequest = 0xFF;
return USBD_OK;
}
@ -203,7 +243,8 @@ static uint8_t USBD_GS_CAN_Vendor_Request(USBD_HandleTypeDef *pdev, USBD_SetupRe
case GS_USB_BREQ_MODE:
case GS_USB_BREQ_BITTIMING:
hcan->req_bRequest = req->bRequest;
hcan->req_wLength = (uint8_t)req->wLength;
hcan->req_wLength = req->wLength;
hcan->req_wValue = req->wValue;
USBD_CtlPrepareRx(pdev, hcan->ep0_buf, req->wLength);
break;
@ -324,7 +365,5 @@ void USBD_GS_CAN_SendFrameToHost(
hf.data[i] = data[i];
}
if (hcan->device_mode.mode == GS_CAN_MODE_START) {
USBD_GS_CAN_Transmit(pdev, (uint8_t*)&hf, sizeof(hf));
}
USBD_GS_CAN_Transmit(pdev, (uint8_t*)&hf, sizeof(hf));
}