Skip to content

Commit

Permalink
Merge pull request #1 from josepablo134/fix-spi
Browse files Browse the repository at this point in the history
fix(spi): SPI driver now handles the CS pin dynamically

Using the peripheral state machine so the peripheral can control the CS channel automatically as long as we control the flow of the SPI packages by knowing what is the last package in the frame.
  • Loading branch information
josepablo134 authored Mar 14, 2023
2 parents 61ba1fe + 6e92960 commit a9b63e5
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 119 deletions.
36 changes: 29 additions & 7 deletions include/MCP2515/MCP2515_regmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,28 @@
#define MCP2515_CMD_RTS_TX_2 0x84
#define MCP2515_CMD_RTS_TX_ALL 0x87

// RX STATUS Bits
#define MCP2515_RX_STATUS_RXF_MASK 0x07
#define MCP2515_RX_STATUS_RXF0 0x00
#define MCP2515_RX_STATUS_RXF1 0x01
#define MCP2515_RX_STATUS_RXF2 0x02
#define MCP2515_RX_STATUS_RXF3 0x03
#define MCP2515_RX_STATUS_RXF4 0x04
#define MCP2515_RX_STATUS_RXF5 0x05
#define MCP2515_RX_STATUS_RXF0_RXB1 0x06
#define MCP2515_RX_STATUS_RXF1_RXB1 0x07
///
#define MCP2515_RX_STATUS_MSG_TYPE_MASK 0x18
#define MCP2515_RX_STATUS_MSG_STD 0x00
#define MCP2515_RX_STATUS_MSG_STD_RTR 0x08
#define MCP2515_RX_STATUS_MSG_EFF 0x10
#define MCP2515_RX_STATUS_MSG_EFF_RTR 0x18
///
#define MCP2515_RX_STATUS_MSG_RCV_MASK 0xC0
#define MCP2515_RX_STATUS_MSG_RCV_RXB0 0x40
#define MCP2515_RX_STATUS_MSG_RCV_RXB1 0x80
#define MCP2515_RX_STATUS_MSG_RCV_RXBX 0xC0

// Modes of Operation
#define MCP2515_OP_MODE_MASK 0xE0
#define MCP2515_OP_MODE_NORMAL 0x00
Expand All @@ -202,14 +224,14 @@
#define MCP2515_SAM_3X 0x40

/// One-shot mode
#define MCP2515_OSM_MASK 0x08
#define MCP2515_OSM_ENABLED 0x08
#define MCP2515_OSM_DISABLED 0x00
#define MCP2515_OSM_MASK 0x08
#define MCP2515_OSM_ENABLED 0x08
#define MCP2515_OSM_DISABLED 0x00

/// Abort all pending transmissions
#define MCP2515_ABAT_MASK 0x10
#define MCP2515_ABAT_ENABLED 0x10
#define MCP2515_ABAT_DISABLED 0x00
#define MCP2515_ABAT_MASK 0x10
#define MCP2515_ABAT_ENABLED 0x10
#define MCP2515_ABAT_DISABLED 0x00

// Interrupt settings
#define MCP2515_DISABLE_ALL_INTS 0x00
Expand Down Expand Up @@ -237,7 +259,7 @@
#define MCP2515_TX1RTS_PIN_RTS 0x02
#define MCP2515_TX2RTS_PIN_RTS 0x04

#define MCP2515_MAX_FRAME_DATA_LENGTH 0x08
#define MCP2515_MAX_FRAME_DATA_LENGTH 0x08

#ifdef __cplusplus
}
Expand Down
6 changes: 6 additions & 0 deletions include/SPI/DriverSPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@
#define DriverSPI_SPI_MODE_PHA_0 0x00
#define DriverSPI_SPI_MODE_PHA_1 0x01

/// Configure the SPI Frame mode
// frame mode is set as a bit OR operation to this flag
#define DriverSPI_IOCTL_CONF_FRAME_MODE 0x00000200
#define DriverSPI_IOCTL_CONF_FRAME_NORMAL 0x00
#define DriverSPI_IOCTL_CONF_FRAME_PARTITION 0x01

struct DriverSPI_mode{
uint32_t bitrate;
uint8_t polarity;/// DriverSPI_SPI_MODE_POL_{0,1}
Expand Down
6 changes: 6 additions & 0 deletions include/SPI/TivaCTM4C1294/DriverSPI_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,19 @@

#define DriverSPI_DEFAULT_BITRATE 1000000

/// SPI devices software flags
#define DriverSPI_MODE_MASK 0x01 /* Frame mode mask */
#define DriverSPI_MODE_FRAME_NORMAL 0x00 /* Each write/read operation is a Frame */
#define DriverSPI_MODE_FRAME_PARTITION 0x01 /* The Frame is divided by multiple readings/writings */

typedef enum TM4C1294XL_SPIName {
TM4C1294XL_SPI2 = 0,
TM4C1294XL_SPI3,
TM4C1294XL_SPICOUNT
} TM4C1294XL_SPIName;

extern const uint32_t DriverSPI_devices[ TM4C1294XL_SPICOUNT ];
extern uint8_t DriverSPI_flags[ TM4C1294XL_SPICOUNT ];


#ifdef __cplusplus
Expand Down
184 changes: 84 additions & 100 deletions source/MCP2515/TivaCTM4C1294/MCP2515_SPI.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@
#include <stdbool.h>
#include <stdint.h>

#define SPI_ENABLE GPIOPinWrite( GPIO_PORTD_BASE , GPIO_PIN_2 , 0 )
#define SPI_DISABLE GPIOPinWrite( GPIO_PORTD_BASE , GPIO_PIN_2 , GPIO_PIN_2 )

void MCP2515_init(void){
DriverSPI_init();
}
Expand All @@ -40,47 +37,44 @@ int MCP2515_open(unsigned int device ){
/// Setting SPI operation mode
DriverSPI_ioctl( fd , DriverSPI_IOCTL_CONF_MODE , &mode );

/*
/// Overwritte SPI_SS for GPIO MODE
/// Manually control the GPIO SS/CS PIN
GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_2);
GPIOPadConfigSet( GPIO_PORTD_BASE , GPIO_PIN_2 , GPIO_STRENGTH_12MA , GPIO_PIN_TYPE_STD );
GPIOPinWrite( GPIO_PORTD_BASE , GPIO_PIN_2 , GPIO_PIN_2 );
*/

return fd;
}
/// Send a IOCTL order
int MCP2515_ioctl( int fd , unsigned int config , void* buffer ){
switch( config & MCP2515_IOCTL_CMD_MASK ){
case MCP2515_IOCTL_RESET:{
SPI_ENABLE;
DriverSPI_ioctl( fd, DriverSPI_IOCTL_CONF_FRAME_MODE | DriverSPI_IOCTL_CONF_FRAME_NORMAL , 0x00 );
uint8_t rstCommand = MCP2515_CMD_RESET;
DriverSPI_write( fd, &rstCommand, 1);
SPI_DISABLE;
return 0;
}
case MCP2515_IOCTL_WRITE_CMD:{
if( !buffer ){ return -1; }
struct MCP2515_command* cmd = (struct MCP2515_command*) buffer;

/// CS Enable
SPI_ENABLE;
DriverSPI_write( fd, &(cmd->cmd), cmd->cmdLen );
DriverSPI_write( fd, cmd->params, cmd->paramsLen);
/// CS Disable
SPI_DISABLE;

DriverSPI_ioctl( fd, DriverSPI_IOCTL_CONF_FRAME_MODE | DriverSPI_IOCTL_CONF_FRAME_PARTITION , 0x00 );
DriverSPI_write( fd, &(cmd->cmd), cmd->cmdLen );
DriverSPI_ioctl( fd, DriverSPI_IOCTL_CONF_FRAME_MODE | DriverSPI_IOCTL_CONF_FRAME_NORMAL , 0x00 );
DriverSPI_write( fd, cmd->params, cmd->paramsLen);
return 0;
}
case MCP2515_IOCTL_READ_CMD:{
if( !buffer ){ return -1; }
struct MCP2515_command* cmd = (struct MCP2515_command*) buffer;

/// CS Enable
SPI_ENABLE;
DriverSPI_write( fd, &(cmd->cmd), cmd->cmdLen );
DriverSPI_read( fd, cmd->params, cmd->paramsLen);
/// CS Disable
SPI_DISABLE;
DriverSPI_ioctl( fd, DriverSPI_IOCTL_CONF_FRAME_MODE | DriverSPI_IOCTL_CONF_FRAME_PARTITION , 0x00 );
DriverSPI_write( fd, &(cmd->cmd), cmd->cmdLen );
DriverSPI_ioctl( fd, DriverSPI_IOCTL_CONF_FRAME_MODE | DriverSPI_IOCTL_CONF_FRAME_NORMAL , 0x00 );
DriverSPI_read( fd, cmd->params, cmd->paramsLen);

return 0;
}
Expand All @@ -102,11 +96,8 @@ int MCP2515_ioctl( int fd , unsigned int config , void* buffer ){
default:
return -1;
}
/// CS Enable
SPI_ENABLE;
DriverSPI_write( fd, &command, 1 );
/// CS Disable
SPI_DISABLE;
DriverSPI_ioctl( fd, DriverSPI_IOCTL_CONF_FRAME_MODE | DriverSPI_IOCTL_CONF_FRAME_NORMAL , 0x00 );
DriverSPI_write( fd, &command, 1 );
return 0;
}
case MCP2515_IOCTL_ONE_SHOT_MODE:{
Expand All @@ -119,11 +110,8 @@ int MCP2515_ioctl( int fd , unsigned int config , void* buffer ){
if( !(config & MCP2515_IOCTL_DATA_MASK) ){
command[3] = MCP2515_OSM_DISABLED;
}
/// CS Enable
SPI_ENABLE;
DriverSPI_write( fd, command, sizeof(command) );
/// CS Disable
SPI_DISABLE;
DriverSPI_ioctl( fd, DriverSPI_IOCTL_CONF_FRAME_MODE | DriverSPI_IOCTL_CONF_FRAME_NORMAL , 0x00 );
DriverSPI_write( fd, command, sizeof(command) );
return 0;
}
}
Expand Down Expand Up @@ -153,44 +141,44 @@ int MCP2515_write( int fd , const void* buffer, unsigned int size ){
return -1;
}

/// CS Enable
SPI_ENABLE;
/// Load Frame to send
wrCounter = DriverSPI_write( fd, &mcp_load_instruction, 1 );
/// Begin Frame
DriverSPI_ioctl( fd, DriverSPI_IOCTL_CONF_FRAME_MODE | DriverSPI_IOCTL_CONF_FRAME_PARTITION , 0x00 );
/// Load Frame to send
wrCounter = DriverSPI_write( fd, &mcp_load_instruction, 1 );

/// According with the datasheet, the load instruction
// allows writing TX buffer in the next order:
// IDH, IDL, ID8, ID0, DLC, D0..D7
uint8_t canId[4];
/// According with the datasheet, the load instruction
// allows writing TX buffer in the next order:
// IDH, IDL, ID8, ID0, DLC, D0..D7
uint8_t canId[4];

// IDH -> Standard ID higher bits (10 .. 3) bit.
canId[0] = (frm->can_id.CAN_ID_STD)>>3;
// IDH -> Standard ID higher bits (10 .. 3) bit.
canId[0] = (frm->can_id.CAN_ID_STD)>>3;

// IDL -> Standard ID lower bits (2 .. 0) bits
canId[1] = (frm->can_id.CAN_ID_STD)<<5;
/// Extended frame format
if( frm->can_id.CAN_ID_EFF ){
canId[1] |= MCP2515_TX_BUFF_ID_HIGH_EXIDE;///Set EXIDE Flag
}
///Set extended ID bits (17 .. 16) bits
canId[1] |= ( (frm->can_id.CAN_ID_EXT)>>16 ) & 0x3;
// IDL -> Standard ID lower bits (2 .. 0) bits
canId[1] = (frm->can_id.CAN_ID_STD)<<5;
/// Extended frame format
if( frm->can_id.CAN_ID_EFF ){
canId[1] |= MCP2515_TX_BUFF_ID_HIGH_EXIDE;///Set EXIDE Flag
}
///Set extended ID bits (17 .. 16) bits
canId[1] |= ( (frm->can_id.CAN_ID_EXT)>>16 ) & 0x3;

/// Set the rest of the Extended ID
canId[2] = (frm->can_id.CAN_ID_EXT>>8);//ID8
canId[3] = (frm->can_id.CAN_ID_EXT);//ID0
/// Set the rest of the Extended ID
canId[2] = (frm->can_id.CAN_ID_EXT>>8);//ID8
canId[3] = (frm->can_id.CAN_ID_EXT);//ID0

/// Send actual ID configuration
wrCounter += DriverSPI_write( fd, canId , sizeof(canId) );
/// Send actual ID configuration
wrCounter += DriverSPI_write( fd, canId , sizeof(canId) );

/// Configure Data Length Code Register
// Set RTR bit if required
canId[0] = frm->can_dlc | ( frm->can_id.CAN_ID_RTR << 6 );
wrCounter += DriverSPI_write( fd, canId , 1 );
/// Configure Data Length Code Register
// Set RTR bit if required
canId[0] = frm->can_dlc | ( frm->can_id.CAN_ID_RTR << 6 );
wrCounter += DriverSPI_write( fd, canId , 1 );

/// Send data bytes
wrCounter += DriverSPI_write( fd, frm->data , frm->can_dlc );
/// CS Disable
SPI_DISABLE;
/// Ending of the frame
DriverSPI_ioctl( fd, DriverSPI_IOCTL_CONF_FRAME_MODE | DriverSPI_IOCTL_CONF_FRAME_NORMAL , 0x00 );
/// Send data bytes
wrCounter += DriverSPI_write( fd, frm->data , frm->can_dlc );

return wrCounter;
}
Expand All @@ -213,58 +201,54 @@ int MCP2515_read( int fd , void* buffer, unsigned int size ){
return -1;
}

/// CS Enable
SPI_ENABLE;
/// According with the datasheet, the read instruction
// allows reading RX buffer in the next order:
// IDH, IDL, ID8, ID0, DLC, D0..D7
uint8_t canId[5];
/// Begin frame
DriverSPI_ioctl( fd, DriverSPI_IOCTL_CONF_FRAME_MODE | DriverSPI_IOCTL_CONF_FRAME_PARTITION , 0x00 );
/// According with the datasheet, the read instruction
// allows reading RX buffer in the next order:
// IDH, IDL, ID8, ID0, DLC, D0..D7
uint8_t canId[5];

/// Read Frame command
DriverSPI_write( fd, &mcp_read_instruction, 1 );
/// Read Frame command
DriverSPI_write( fd, &mcp_read_instruction, 1 );

/// Read IDH,IDL,ID8,ID0 and DLC
rdCounter = DriverSPI_read( fd , canId , sizeof(canId) );
/// Read IDH,IDL,ID8,ID0 and DLC
rdCounter = DriverSPI_read( fd , canId , sizeof(canId) );

/// CAN ID Needs reorder
/// CAN ID Needs reorder

/// Setting Standard CAN ID
frm->can_id.ID = 0x00;
frm->can_id.CAN_ID_STD = ((uint16_t)canId[0])<<3;
frm->can_id.CAN_ID_STD |= canId[1]>>5;
/// Setting Standard CAN ID
frm->can_id.ID = 0x00;
frm->can_id.CAN_ID_STD = ((uint16_t)canId[0])<<3;
frm->can_id.CAN_ID_STD |= canId[1]>>5;

/// Extended Frame Format
frm->can_id.CAN_ID_EFF = (canId[1] & MCP2515_RX_BUFF_ID_LOW_IDE)? 1: 0;
/// Extended Frame Format
frm->can_id.CAN_ID_EFF = (canId[1] & MCP2515_RX_BUFF_ID_LOW_IDE)? 1: 0;

/// Standard Frame Remote Transmit Request
frm->can_id.CAN_ID_RTR = (canId[1] & MCP2515_RX_BUFF_ID_LOW_SRR)? 1: 0;
/// Standard Frame Remote Transmit Request
frm->can_id.CAN_ID_RTR = (canId[1] & MCP2515_RX_BUFF_ID_LOW_SRR)? 1: 0;

if( frm->can_id.CAN_ID_EFF ){
/// Extended Frame Remote Transmit Request
frm->can_id.CAN_ID_RTR |= (canId[4] & MCP2515_RX_DLC_RTR)? 1: 0;

/// Setting Extended CAN ID
frm->can_id.CAN_ID_EXT = ((uint32_t)canId[1] & 0x03)<<16;
frm->can_id.CAN_ID_EXT |= ((uint32_t)canId[2]) << 8;
frm->can_id.CAN_ID_EXT |= canId[3];
}else{
frm->can_id.CAN_ID_EXT = 0;
}
if( frm->can_id.CAN_ID_EFF ){
/// Extended Frame Remote Transmit Request
frm->can_id.CAN_ID_RTR |= (canId[4] & MCP2515_RX_DLC_RTR)? 1: 0;

/// Set Data Length Code
frm->can_dlc = canId[4] & 0x1F;

/// Validate Data Length Code
if(frm->can_dlc > MCP2515_MAX_FRAME_DATA_LENGTH){
SPI_DISABLE;
return -1;
}
/// Setting Extended CAN ID
frm->can_id.CAN_ID_EXT = ((uint32_t)canId[1] & 0x03)<<16;
frm->can_id.CAN_ID_EXT |= ((uint32_t)canId[2]) << 8;
frm->can_id.CAN_ID_EXT |= canId[3];
}else{
frm->can_id.CAN_ID_EXT = 0;
}

/// Read Frame Bytes
rdCounter += DriverSPI_read( fd , &frm->data , frm->can_dlc );
/// CS Disable
SPI_DISABLE;
/// Set Data Length Code
frm->can_dlc = canId[4] & 0x1F;

/// Validate Data Length Code
if(frm->can_dlc > MCP2515_MAX_FRAME_DATA_LENGTH){
frm->can_dlc = MCP2515_MAX_FRAME_DATA_LENGTH;
}
/// Ending of the frame
DriverSPI_ioctl( fd, DriverSPI_IOCTL_CONF_FRAME_MODE | DriverSPI_IOCTL_CONF_FRAME_PARTITION , 0x00 );
rdCounter += DriverSPI_read( fd , &frm->data , frm->can_dlc );
return rdCounter;
}
/// Release controller
Expand Down
Loading

0 comments on commit a9b63e5

Please sign in to comment.