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

@ -5,6 +5,8 @@
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( void USBD_GS_CAN_SendFrameToHost(
USBD_HandleTypeDef *pdev, USBD_HandleTypeDef *pdev,
uint32_t echo_id, uint32_t echo_id,

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_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS);
USBD_RegisterClass(&hUsbDeviceFS, &USBD_GS_CAN); USBD_RegisterClass(&hUsbDeviceFS, &USBD_GS_CAN);
USBD_GS_CAN_SetChannel(&hUsbDeviceFS, 0, &hcan);
USBD_Start(&hUsbDeviceFS); USBD_Start(&hUsbDeviceFS);
while (1) { while (1) {

View File

@ -1,27 +1,31 @@
#include "usbd_gs_can.h" #include "usbd_gs_can.h"
#include "stm32f0xx_hal.h"
#include "usbd_desc.h" #include "usbd_desc.h"
#include "usbd_ctlreq.h" #include "usbd_ctlreq.h"
#include "usbd_ioreq.h" #include "usbd_ioreq.h"
#include "gs_usb.h" #include "gs_usb.h"
#include "can.h"
#define CAN_DATA_MAX_PACKET_SIZE 32 /* Endpoint IN & OUT Packet size */ #define CAN_DATA_MAX_PACKET_SIZE 32 /* Endpoint IN & OUT Packet size */
#define CAN_CMD_PACKET_SIZE 64 /* Control Endpoint Packet size */ #define CAN_CMD_PACKET_SIZE 64 /* Control Endpoint Packet size */
#define USB_CAN_CONFIG_DESC_SIZ 32 #define USB_CAN_CONFIG_DESC_SIZ 32
#define NUM_CAN_CHANNEL 1
typedef struct { typedef struct {
__IO uint32_t TxState; __IO uint32_t TxState;
uint8_t req_bRequest; uint8_t req_bRequest;
uint8_t req_wLength; uint16_t req_wLength;
uint16_t req_wValue;
uint8_t ep0_buf[CAN_CMD_PACKET_SIZE]; uint8_t ep0_buf[CAN_CMD_PACKET_SIZE];
uint8_t ep_out_buf[CAN_DATA_MAX_PACKET_SIZE]; uint8_t ep_out_buf[CAN_DATA_MAX_PACKET_SIZE];
uint8_t ep_in_buf[CAN_DATA_MAX_PACKET_SIZE]; uint8_t ep_in_buf[CAN_DATA_MAX_PACKET_SIZE];
struct gs_host_config host_config; 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; } USBD_GS_CAN_HandleTypeDef;
static uint8_t USBD_GS_CAN_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx); 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; 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) static uint8_t USBD_GS_CAN_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{ {
(void) 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; 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) { switch (hcan->req_bRequest) {
case GS_USB_BREQ_HOST_FORMAT: case GS_USB_BREQ_HOST_FORMAT:
@ -156,20 +171,45 @@ static uint8_t USBD_GS_CAN_EP0_RxReady(USBD_HandleTypeDef *pdev) {
break; break;
case GS_USB_BREQ_MODE: case GS_USB_BREQ_MODE:
// TODO set device mode (flags, start/reset...) if (hcan->req_wValue < NUM_CAN_CHANNEL) {
memcpy(&hcan->device_mode, hcan->ep0_buf, sizeof(hcan->device_mode));
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; break;
case GS_USB_BREQ_BITTIMING: case GS_USB_BREQ_BITTIMING:
// TODO set bit timing timing = (struct gs_device_bittiming*)hcan->ep0_buf;
memcpy(&hcan->bittiming, hcan->ep0_buf, sizeof(hcan->bittiming)); 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; break;
default: default:
break; break;
} }
hcan->req_bRequest = 0xFF; hcan->req_bRequest = 0xFF;
return USBD_OK; 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_MODE:
case GS_USB_BREQ_BITTIMING: case GS_USB_BREQ_BITTIMING:
hcan->req_bRequest = req->bRequest; 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); USBD_CtlPrepareRx(pdev, hcan->ep0_buf, req->wLength);
break; break;
@ -324,7 +365,5 @@ void USBD_GS_CAN_SendFrameToHost(
hf.data[i] = data[i]; 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));
} }
}