Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
A
Arduino Core for SAMD21 CPU
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
josc941e
Arduino Core for SAMD21 CPU
Commits
cb722cfd
Commit
cb722cfd
authored
9 years ago
by
Claudio Indellicati
Committed by
Claudio Indellicati
9 years ago
Browse files
Options
Downloads
Patches
Plain Diff
Implemented SPI Transaction API.
parent
730ff493
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
libraries/SPI/SPI.cpp
+80
-13
80 additions, 13 deletions
libraries/SPI/SPI.cpp
libraries/SPI/SPI.h
+41
-14
41 additions, 14 deletions
libraries/SPI/SPI.h
with
121 additions
and
27 deletions
libraries/SPI/SPI.cpp
+
80
−
13
View file @
cb722cfd
/*
* SPI Master library for
a
rduino.
* Copyright (c) 201
4
Arduino
.
* SPI Master library for
A
rduino.
* Copyright (c) 201
5
Arduino
LLC
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either the GNU General Public License version 2
...
...
@@ -13,8 +13,15 @@
#include
"assert.h"
#include
"variant.h"
#define SPI_IMODE_NONE 0
#define SPI_IMODE_EXTINT 1
#define SPI_IMODE_GLOBAL 2
const
SPISettings
DEFAULT_SPI_SETTINGS
=
SPISettings
();
SPIClass
::
SPIClass
(
SERCOM
*
p_sercom
,
uint8_t
uc_pinMISO
,
uint8_t
uc_pinSCK
,
uint8_t
uc_pinMOSI
)
{
initialized
=
false
;
assert
(
p_sercom
!=
NULL
);
_p_sercom
=
p_sercom
;
...
...
@@ -25,14 +32,32 @@ SPIClass::SPIClass(SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint
void
SPIClass
::
begin
()
{
init
();
// PIO init
pinPeripheral
(
_uc_pinMiso
,
g_APinDescription
[
_uc_pinMiso
].
ulPinType
);
pinPeripheral
(
_uc_pinSCK
,
g_APinDescription
[
_uc_pinSCK
].
ulPinType
);
pinPeripheral
(
_uc_pinMosi
,
g_APinDescription
[
_uc_pinMosi
].
ulPinType
);
// Default speed set to 4Mhz, SPI mode set to MODE 0 and Bit order set to MSB first.
_p_sercom
->
initSPI
(
SPI_PAD_2_SCK_3
,
SERCOM_RX_PAD_0
,
SPI_CHAR_SIZE_8_BITS
,
MSB_FIRST
);
_p_sercom
->
initSPIClock
(
SERCOM_SPI_MODE_0
,
4000000
);
config
(
DEFAULT_SPI_SETTINGS
);
}
void
SPIClass
::
init
()
{
if
(
initialized
)
return
;
interruptMode
=
SPI_IMODE_NONE
;
interruptSave
=
0
;
interruptMask
=
0
;
initialized
=
true
;
}
void
SPIClass
::
config
(
SPISettings
settings
)
{
_p_sercom
->
disableSPI
();
_p_sercom
->
initSPI
(
SPI_PAD_2_SCK_3
,
SERCOM_RX_PAD_0
,
SPI_CHAR_SIZE_8_BITS
,
settings
.
bitOrder
);
_p_sercom
->
initSPIClock
(
settings
.
dataMode
,
settings
.
clockFreq
);
_p_sercom
->
enableSPI
();
}
...
...
@@ -40,25 +65,67 @@ void SPIClass::begin()
void
SPIClass
::
end
()
{
_p_sercom
->
resetSPI
();
initialized
=
false
;
}
#ifndef interruptsStatus
#define interruptsStatus() __interruptsStatus()
static
inline
unsigned
char
__interruptsStatus
(
void
)
__attribute__
((
always_inline
,
unused
));
static
inline
unsigned
char
__interruptsStatus
(
void
)
{
// See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/CHDBIBGJ.html
return
(
__get_PRIMASK
()
?
0
:
1
);
}
#endif
void
SPIClass
::
usingInterrupt
(
u
int
8_t
interruptNumber
)
void
SPIClass
::
usingInterrupt
(
int
interruptNumber
)
{
// XXX: TODO
if
((
interruptNumber
==
NOT_AN_INTERRUPT
)
||
(
interruptNumber
==
EXTERNAL_INT_NMI
))
return
;
uint8_t
irestore
=
interruptsStatus
();
noInterrupts
();
if
(
interruptNumber
>=
EXTERNAL_NUM_INTERRUPTS
)
interruptMode
=
SPI_IMODE_GLOBAL
;
else
{
interruptMode
|=
SPI_IMODE_EXTINT
;
interruptMask
|=
(
1
<<
interruptNumber
);
}
if
(
irestore
)
interrupts
();
}
void
SPIClass
::
beginTransaction
(
SPISettings
settings
)
{
// XXX: TODO
setBitOrder
(
settings
.
bitOrder
);
setClockDivider
(
settings
.
clockDiv
);
setDataMode
(
settings
.
dataMode
);
if
(
interruptMode
!=
SPI_IMODE_NONE
)
{
if
(
interruptMode
&
SPI_IMODE_GLOBAL
)
{
interruptSave
=
interruptsStatus
();
noInterrupts
();
}
else
if
(
interruptMode
&
SPI_IMODE_EXTINT
)
EIC
->
INTENCLR
.
reg
=
EIC_INTENCLR_EXTINT
(
interruptMask
);
}
config
(
settings
);
}
void
SPIClass
::
endTransaction
(
void
)
{
// XXX: TODO
if
(
interruptMode
!=
SPI_IMODE_NONE
)
{
if
(
interruptMode
&
SPI_IMODE_GLOBAL
)
{
if
(
interruptSave
)
interrupts
();
}
else
if
(
interruptMode
&
SPI_IMODE_EXTINT
)
EIC
->
INTENSET
.
reg
=
EIC_INTENSET_EXTINT
(
interruptMask
);
}
}
void
SPIClass
::
setBitOrder
(
BitOrder
order
)
...
...
@@ -110,7 +177,7 @@ byte SPIClass::transfer(uint8_t data)
_p_sercom
->
writeDataSPI
(
data
);
// Read data
return
_p_sercom
->
readDataSPI
();
return
_p_sercom
->
readDataSPI
()
&
0xFF
;
}
void
SPIClass
::
attachInterrupt
()
{
...
...
This diff is collapsed.
Click to expand it.
libraries/SPI/SPI.h
+
41
−
14
View file @
cb722cfd
/*
* SPI Master library for Arduino.
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
*
SPI Master library for a
rduino
.
*
Copyright (c) 2015 A
rduino
LLC
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either the GNU General Public License version 2
...
...
@@ -13,6 +14,13 @@
#include
<Arduino.h>
// SPI_HAS_TRANSACTION means SPI has
// - beginTransaction()
// - endTransaction()
// - usingInterrupt()
// - SPISetting(clock, bitOrder, dataMode)
#define SPI_HAS_TRANSACTION 1
#define SPI_MODE0 0x02
#define SPI_MODE1 0x00
#define SPI_MODE2 0x03
...
...
@@ -38,6 +46,7 @@ class SPISettings {
}
}
// Default speed set to 4MHz, SPI mode set to MODE 0 and Bit order set to MSB first.
SPISettings
()
{
init_AlwaysInline
(
4000000
,
MSBFIRST
,
SPI_MODE0
);
}
private
:
...
...
@@ -46,21 +55,32 @@ class SPISettings {
}
void
init_AlwaysInline
(
uint32_t
clock
,
BitOrder
bitOrder
,
uint8_t
dataMode
)
__attribute__
((
__always_inline__
))
{
uint8_t
div
;
if
(
clock
<
(
F_CPU
/
255
))
{
div
=
255
;
}
else
if
(
clock
>=
(
F_CPU
/
SPI_MIN_CLOCK_DIVIDER
))
{
div
=
SPI_MIN_CLOCK_DIVIDER
;
}
else
{
div
=
(
F_CPU
/
(
clock
+
1
))
+
1
;
this
->
clockFreq
=
(
clock
>=
(
F_CPU
/
SPI_MIN_CLOCK_DIVIDER
)
?
F_CPU
/
SPI_MIN_CLOCK_DIVIDER
:
clock
);
this
->
bitOrder
=
(
bitOrder
==
MSBFIRST
?
MSB_FIRST
:
LSB_FIRST
);
switch
(
dataMode
)
{
case
SPI_MODE0
:
this
->
dataMode
=
SERCOM_SPI_MODE_0
;
case
SPI_MODE1
:
this
->
dataMode
=
SERCOM_SPI_MODE_1
;
case
SPI_MODE2
:
this
->
dataMode
=
SERCOM_SPI_MODE_2
;
case
SPI_MODE3
:
this
->
dataMode
=
SERCOM_SPI_MODE_3
;
default:
this
->
dataMode
=
SERCOM_SPI_MODE_0
;
}
this
->
clockDiv
=
div
;
this
->
dataMode
=
dataMode
;
this
->
bitOrder
=
bitOrder
;
}
uint8_t
clockDiv
,
dataMode
;
BitOrder
bitOrder
;
uint32_t
clockFreq
;
SercomSpiClockMode
dataMode
;
SercomDataOrder
bitOrder
;
friend
class
SPIClass
;
};
...
...
@@ -73,7 +93,7 @@ class SPIClass {
inline
void
transfer
(
void
*
buf
,
size_t
count
);
// Transaction Functions
void
usingInterrupt
(
u
int
8_t
interruptNumber
);
void
usingInterrupt
(
int
interruptNumber
);
void
beginTransaction
(
SPISettings
settings
);
void
endTransaction
(
void
);
...
...
@@ -89,10 +109,17 @@ class SPIClass {
void
setClockDivider
(
uint8_t
uc_div
);
private:
void
init
();
void
config
(
SPISettings
settings
);
SERCOM
*
_p_sercom
;
uint8_t
_uc_pinMiso
;
uint8_t
_uc_pinMosi
;
uint8_t
_uc_pinSCK
;
bool
initialized
;
uint8_t
interruptMode
;
char
interruptSave
;
uint32_t
interruptMask
;
};
void
SPIClass
::
transfer
(
void
*
buf
,
size_t
count
)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment