Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F79105589
dma_sbcp_slave.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, Aug 24, 18:57
Size
9 KB
Mime Type
text/x-c
Expires
Mon, Aug 26, 18:57 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
20147388
Attached To
R6619 Oncilla Motordriver Firmware
dma_sbcp_slave.c
View Options
/*
* dma_sbcp.c
*
* Copyright (c) 2011 Alexandre Tuleu
*
*/
#include <p33Fxxxx.h>
#include "dma_sbcp.h"
#include "sbcp.h"
#include "config.h"
#include "timer.h"
#include "port.h"
//note: now dma for sbcp buffer are allocated in dma_memory_mapping_sbcp.c module
volatile
DMA_SBCP_data
dma_sbcp
;
/*
DMA_packet_tx_queue dma_usb_tx_queue = {
0, //head
0, //tail
0, //nb_packet
{0,0,0,0}, //data_dma
{0,0,0,0} //data_cpu
};
DMA_packet_tx_queue dma_bus_tx_queue = {
0, //head
0, //tail
0, //nb_packet
{0,0,0,0}, //data_dma
{0,0,0,0} //data_cpu
};
*/
/* Interruption for the first dma channel.*/
void
__attribute__
((
__interrupt__
,
no_auto_psv
))
_DMA0Interrupt
(
void
)
{
switch
(
dma_sbcp
.
bus_rx_state
)
{
case
DMA_WAIT_FOR_HEADER_BYTE
:
{
if
(
*
(
dma_sbcp
.
current_bus_rx_packet
)
!=
0
X00ff
){
DMA0CONbits
.
CHEN
=
0
;
DMA0CONbits
.
CHEN
=
1
;
}
else
{
DMA_BUS_CHANNEL_CONFIG_GET_END_HEADER
;
TIMER_4_START
;
//DMA_BUS_ENABLE_ERR_DETECTION;
}
break
;
}
case
DMA_WAIT_FOR_FULL_HEADER
:
{
DMA_BUS_CHANNEL_CONFIG_GET_END_PACKET
;
break
;
}
case
DMA_WAIT_FOR_FULL_PACKET
:
{
//first of all, we check if the packet is for us.
if
(
dma_sbcp
.
current_bus_rx_packet
[
SBCP_POS_ID
]
!=
SBCP_MY_ID
||
dma_sbcp
.
current_bus_rx_packet
[
SBCP_POS_CLASS
]
!=
SBCP_MY_CLASS
){
//the packet is not for us, we re-init the DMA 0 channel, and we
//the current incoming packet.
DMA0STA
-=
8
;
// we remove the 4 first pointed bytes
DMA0CNT
=
0
;
//just one byte reception
DMA0CONbits
.
CHEN
=
1
;
//channel is resetted
dma_sbcp
.
bus_rx_state
=
DMA_WAIT_FOR_HEADER_BYTE
;
//we are waiting the first byte
}
else
{
//the packet is for us
if
(
sbcp
.
bus_low_latency_flags
&
SBCP_LL_IS_DISABLED
){
IEC0bits
.
DMA0IE
=
0
;
return
;
}
//We check if it is the special low latency instruction
//this instruction should be responded ASAP, so in this interruption.
if
(
dma_sbcp
.
current_bus_rx_packet
[
SBCP_POS_INSTRUCTION
]
==
SBCP_LOW_LATENCY_INSTRUCTION
)
{
//of course checksum should be checked
unsigned
char
correctChecksum
=
SBCP_MY_CLASS
+
SBCP_MY_ID
+
SBCP_LOW_LATENCY_INSTRUCTION_COMMAND_PAYLOAD_SIZE
+
SBCP_LOW_LATENCY_INSTRUCTION
;
correctChecksum
+=
dma_sbcp
.
current_bus_rx_packet
[
SBCP_POS_PAYLOAD_START
];
correctChecksum
+=
dma_sbcp
.
current_bus_rx_packet
[
SBCP_POS_PAYLOAD_START
+
1
];
correctChecksum
+=
dma_sbcp
.
current_bus_rx_packet
[
SBCP_POS_PAYLOAD_START
+
2
];
correctChecksum
+=
dma_sbcp
.
current_bus_rx_packet
[
SBCP_POS_PAYLOAD_START
+
3
];
if
(
correctChecksum
==
dma_sbcp
.
current_bus_rx_packet
[
SBCP_POS_PAYLOAD_START
+
4
])
{
//we use the already prepared standard message
DMA1STA
=
DMA_PACKET_QUEUE_BUS_LL_TX_BUFFER_DMA
;
DMA1CNT
=
SBCP_LOW_LATENCY_INSTRUCTION_FEEDBACK_PAYLOAD_SIZE
+
5
;
PORT_RS485_RECEIVER_DISABLE
;
PORT_RS485_DRIVER_ENABLE
;
DMA1CONbits
.
CHEN
=
1
;
DMA1REQbits
.
FORCE
=
1
;
//we save the incomming payload.
sbcp
.
bus_low_latency_payload
[
0
]
=
dma_sbcp
.
current_bus_rx_packet
[
SBCP_POS_PAYLOAD_START
];
sbcp
.
bus_low_latency_payload
[
1
]
=
dma_sbcp
.
current_bus_rx_packet
[
SBCP_POS_PAYLOAD_START
+
1
];
sbcp
.
bus_low_latency_payload
[
2
]
=
dma_sbcp
.
current_bus_rx_packet
[
SBCP_POS_PAYLOAD_START
+
2
];
sbcp
.
bus_low_latency_payload
[
3
]
=
dma_sbcp
.
current_bus_rx_packet
[
SBCP_POS_PAYLOAD_START
+
3
];
//we specify that new data is available to treat it at the appropriate time
sbcp
.
bus_low_latency_flags
|=
SBCP_LL_RX_IS_AVAILABLE
;
}
else
{
//we get a bad checksum
//we use the already prepared error
DMA1STA
=
DMA_PACKET_QUEUE_BUS_LL_ERROR_TX_BUFFER_DMA
;
DMA1CNT
=
6
;
PORT_RS485_RECEIVER_DISABLE
;
PORT_RS485_DRIVER_ENABLE
;
DMA1CONbits
.
CHEN
=
1
;
DMA1REQbits
.
FORCE
=
1
;
}
sbcp
.
bus_tx_flags
=
SBCP_TX_BUFFER_IN_TX
;
//we mark it as treated since it was for us, and we have treated it.
DMA_PACKET_QUEUE_INCREMENT_HEAD
(
sbcp
.
bus_ready_packet_queue
);
}
//the packet is for us (just imagine that this line is just
// after the else :) ) so we mark it as ready for treatment. If
// it was a low latency one, it would already have been already
//treated.
DMA_PACKET_QUEUE_INCREMENT_TAIL
(
sbcp
.
bus_ready_packet_queue
);
}
//now we clear the timer 4. Interruption may have already occured,
//but masked by this one that have a higher priority. To not mess up
//the whole thing, we should clear the corresponding interrupt flag.
TIMER_4_STOP_AND_CLEAR
;
IFS1bits
.
T4IF
=
0
;
//if the interruption have occured for some magic reason, or
//obviously deficient programming skill of mine, it should remove
//any uterly bad effect
dma_sbcp
.
bus_rx_error
&=
~
(
SBCP_COM_ERROR_CODE_BUS_TIMEOUT
);
break
;
}
default
:
break
;
}
//clear the interrupt flag !
IFS0bits
.
DMA0IF
=
0
;
}
//Transfer is completely in UART Queue
void
__attribute__
((
__interrupt__
,
no_auto_psv
))
_DMA1Interrupt
(
void
){
U1STAbits
.
UTXISEL0
=
1
;
//stop only when all operation are finished
//clear any pending flags (which is set BTW)
IFS0bits
.
U1TXIF
=
0
;
//enable TX interrupt to detect when trnasfer is actually finished (not just in queue)
IEC0bits
.
U1TXIE
=
1
;
//clear the interrupt flag !
IFS0bits
.
DMA1IF
=
0
;
}
void
__attribute__
((
__interrupt__
,
no_auto_psv
))
_U1TXInterrupt
(
void
)
{
/*
while(!(U1STAbits.TRMT)){
Nop();
}
*/
PORT_RS485_DRIVER_DISABLE
;
PORT_RS485_RECEIVER_ENABLE
;
//here all Tx operations are done
//We start the reset of the UART. indeed , UART has been of for a time now
//so a OERR could have occur, this is safer for two instructions !
U1MODEbits
.
UARTEN
=
0
;
//disabled.
U1STAbits
.
UTXEN
=
0
;
//we switch the port back to Rx mode
// TODO we may need to re-enable Tx ! check doc for this !
// TODO check the error handling code too !
DMA_INIT_BUS_RX
;
//now reception is OK !
sbcp
.
bus_tx_flags
=
SBCP_TX_BUFFER_FREE
;
IEC0bits
.
U1TXIE
=
0
;
//disable interrut
U1STAbits
.
UTXISEL0
=
0
;
//Interrupt every char
IFS0bits
.
U1TXIF
=
0
;
//clear interrupt !
U1MODEbits
.
UARTEN
=
1
;
//resetted, buffer are now empty !
U1STAbits
.
UTXEN
=
1
;
};
void
dma_sbcp_init
(){
//initialize data
dma_sbcp
.
bus_uart_error_enable_flags
=
DMA_UART_ALL_ERRORS_DISABLED
;
dma_sbcp
.
bus_rx_state
=
DMA_WAIT_FOR_HEADER_BYTE
;
DMA_PACKET_QUEUE_SET_EMPTY
(
dma_sbcp
.
bus_rx_queue
);
dma_sbcp
.
bus_rx_error
=
0
;
//initialize DMA 0 for BUS RX
DMA0CONbits
.
SIZE
=
0
;
// use word
DMA0CONbits
.
DIR
=
0
;
// from peripherical to RAM
DMA0CONbits
.
HALF
=
0
;
// inetrrupt after all receive
DMA0CONbits
.
NULLW
=
0
;
// non null write
DMA0CONbits
.
AMODE
=
0
;
//indirect register with post increment
DMA0CONbits
.
MODE
=
1
;
//One shot, no ping pong
DMA0CNT
=
0
;
//1 transfers
DMA0PAD
=
(
volatile
unsigned
int
)
&
U1RXREG
;
DMA0STA
=
DMA_PACKET_QUEUE_BUS_GET_DMA
(
dma_sbcp
.
bus_rx_queue
.
tail
);
DMA0REQ
=
0x000b
;
//UART 1 RX irq
IFS0bits
.
DMA0IF
=
0
;
//clear DMA interrupt flag
IEC0bits
.
DMA0IE
=
1
;
//enable dmao interrupt
DMA0CONbits
.
CHEN
=
0
;
//enable channel 0
//activate DMA 0
//initialize DMA 1 for BUS TX
DMA1CONbits
.
SIZE
=
0
;
//use word
DMA1CONbits
.
DIR
=
1
;
//from RAM to periph
DMA1CONbits
.
HALF
=
0
;
//interrupt after all received char
DMA1CONbits
.
NULLW
=
0
;
//normal mode
DMA1CONbits
.
AMODE
=
0
;
//indirect register with post increment
DMA1CONbits
.
MODE
=
1
;
//One shot, no ping pong
DMA1CNT
=
0
;
//1 byte, should be overrwriten when launching
DMA1PAD
=
(
volatile
unsigned
int
)
&
U1TXREG
;
DMA1STA
=
DMA_PACKET_QUEUE_BUS_TX_BUFFER_DMA
;
//should be overwritten when launching
DMA1REQ
=
0x000c
;
//UART 1 TX IRQ
IFS0bits
.
DMA1IF
=
0
;
//clear DMA interrupt flag
IEC0bits
.
DMA1IE
=
1
;
//ENABLE DMA1 INTERRUPT !!!!
//DISABLE CHANNEL, WILL BE CONFIGURED AND ENABLED WHEN NEEDED
DMA1CONbits
.
CHEN
=
0
;
PORT_RS485_RECEIVER_ENABLE
;
PORT_RS485_DRIVER_DISABLE
;
//we disable the frame error detection while waiting for the header byte
//in case the terminal resistor is not put on the bus.
//DMA_BUS_DISABLE_ERR_DETECTION;
DMA_INIT_BUS_RX
;
}
Event Timeline
Log In to Comment