OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [CORTEX_LM3S811_GCC/] [hw_include/] [ssi.c] - Blame information for rev 591

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 581 jeremybenn
//*****************************************************************************
2
//
3
// ssi.c - Driver for Synchronous Serial Interface.
4
//
5
// Copyright (c) 2005,2006 Luminary Micro, Inc.  All rights reserved.
6
//
7
// Software License Agreement
8
//
9
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
10
// exclusively on LMI's Stellaris Family of microcontroller products.
11
//
12
// The software is owned by LMI and/or its suppliers, and is protected under
13
// applicable copyright laws.  All rights are reserved.  Any use in violation
14
// of the foregoing restrictions may subject the user to criminal sanctions
15
// under applicable laws, as well as to civil liability for the breach of the
16
// terms and conditions of this license.
17
//
18
// THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
19
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
20
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
21
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
22
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
23
//
24
// This is part of revision 991 of the Stellaris Driver Library.
25
//
26
//*****************************************************************************
27
 
28
//*****************************************************************************
29
//
30
//! \addtogroup ssi_api
31
//! @{
32
//
33
//*****************************************************************************
34
 
35
#include "../hw_ints.h"
36
#include "../hw_memmap.h"
37
#include "../hw_ssi.h"
38
#include "../hw_types.h"
39
#include "debug.h"
40
#include "interrupt.h"
41
#include "ssi.h"
42
#include "sysctl.h"
43
 
44
//*****************************************************************************
45
//
46
//! Configures the synchronous serial interface.
47
//!
48
//! \param ulBase specifies the SSI module base address.
49
//! \param ulProtocol specifies the data transfer protocol.
50
//! \param ulMode specifies the mode of operation.
51
//! \param ulBitRate specifies the clock rate.
52
//! \param ulDataWidth specifies number of bits transfered per frame.
53
//!
54
//! This function configures the synchronous serial interface. It sets
55
//! the SSI protocol, mode of operation, bit rate, and data width.
56
//!
57
//! The parameter \e ulProtocol defines the data frame format. The parameter
58
//! \e ulProtocol can be one of the following values: SSI_FRF_MOTO_MODE_0,
59
//! SSI_FRF_MOTO_MODE_1, SSI_FRF_MOTO_MODE_2, SSI_FRF_MOTO_MODE_3,
60
//! SSI_FRF_TI, or SSI_FRF_NMW. The Motorola frame formats imply the
61
//! following polarity and phase configurations:
62
//! <pre>
63
//! Polarity Phase       Mode
64
//!   0       0   SSI_FRF_MOTO_MODE_0
65
//!   0       1   SSI_FRF_MOTO_MODE_1
66
//!   1       0   SSI_FRF_MOTO_MODE_2
67
//!   1       1   SSI_FRF_MOTO_MODE_3
68
//! </pre>
69
//!
70
//! The parameter \e ulMode defines the operating mode of the SSI module. The
71
//! SSI module can operate as a master or slave; if a slave, the SSI can be
72
//! configured to disable output on its serial output line. The parameter
73
//! \e ulMode can be one of the following values: SSI_MODE_MASTER,
74
//! SSI_MODE_SLAVE, or SSI_MODE_SLAVE_OD.
75
//!
76
//! The parameter \e ulBitRate defines the bit rate for the SSI. This bit rate
77
//! must satisfy the following clock ratio criteria:
78
//! - FSSI >= 2 * bit rate (master mode)
79
//! - FSSI >= 12 * bit rate (slave modes)
80
//!
81
//! where FSSI is the frequency of the clock supplied to the SSI module.
82
//!
83
//! The parameter \e ulDataWidth defines the width of the data transfers.
84
//! The parameter \e ulDataWidth can be a value between 4 and 16, inclusive.
85
//!
86
//! The SSI clocking is dependent upon the system clock rate returned by
87
//! SysCtlClockGet(); if it does not return the correct system clock rate then
88
//! the SSI clock rate will be incorrect.
89
//!
90
//! \return None.
91
//
92
//*****************************************************************************
93
#if defined(GROUP_config) || defined(BUILD_ALL) || defined(DOXYGEN)
94
void
95
SSIConfig(unsigned long ulBase, unsigned long ulProtocol, unsigned long ulMode,
96
          unsigned long ulBitRate, unsigned long ulDataWidth)
97
{
98
    unsigned long ulMaxBitRate;
99
    unsigned long ulRegVal;
100
    unsigned long ulPreDiv;
101
    unsigned long ulSCR;
102
    unsigned long ulSPH_SPO;
103
    unsigned long ulClock;
104
 
105
    //
106
    // Check the arguments.
107
    //
108
    ASSERT(ulBase == SSI_BASE);
109
    ASSERT((ulProtocol == SSI_FRF_MOTO_MODE_0) ||
110
           (ulProtocol == SSI_FRF_MOTO_MODE_1) ||
111
           (ulProtocol == SSI_FRF_MOTO_MODE_2) ||
112
           (ulProtocol == SSI_FRF_MOTO_MODE_3) ||
113
           (ulProtocol == SSI_FRF_TI) ||
114
           (ulProtocol == SSI_FRF_NMW));
115
    ASSERT((ulMode == SSI_MODE_MASTER) ||
116
           (ulMode == SSI_MODE_SLAVE) ||
117
           (ulMode == SSI_MODE_SLAVE_OD));
118
    ASSERT((ulDataWidth >= 4) && (ulDataWidth <= 16));
119
 
120
    //
121
    // Get the processor clock rate.
122
    //
123
    ulClock = SysCtlClockGet();
124
 
125
    //
126
    // Validate the clock speed.
127
    //
128
    ASSERT(((ulMode == SSI_MODE_MASTER) && (ulBitRate <= (ulClock / 2))) ||
129
           ((ulMode != SSI_MODE_MASTER) && (ulBitRate <= (ulClock / 12))));
130
    ASSERT((ulClock / ulBitRate) <= (254 * 256));
131
 
132
    //
133
    // Set the mode.
134
    //
135
    ulRegVal = (ulMode == SSI_MODE_SLAVE_OD) ? SSI_CR1_SOD : 0;
136
    ulRegVal |= (ulMode == SSI_MODE_MASTER) ? 0 : SSI_CR1_MS;
137
    HWREG(ulBase + SSI_O_CR1) = ulRegVal;
138
 
139
    //
140
    // Set the clock predivider.
141
    //
142
    ulMaxBitRate = ulClock / ulBitRate;
143
    ulPreDiv = 0;
144
    do
145
    {
146
        ulPreDiv += 2;
147
        ulSCR = (ulMaxBitRate / ulPreDiv) - 1;
148
    }
149
    while(ulSCR > 255);
150
    HWREG(ulBase + SSI_O_CPSR) = ulPreDiv;
151
 
152
    //
153
    // Set protocol and clock rate.
154
    //
155
    ulSPH_SPO = ulProtocol << 6;
156
    ulProtocol &= SSI_CR0_FRF_MASK;
157
    ulRegVal = (ulSCR << 8) | ulSPH_SPO | ulProtocol | (ulDataWidth - 1);
158
    HWREG(ulBase + SSI_O_CR0) = ulRegVal;
159
}
160
#endif
161
 
162
//*****************************************************************************
163
//
164
//! Enables the synchronous serial interface.
165
//!
166
//! \param ulBase specifies the SSI module base address.
167
//!
168
//! This will enable operation of the synchronous serial interface. It must be
169
//! configured before it is enabled.
170
//!
171
//! \return None.
172
//
173
//*****************************************************************************
174
#if defined(GROUP_enable) || defined(BUILD_ALL) || defined(DOXYGEN)
175
void
176
SSIEnable(unsigned long ulBase)
177
{
178
    //
179
    // Check the arguments.
180
    //
181
    ASSERT(ulBase == SSI_BASE);
182
 
183
    //
184
    // Read-modify-write the enable bit.
185
    //
186
    HWREG(ulBase + SSI_O_CR1) |= SSI_CR1_SSE;
187
}
188
#endif
189
 
190
//*****************************************************************************
191
//
192
//! Disables the synchronous serial interface.
193
//!
194
//! \param ulBase specifies the SSI module base address.
195
//!
196
//! This will disable operation of the synchronous serial interface.
197
//!
198
//! \return None.
199
//
200
//*****************************************************************************
201
#if defined(GROUP_disable) || defined(BUILD_ALL) || defined(DOXYGEN)
202
void
203
SSIDisable(unsigned long ulBase)
204
{
205
    //
206
    // Check the arguments.
207
    //
208
    ASSERT(ulBase == SSI_BASE);
209
 
210
    //
211
    // Read-modify-write the enable bit.
212
    //
213
    HWREG(ulBase + SSI_O_CR1) &= ~(SSI_CR1_SSE);
214
}
215
#endif
216
 
217
//*****************************************************************************
218
//
219
//! Registers an interrupt handler for the synchronous serial interface.
220
//!
221
//! \param ulBase specifies the SSI module base address.
222
//! \param pfnHandler is a pointer to the function to be called when the
223
//! synchronous serial interface interrupt occurs.
224
//!
225
//! This sets the handler to be called when an SSI interrupt
226
//! occurs.  This will enable the global interrupt in the interrupt controller;
227
//! specific SSI interrupts must be enabled via SSIIntEnable().  If necessary,
228
//! it is the interrupt handler's responsibility to clear the interrupt source
229
//! via SSIIntClear().
230
//!
231
//! \sa IntRegister() for important information about registering interrupt
232
//! handlers.
233
//!
234
//! \return None.
235
//
236
//*****************************************************************************
237
#if defined(GROUP_intregister) || defined(BUILD_ALL) || defined(DOXYGEN)
238
void
239
SSIIntRegister(unsigned long ulBase, void (*pfnHandler)(void))
240
{
241
    //
242
    // Check the arguments.
243
    //
244
    ASSERT(ulBase == SSI_BASE);
245
 
246
    //
247
    // Register the interrupt handler, returning an error if an error occurs.
248
    //
249
    IntRegister(INT_SSI, pfnHandler);
250
 
251
    //
252
    // Enable the synchronous serial interface interrupt.
253
    //
254
    IntEnable(INT_SSI);
255
}
256
#endif
257
 
258
//*****************************************************************************
259
//
260
//! Unregisters an interrupt handler for the synchronous serial interface.
261
//!
262
//! \param ulBase specifies the SSI module base address.
263
//!
264
//! This function will clear the handler to be called when a SSI
265
//! interrupt occurs.  This will also mask off the interrupt in the interrupt
266
//! controller so that the interrupt handler no longer is called.
267
//!
268
//! \sa IntRegister() for important information about registering interrupt
269
//! handlers.
270
//!
271
//! \return None.
272
//
273
//*****************************************************************************
274
#if defined(GROUP_intunregister) || defined(BUILD_ALL) || defined(DOXYGEN)
275
void
276
SSIIntUnregister(unsigned long ulBase)
277
{
278
    //
279
    // Check the arguments.
280
    //
281
    ASSERT(ulBase == SSI_BASE);
282
 
283
    //
284
    // Disable the interrupt.
285
    //
286
    IntDisable(INT_SSI);
287
 
288
    //
289
    // Unregister the interrupt handler.
290
    //
291
    IntUnregister(INT_SSI);
292
}
293
#endif
294
 
295
//*****************************************************************************
296
//
297
//! Enables individual SSI interrupt sources.
298
//!
299
//! \param ulBase specifies the SSI module base address.
300
//! \param ulIntFlags is a bit mask of the interrupt sources to be enabled.
301
//!
302
//! Enables the indicated SSI interrupt sources.  Only the sources that are
303
//! enabled can be reflected to the processor interrupt; disabled sources
304
//! have no effect on the processor.  The parameter \e ulIntFlags Can be
305
//! any of the SSI_TXFF, SSI_RXFF, SSI_RXTO, or SSI_RXOR values.
306
//!
307
//! \return None.
308
//
309
//*****************************************************************************
310
#if defined(GROUP_intenable) || defined(BUILD_ALL) || defined(DOXYGEN)
311
void
312
SSIIntEnable(unsigned long ulBase, unsigned long ulIntFlags)
313
{
314
    //
315
    // Check the arguments.
316
    //
317
    ASSERT(ulBase == SSI_BASE);
318
 
319
    //
320
    // Enable the specified interrupts.
321
    //
322
    HWREG(ulBase + SSI_O_IM) |= ulIntFlags;
323
}
324
#endif
325
 
326
//*****************************************************************************
327
//
328
//! Disables individual SSI interrupt sources.
329
//!
330
//! \param ulBase specifies the SSI module base address.
331
//! \param ulIntFlags is a bit mask of the interrupt sources to be disabled.
332
//!
333
//! Disables the indicated SSI interrupt sources. The parameter
334
//! \e ulIntFlags Can be any of the SSI_TXFF, SSI_RXFF, SSI_RXTO,
335
//! or SSI_RXOR values.
336
//!
337
//! \return None.
338
//
339
//*****************************************************************************
340
#if defined(GROUP_intdisable) || defined(BUILD_ALL) || defined(DOXYGEN)
341
void
342
SSIIntDisable(unsigned long ulBase, unsigned long ulIntFlags)
343
{
344
    //
345
    // Check the arguments.
346
    //
347
    ASSERT(ulBase == SSI_BASE);
348
 
349
    //
350
    // Disable the specified interrupts.
351
    //
352
    HWREG(ulBase + SSI_O_IM) &= ~(ulIntFlags);
353
}
354
#endif
355
 
356
//*****************************************************************************
357
//
358
//! Gets the current interrupt status.
359
//!
360
//! \param ulBase specifies the SSI module base address.
361
//! \param bMasked is false if the raw interrupt status is required and
362
//! true if the masked interrupt status is required.
363
//!
364
//! This returns the interrupt status for the SSI module.
365
//! Either the raw interrupt status or the status of interrupts that are
366
//! allowed to reflect to the processor can be returned.
367
//!
368
//! \return The current interrupt status, enumerated as a bit field of
369
//! SSI_TXFF, SSI_RXFF, SSI_RXTO, and SSI_RXOR.
370
//
371
//*****************************************************************************
372
#if defined(GROUP_intstatus) || defined(BUILD_ALL) || defined(DOXYGEN)
373
unsigned long
374
SSIIntStatus(unsigned long ulBase, tBoolean bMasked)
375
{
376
    //
377
    // Check the arguments.
378
    //
379
    ASSERT(ulBase == SSI_BASE);
380
 
381
    //
382
    // Return either the interrupt status or the raw interrupt status as
383
    // requested.
384
    //
385
    if(bMasked)
386
    {
387
        return(HWREG(ulBase + SSI_O_MIS));
388
    }
389
    else
390
    {
391
        return(HWREG(ulBase + SSI_O_RIS));
392
    }
393
}
394
#endif
395
 
396
//*****************************************************************************
397
//
398
//! Clears SSI interrupt sources.
399
//!
400
//! \param ulBase specifies the SSI module base address.
401
//! \param ulIntFlags is a bit mask of the interrupt sources to be cleared.
402
//!
403
//! The specified SSI interrupt sources are cleared, so that
404
//! they no longer assert.  This must be done in the interrupt handler to
405
//! keep it from being called again immediately upon exit.
406
//! The parameter \e ulIntFlags can consist of either or both the SSI_RXTO
407
//! and SSI_RXOR values.
408
//!
409
//! \return None.
410
//
411
//*****************************************************************************
412
#if defined(GROUP_intclear) || defined(BUILD_ALL) || defined(DOXYGEN)
413
void
414
SSIIntClear(unsigned long ulBase, unsigned long ulIntFlags)
415
{
416
    //
417
    // Check the arguments.
418
    //
419
    ASSERT(ulBase == SSI_BASE);
420
 
421
    //
422
    // Clear the requested interrupt sources.
423
    //
424
    HWREG(ulBase + SSI_O_ICR) = ulIntFlags;
425
}
426
#endif
427
 
428
//*****************************************************************************
429
//
430
//! Puts a data element into the SSI transmit FIFO.
431
//!
432
//! \param ulBase specifies the SSI module base address.
433
//! \param ulData data to be transmitted over the SSI interface.
434
//!
435
//! This function will place the supplied data into the transmit FIFO of
436
//! the specified SSI module.
437
//!
438
//! \note The upper 32 - N bits of the \e ulData will be discarded by the
439
//! hardware, where N is the data width as configured by SSIConfig().  For
440
//! example, if the interface is configured for 8 bit data width, the upper 24
441
//! bits of \e ulData will be discarded.
442
//!
443
//! \return None.
444
//
445
//*****************************************************************************
446
#if defined(GROUP_dataput) || defined(BUILD_ALL) || defined(DOXYGEN)
447
void
448
SSIDataPut(unsigned long ulBase, unsigned long ulData)
449
{
450
    //
451
    // Check the arguments.
452
    //
453
    ASSERT(ulBase == SSI_BASE);
454
    ASSERT((ulData & (0xfffffffe << (HWREG(ulBase + SSI_O_CR0) &
455
                                     SSI_CR0_DSS))) == 0);
456
 
457
    //
458
    // Wait until there is space.
459
    //
460
    while(!(HWREG(ulBase + SSI_O_SR) & SSI_SR_TNF))
461
    {
462
    }
463
 
464
    //
465
    // Write the data to the SSI.
466
    //
467
    HWREG(ulBase + SSI_O_DR) = ulData;
468
}
469
#endif
470
 
471
//*****************************************************************************
472
//
473
//! Puts a data element into the SSI transmit FIFO.
474
//!
475
//! \param ulBase specifies the SSI module base address.
476
//! \param ulData data to be transmitted over the SSI interface.
477
//!
478
//! This function will place the supplied data into the transmit FIFO of
479
//! the specified SSI module. If there is no space in the FIFO, then this
480
//! function will return a zero.
481
//!
482
//! \note The upper 32 - N bits of the \e ulData will be discarded by the
483
//! hardware, where N is the data width as configured by SSIConfig().  For
484
//! example, if the interface is configured for 8 bit data width, the upper 24
485
//! bits of \e ulData will be discarded.
486
//!
487
//! \return Returns the number of elements written to the SSI transmit FIFO.
488
//
489
//*****************************************************************************
490
#if defined(GROUP_datanonblockingput) || defined(BUILD_ALL) || defined(DOXYGEN)
491
long
492
SSIDataNonBlockingPut(unsigned long ulBase, unsigned long ulData)
493
{
494
    //
495
    // Check the arguments.
496
    //
497
    ASSERT(ulBase == SSI_BASE);
498
    ASSERT((ulData & (0xfffffffe << (HWREG(ulBase + SSI_O_CR0) &
499
                                     SSI_CR0_DSS))) == 0);
500
 
501
    //
502
    // Check for space to write.
503
    //
504
    if(HWREG(ulBase + SSI_O_SR) & SSI_SR_TNF)
505
    {
506
        HWREG(ulBase + SSI_O_DR) = ulData;
507
        return(1);
508
    }
509
    else
510
    {
511
        return(0);
512
    }
513
}
514
#endif
515
 
516
//*****************************************************************************
517
//
518
//! Gets a data element from the SSI receive FIFO.
519
//!
520
//! \param ulBase specifies the SSI module base address.
521
//! \param pulData pointer to a storage location for data that was received
522
//! over the SSI interface.
523
//!
524
//! This function will get received data from the receive FIFO of the specified
525
//! SSI module, and place that data into the location specified by the
526
//! \e pulData parameter.
527
//!
528
//! \note Only the lower N bits of the value written to \e pulData will contain
529
//! valid data, where N is the data width as configured by SSIConfig().  For
530
//! example, if the interface is configured for 8 bit data width, only the
531
//! lower 8 bits of the value written to \e pulData will contain valid data.
532
//!
533
//! \return None.
534
//
535
//*****************************************************************************
536
#if defined(GROUP_dataget) || defined(BUILD_ALL) || defined(DOXYGEN)
537
void
538
SSIDataGet(unsigned long ulBase, unsigned long *pulData)
539
{
540
    //
541
    // Check the arguments.
542
    //
543
    ASSERT(ulBase == SSI_BASE);
544
 
545
    //
546
    // Wait until there is data to be read.
547
    //
548
    while(!(HWREG(ulBase + SSI_O_SR) & SSI_SR_RNE))
549
    {
550
    }
551
 
552
    //
553
    // Read data from SSI.
554
    //
555
    *pulData = HWREG(ulBase + SSI_O_DR);
556
}
557
#endif
558
 
559
//*****************************************************************************
560
//
561
//! Gets a data element from the SSI receive FIFO.
562
//!
563
//! \param ulBase specifies the SSI module base address.
564
//! \param pulData pointer to a storage location for data that was received
565
//! over the SSI interface.
566
//!
567
//! This function will get received data from the receive FIFO of
568
//! the specified SSI module, and place that data into the location specified
569
//! by the \e ulData parameter. If there is no data in the FIFO, then this
570
//! function will return a zero.
571
//!
572
//! \note Only the lower N bits of the value written to \e pulData will contain
573
//! valid data, where N is the data width as configured by SSIConfig().  For
574
//! example, if the interface is configured for 8 bit data width, only the
575
//! lower 8 bits of the value written to \e pulData will contain valid data.
576
//!
577
//! \return Returns the number of elements read from the SSI receive FIFO.
578
//
579
//*****************************************************************************
580
#if defined(GROUP_datanonblockingget) || defined(BUILD_ALL) || defined(DOXYGEN)
581
long
582
SSIDataNonBlockingGet(unsigned long ulBase, unsigned long *pulData)
583
{
584
   //
585
    // Check the arguments.
586
    //
587
    ASSERT(ulBase == SSI_BASE);
588
 
589
    //
590
    // Check for data to read.
591
    //
592
    if(HWREG(ulBase + SSI_O_SR) & SSI_SR_RNE)
593
    {
594
        *pulData = HWREG(ulBase + SSI_O_DR);
595
        return(1);
596
    }
597
    else
598
    {
599
        return(0);
600
    }
601
}
602
#endif
603
 
604
//*****************************************************************************
605
//
606
// Close the Doxygen group.
607
//! @}
608
//
609
//*****************************************************************************

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.