Page MenuHomec4science

dma_sbcp.h
No OneTemporary

File Metadata

Created
Sat, Aug 24, 17:42

dma_sbcp.h

/*
* dma_sbcp.h
*
* Copyright (c) Alexandre Tuleu
* EPFL Biorobotics Laboratory (http://biorob.epfl.ch)
* EPFL Ecole Polytechnique Federale de Lausanne (http://www.epfl.ch)
*
* 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/>.
*
*/
/**
* \file dma_sbcp.h
* DMA management for SBCP protocol
* \author Alexandre Tuleu
*
*/
#ifndef DMA_SBCP_H_
#define DMA_SBCP_H_
#include "dma_packet_queue.h"
#include "sbcp.h"
/**
* Initializes a channel for reception
* \param channel : the number of the dma channel to initialize
* \param type : either usb or bus
* \param TYPE : the same than type, but in capitals
* \param mask : the mask to use forincrementing DMA_packet_buffer_handler
*/
#define DMA_INIT_CHANNEL_FOR_RX(channel,type,TYPE) do {\
DMA_PACKET_QUEUE_INCREMENT_TAIL(dma_sbcp.type ## _rx_queue);\
DMA ## channel ## STA = DMA_PACKET_QUEUE_ ## TYPE ##_GET_DMA(dma_sbcp.type ## _rx_queue.tail);\
dma_sbcp.current_ ## type ##_rx_packet = DMA_PACKET_QUEUE_## TYPE ## _GET_CPU(dma_sbcp.type ## _rx_queue.tail);\
DMA ## channel ## CNT = 0; \
dma_sbcp.type ## _rx_state = DMA_WAIT_FOR_HEADER_BYTE;\
DMA ## channel ## CONbits.CHEN = 1;}while(0)
#ifdef SBCP_IS_MASTER
/**
* Initialize the USB dma channel.
*/
#define DMA_INIT_USB_RX do{\
DMA_PACKET_QUEUE_INCREMENT_TAIL(dma_sbcp.rx_queue);\
DMA2STA = DMA_PACKET_QUEUE_USB_GET_DMA(dma_sbcp.rx_queue.tail);\
dma_sbcp.current_usb_rx_packet = DMA_PACKET_QUEUE_USB_GET_CPU(dma_sbcp.rx_queue.tail);\
DMA2CNT = 0;\
dma_sbcp.usb_rx_state = DMA_WAIT_FOR_HEADER_BYTE;\
DMA2CONbits.CHEN = 1;\
dma_sbcp.packet_states[dma_sbcp.rx_queue.tail] = SBCP_FORWARD_STARTED_RECEPTION;\
}while(0)
//DMA_INIT_CHANNEL_FOR_RX(2,usb,USB)
/**
* Initialize the BUS dma channel
*/
#define DMA_INIT_BUS_RX do{\
DMA0STA = DMA_PACKET_QUEUE_BUS_GET_DMA(dma_sbcp.bus_rx_packet);\
dma_sbcp.current_bus_rx_packet = DMA_PACKET_QUEUE_BUS_GET_CPU(dma_sbcp.bus_rx_packet);\
DMA0CNT = 0;\
dma_sbcp.bus_rx_state = DMA_WAIT_FOR_HEADER_BYTE;\
DMA0CONbits.CHEN = 1;\
dma_sbcp.packet_states[dma_sbcp.bus_rx_packet] = SBCP_WAIT_FOR_FEEDBACK;\
}while(0)
#elif defined(SBCP_IS_SLAVE)
#define DMA_INIT_BUS_RX \
DMA_INIT_CHANNEL_FOR_RX(0,bus,BUS)
#endif
//DMA_INIT_CHANNEL_FOR_RX(0,bus,BUS)
/**
* Config a DMA channel to get the end of the header of a packet.
* \param channel : the number of the channel to use
* \param type : the queue to use
*/
#define DMA_CHANNEL_CONFIG_GET_END_HEADER(channel,type) do { \
DMA ## channel ## CONbits.CHEN = 0; \
DMA ## channel ## STA += 2;\
DMA ## channel ## CNT = 2;\
DMA ## channel ## CONbits.CHEN = 1; \
dma_sbcp.type ## _rx_state = DMA_WAIT_FOR_FULL_HEADER; } while(0)
#ifdef SBCP_IS_MASTER
/// Config the usb Rx channel to get the end of the headre of an packet
#define DMA_USB_CHANNEL_CONFIG_GET_END_HEADER \
DMA_CHANNEL_CONFIG_GET_END_HEADER(2,usb)
#endif
/// Config the bus Rx channel to get the end of the headre of an packet
#define DMA_BUS_CHANNEL_CONFIG_GET_END_HEADER \
DMA_CHANNEL_CONFIG_GET_END_HEADER(0,bus)
/**
* Config a channel to get the end of an packet.
* \param channel : the number of teh channel to use
* \param type : the associated type
*/
#define DMA_CHANNEL_CONFIG_GET_END_PACKET(channel,type) do { \
DMA ## channel ## CONbits.CHEN = 0;\
DMA ## channel ## STA += 6; \
unsigned char length = ((unsigned char *)dma_sbcp.current_## type ##_rx_packet)[2 * SBCP_POS_PAYLOAD_LENGTH]; \
if(length > DMA_SBCP_MAX_PACKET_PAYLOAD_SIZE){ length = DMA_SBCP_MAX_PACKET_PAYLOAD_SIZE; } \
DMA ## channel ## CNT = length + 1; \
DMA ## channel ## CONbits.CHEN = 1; \
dma_sbcp.type ## _rx_state = DMA_WAIT_FOR_FULL_PACKET;} while(0)
#ifdef SBCP_IS_MASTER
/**
* Config the usb rx channel to get the end of an packet.
*/
#define DMA_USB_CHANNEL_CONFIG_GET_END_PACKET \
DMA_CHANNEL_CONFIG_GET_END_PACKET(2,usb)
#endif
/**
* Config the bus rx channel to get the end of an packet.
*/
#define DMA_BUS_CHANNEL_CONFIG_GET_END_PACKET \
DMA_CHANNEL_CONFIG_GET_END_PACKET(0,bus)
#define DMA_BUS_DISABLE_ERR_DETECTION do{\
dma_sbcp.bus_uart_error_enable_flags = DMA_UART_ALL_ERRORS_DISABLED;\
}while(0)
#define DMA_BUS_ENABLE_ERR_DETECTION do{\
dma_sbcp.bus_uart_error_enable_flags = DMA_UART_FERR_ENABLED \
| DMA_UART_PERR_ENABLED \
| DMA_UART_OERR_ENABLED;\
}while(0)
#ifdef SBCP_IS_MASTER
/**
* Config a tx channel to send data over the bus.
* \param channel : the number of the channel to use
* \param type : aither usb or bus
* \param TYPE : the same than type, but in capitals
* \param state : the state that should have the channel after the transmission
* is started.
*/
/*#define DMA_CHANNEL_CONFIG_TRANSMISSION(channel,type,TYPE,LENGTH,state) do { \
DMA ## channel ## STA = DMA_PACKET_QUEUE_ ## TYPE ##_GET_DMA(dma_sbcp.type ## _rx_queue.head);\
DMA ## channel ## CNT = (LENGTH) & DMA_SBCP_MAX_PACKET_SIZE_MASK;\
sbcp.type ## _tx_state = state;\
DMA ## channel ## CONbits.CHEN = 1;\
DMA ## channel ## REQbits.FORCE = 1; \
}while(0) */
#elif defined(SBCP_IS_SLAVE)
#define DMA_INIT_BUS_TRANSMISSION do{\
DMA1CNT = ((((volatile unsigned int )DMA_PACKET_QUEUE_BUS_TX_BUFFER_CPU[SBCP_POS_PAYLOAD_LENGTH]) + 5 ) & DMA_SBCP_MAX_PACKET_SIZE_MASK );\
PORT_RS485_RECEIVER_DISABLE;\
PORT_RS485_DRIVER_ENABLE;\
DMA1REQbits.FORCE = 1;\
DMA1CONbits.CHEN = 1;\
}while(0)
#endif
#ifdef SBCP_IS_SLAVE
#endif //SBCP_IS_SLAVE
/**
* State for dma reception channel. REally simple state machine :
* DMA_WAIT_FOR_HEADER_BYTE > DMA_WAIT_FOR_FULL_HEADER >
* DMA_WAIT_FOR_FULL_PACKET > DMA_OVERFLOW_PEDNING;
* any state > DMA_WAIT_FOR_HEADER_BYTE
*/
typedef enum DMA_rx_state {
DMA_NO_RECEPTION = 0x00,
DMA_WAIT_FOR_HEADER_BYTE = 0x01, ///< Wait to get a 0xff
DMA_WAIT_FOR_FULL_HEADER = 0x02, ///< Wait to get the 4 first byte of an packet
DMA_WAIT_FOR_FULL_PACKET = 0x03, ///< Wait to get the complete packet
DMA_OVERFLOW_PENDING = 0x04 ///< an overflow is pending, reception is therefore *disabled*
} DMA_rx_state;
typedef enum DMA_UART_err_flags {
DMA_UART_ALL_ERRORS_DISABLED = 0x00,
DMA_UART_FERR_ENABLED = 0x01,
DMA_UART_PERR_ENABLED = 0x02,
DMA_UART_OERR_ENABLED = 0x04
} DMA_UART_err_flags;
#ifdef SBCP_IS_SLAVE
/**
* Static data for DMA management
*/
typedef struct DMA_SBCP_data {
/**
* state of the bus transmission
*/
DMA_rx_state bus_rx_state;
/**
* Represent the packet slots available for bis reception, and therefore for
* usb transmission.
*/
DMA_packet_queue bus_rx_queue;
/**
* Is 1 if a timeout issued while receiving over the bus.
*/
unsigned int bus_rx_error;
/**
* Pointer to the current received bus packet.
*/
unsigned int * current_bus_rx_packet;
DMA_UART_err_flags bus_uart_error_enable_flags;
} DMA_SBCP_data;
#elif defined(SBCP_IS_MASTER)
typedef enum eSBCP_tx_state{
SBCP_IDLE, ///< is free
SBCP_TX_FINISHED_PACKET, ///< is transmitting a well, finished packet
SBCP_TX_UNFINISHED_PACKET, ///< is transmitting an unfunished packet(unsafe !)
SBCP_HALF_DUPLEX_WAITING_RESPONSE
} eSBCP_tx_state;
typedef enum eSBCP_packet_flags{
SBCP_UNCHECKED = 0x00,
SBCP_CS_CHECKED = 0x01,
SBCP_CS_IS_CORRECT = 0x02,
SBCP_DEST_CHECKED = 0x04,
SBCP_DEST_IS_US = 0x08,
} eSBCP_packet_flags;
typedef enum eSBCP_packet_state{
SBCP_INEXISTANT = 0x00,
SBCP_FORWARD_STARTED_RECEPTION,
SBCP_FORWARD_DEST_AND_SIZE_KNOWN,
SBCP_FORWARD_READY_TO_TREAT,
SBCP_FORWARD_NEED_TO_BE_TRANSMITTED,
SBCP_FORWARD_NEED_TO_BE_TREATED_LOCALLY,
SBCP_FORWARD_IN_TX,
SBCP_WAIT_FOR_FEEDBACK,
SBCP_FEEDBACK_DEST_AND_SIZE_KNOWN,
SBCP_FEEDBACK_FULLY_RECEIVED,
SBCP_FEEDBACK_IN_TRANSMISSION
}eSBCP_packet_state;
typedef struct DMA_SBCP_data {
/**
* state of the usb transmission
*/
DMA_rx_state usb_rx_state;
DMA_rx_state bus_rx_state;
eSBCP_tx_state bus_tx_state;
eSBCP_tx_state usb_tx_state;
/**
* Represent the packet slots available for usb reception, (and thus bus
* transmission).
*/
DMA_packet_queue rx_queue;
DMA_packet_queue_buffer_handler bus_rx_packet;
/**
* Is 1 if a timeout issued while receiving over the usb.
*/
unsigned int usb_rx_error;
unsigned int bus_rx_error;
/**
* Pointer to the current received usb packet.
*/
unsigned int * current_usb_rx_packet;
unsigned int * current_bus_rx_packet;
eSBCP_packet_flags packet_flags[DMA_PACKET_QUEUE_LENGTH];
eSBCP_packet_state packet_states[DMA_PACKET_QUEUE_LENGTH];
DMA_UART_err_flags bus_uart_error_enable_flags;
} DMA_SBCP_data;
#endif
/**
* The global data of the dma module
*/
extern volatile DMA_SBCP_data dma_sbcp;
void dma_sbcp_init();
#endif //DMA_H_
///TODO :
/// seting priority of interruption :
/// timer should have a lower priority than interrupt of DMA

Event Timeline