RasPi Direct Hardware Access
Integrated peripheral access without operating system drivers.
 All Data Structures Files Functions Variables Typedefs Enumerations Macros Groups Pages
spisl.h
Go to the documentation of this file.
1 
67 #ifndef RASPI_SPISL_H
68 #define RASPI_SPISL_H
69 
70 #include "raspi/hw.h"
71 #include <stdint.h>
72 
73 
75 static inline void spisl_init()
76 {
77  int i;
78 
79  struct raspi_PCM_CS_reg init_cs = {
80  .TXCLR = 1,
81  .RXCLR = 1,
82  .TXERR = 1,
83  .RXERR = 1,
84  .TXON = 1,
85  .RXON = 1,
86  .SYNC = 1,
87  .STBY = 1,
88  .EN = 1,
89  };
90 
91  const struct raspi_PCM_MODE_reg mode_master = {
92  .FLEN = 7,
93  .FSLEN = 7,
94  .CLKM = 0,
95  .CLKI = 0,
96  .FSM = 0,
97  .FSI = 0,
98  .CLK_DIS = 1,
99  };
100 
101  const struct raspi_PCM_MODE_reg mode_slave = {
102  .FLEN = 7,
103  .FSLEN = 7,
104  .CLKM = 1,
105  .CLKI = 0,
106  .FSM = 1,
107  .FSI = 1,
108  .CLK_DIS = 1,
109  };
110 
111  const struct raspi_CM_CTL_reg pcm_cm_ctl = {
112  .PASSWD = CM_PASSWD,
113  .SRC = CM_OSC,
114  .MASH = 1,
115  .ENAB = 1,
116  };
117 
118  const struct raspi_CM_DIV_reg pcm_cm_div = {
119  .PASSWD = CM_PASSWD,
120  .DIVI = 250,
121  };
122 
123  // disable interface for reconfiguration
124  for (i = 28; i <= 31; i++) gpio_configure(i, Input);
125  memory_barrier();
126 
127  // empty FIFO
128  while (HW.PCM.CS.B.RXD) (void)HW.PCM.FIFO;
129 
130  // disable module to reset all parameters
131  HW.PCM.CS.B.EN = 0;
132  st_delay(ST_1ms);
133 
134  // set desired transmission parameters
135  HW.PCM.RXC.U = 0;
136  HW.PCM.TXC.U = 0;
137  HW.PCM.INTEN.U = 0;
138  HW.PCM.INTSTC.U = 15;
139  HW.PCM.GRAY.U = 0;
140 
141  HW.PCM.RXC.B.CH1WEX = 0;
142  HW.PCM.RXC.B.CH1POS = 0;
143  HW.PCM.RXC.B.CH1WID = 0;
144  HW.PCM.RXC.B.CH1EN = 1;
145 
146  HW.PCM.TXC.B.CH1WEX = 0;
147  HW.PCM.TXC.B.CH1POS = 0;
148  HW.PCM.TXC.B.CH1WID = 0;
149  HW.PCM.TXC.B.CH1EN = 1;
150 
151  // execute reset sequence
152  HW.CM[CM_PCM].DIV.B = pcm_cm_div;
153  HW.CM[CM_PCM].CTL.B = pcm_cm_ctl;
154  HW.PCM.MODE.B = mode_master;
155  HW.PCM.MODE.B.CLK_DIS = 0;
156  HW.PCM.CS.B = init_cs;
157 
158  while (!HW.PCM.CS.B.SYNC);
159  HW.PCM.CS.B.SYNC = 0;
160  while (HW.PCM.CS.B.SYNC);
161 
162  // configure slave mode and attach external interface
163  HW.PCM.MODE.B.CLK_DIS = 1;
164  HW.PCM.MODE.B = mode_slave;
165 
166  memory_barrier();
167  gpio_configure(28, Alt2);
168  gpio_configure(29, Alt2);
169  gpio_configure(30, Alt2);
170  gpio_configure(31, Alt2);
171  memory_barrier();
172 
173  HW.PCM.MODE.B.CLK_DIS = 0;
174 
175  memory_barrier();
176 }
177 
178 
182 static inline int spisl_poll(int num)
183 {
184  if (num <= 0) return 1;
185  return HW.PCM.CS.B.RXD;
186 }
187 
188 
190 static inline uint8_t spisl_read(void)
191 {
192  while (!HW.PCM.CS.B.RXD);
193  return HW.PCM.FIFO;
194 }
195 
196 
200 static inline void spisl_write(uint8_t data)
201 {
202  uint8_t dummy;
203  while (!HW.PCM.CS.B.TXD);
204  HW.PCM.FIFO = data;
205  while (HW.PCM.CS.B.RXD) dummy = HW.PCM.FIFO;
206  (void)dummy;
207 }
208 
209 
211 static inline void spisl_flush()
212 {
213  while (!HW.PCM.CS.B.TXE);
214 }
215 
216 
217 
233 static inline void spisl_synchronize(void)
234 {
235  uint8_t marker = 0x81;
236  uint8_t incoming;
237  int cnt = 0;
238 
239  incoming = spisl_read();
240  while (cnt++ < 10) {
241  if (incoming != marker) {
242  HW.PCM.MODE.B.CLK_DIS = 1;
243  st_delay(ST_1us);
244  cnt = 0;
245  HW.PCM.MODE.B.CLK_DIS = 0;
246  }
247  incoming = spisl_read();
248  }
249 
250  spisl_write(marker);
251 
252  marker ^= 0xff;
253 
254  while (incoming != marker) incoming = spisl_read();
255 }
256 
257 #endif
258