-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathSPISlave_T4.tpp
151 lines (126 loc) · 4.71 KB
/
SPISlave_T4.tpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include <SPISlave_T4.h>
#include "Arduino.h"
#include "SPI.h"
#define SLAVE_CR spiAddr[4]
#define SLAVE_FCR spiAddr[22]
#define SLAVE_IER spiAddr[6]
#define SLAVE_CFGR0 spiAddr[8]
#define SLAVE_CFGR1 spiAddr[9]
#define SLAVE_TDR spiAddr[25]
#define SLAVE_RDR spiAddr[29]
#define SLAVE_SR spiAddr[5]
#define SLAVE_TCR_REFRESH spiAddr[24] = (0UL << 27) | LPSPI_TCR_FRAMESZ(bits - 1)
#define SLAVE_PORT_ADDR volatile uint32_t *spiAddr = &(*(volatile uint32_t*)(0x40394000 + (0x4000 * _portnum)))
#define SLAVE_PINS_ADDR volatile uint32_t *spiAddr = &(*(volatile uint32_t*)(0x401F84EC + (_portnum * 0x10)))
void lpspi4_slave_isr() {
_LPSPI4->SLAVE_ISR();
}
SPISlave_T4_FUNC SPISlave_T4_OPT::SPISlave_T4() {
if ( port == &SPI ) {
_LPSPI4 = this;
_portnum = 3;
CCM_CCGR1 |= (3UL << 6);
nvic_irq = 32 + _portnum;
_VectorsRam[16 + nvic_irq] = lpspi4_slave_isr;
/* Alternate pins not broken out on Teensy 4.0/4.1 for LPSPI4 */
SLAVE_PINS_ADDR;
spiAddr[0] = 0; /* PCS0_SELECT_INPUT */
spiAddr[1] = 0; /* SCK_SELECT_INPUT */
spiAddr[2] = 0; /* SDI_SELECT_INPUT */
spiAddr[3] = 0; /* SDO_SELECT_INPUT */
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_03 = 0x3; /* LPSPI4 SCK (CLK) */
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_01 = 0x3; /* LPSPI4 SDI (MISO) */
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_02 = 0x3; /* LPSPI4 SDO (MOSI) */
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_00 = 0x3; /* LPSPI4 PCS0 (CS) */
}
}
SPISlave_T4_FUNC void SPISlave_T4_OPT::swapPins(bool enable) {
SLAVE_PORT_ADDR;
SLAVE_CR &= ~LPSPI_CR_MEN; /* Disable Module */
SLAVE_CFGR1 = (SLAVE_CFGR1 & 0xFCFFFFFF) | (enable) ? (3UL << 24) : (0UL << 24);
SLAVE_CR |= LPSPI_CR_MEN; /* Enable Module */
if ( sniffer_enabled ) sniffer();
}
SPISlave_T4_FUNC void SPISlave_T4_OPT::sniffer(bool enable) {
SLAVE_PORT_ADDR;
sniffer_enabled = enable;
if ( port == &SPI ) {
if ( sniffer_enabled ) {
if ( SLAVE_CFGR1 & (3UL << 24) ) { /* if pins are swapped */
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_03 = 0x3; /* LPSPI4 SCK (CLK) */
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_01 = 0x0; /* LPSPI4 SDI (MISO) */
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_02 = 0x3; /* LPSPI4 SDO (MOSI) */
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_00 = 0x3; /* LPSPI4 PCS0 (CS) */
}
else {
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_03 = 0x3; /* LPSPI4 SCK (CLK) */
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_01 = 0x3; /* LPSPI4 SDI (MISO) */
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_02 = 0x0; /* LPSPI4 SDO (MOSI) */
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_00 = 0x3; /* LPSPI4 PCS0 (CS) */
}
}
else {
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_03 = 0x3; /* LPSPI4 SCK (CLK) */
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_01 = 0x3; /* LPSPI4 SDI (MISO) */
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_02 = 0x3; /* LPSPI4 SDO (MOSI) */
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_00 = 0x3; /* LPSPI4 PCS0 (CS) */
}
}
}
SPISlave_T4_FUNC bool SPISlave_T4_OPT::active() {
SLAVE_PORT_ADDR;
return ( !(SLAVE_SR & (1UL << 9)) ) ? 1 : 0;
}
SPISlave_T4_FUNC bool SPISlave_T4_OPT::available() {
SLAVE_PORT_ADDR;
return ( (SLAVE_SR & (1UL << 8)) ) ? 1 : 0;
}
SPISlave_T4_FUNC void SPISlave_T4_OPT::pushr(uint32_t data) {
SLAVE_PORT_ADDR;
SLAVE_TDR = data;
}
SPISlave_T4_FUNC uint32_t SPISlave_T4_OPT::popr() {
SLAVE_PORT_ADDR;
uint32_t data = SLAVE_RDR;
SLAVE_SR = (1UL << 8); /* Clear WCF */
return data;
}
SPISlave_T4_FUNC void SPISlave_T4_OPT::SLAVE_ISR() {
SLAVE_PORT_ADDR;
if ( _spihandler ) {
_spihandler();
SLAVE_SR = 0x3F00;
asm volatile ("dsb");
return;
}
while ( !(SLAVE_SR & (1UL << 9)) ) { /* FCF: Frame Complete Flag, set when PCS deasserts */
if ( SLAVE_SR & (1UL << 11) ) { /* transmit error, clear flag, check cabling */
SLAVE_SR = (1UL << 11);
transmit_errors++;
}
if ( (SLAVE_SR & (1UL << 8)) ) { /* WCF set */
uint32_t val = SLAVE_RDR;
Serial.print(val); Serial.print(" ");
SLAVE_TDR = val;
SLAVE_SR = (1UL << 8); /* Clear WCF */
}
}
Serial.println();
SLAVE_SR = 0x3F00; /* Clear remaining flags on exit */
asm volatile ("dsb");
}
SPISlave_T4_FUNC void SPISlave_T4_OPT::begin() {
SLAVE_PORT_ADDR;
SLAVE_CR = LPSPI_CR_RST; /* Reset Module */
SLAVE_CR = 0; /* Disable Module */
SLAVE_FCR = 0;//x10001; /* 1x watermark for RX and TX */
SLAVE_IER = 0x1; /* RX Interrupt */
SLAVE_CFGR0 = 0;
SLAVE_CFGR1 = 0;
SLAVE_CR |= LPSPI_CR_MEN | LPSPI_CR_DBGEN; /* Enable Module, Debug Mode */
SLAVE_SR = 0x3F00; /* Clear status register */
SLAVE_TCR_REFRESH;
SLAVE_TDR = 0x0; /* dummy data, must populate initial TX slot */
NVIC_ENABLE_IRQ(nvic_irq);
NVIC_SET_PRIORITY(nvic_irq, 1);
}