Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
Skyward Boardcore
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Giulia Facchi
Skyward Boardcore
Commits
be295624
Commit
be295624
authored
2 years ago
by
Federico Lolli
Browse files
Options
Downloads
Patches
Plain Diff
added initial files and updated cmake
parent
0e5f4d79
Branches
parafoil-f103-SDlog
No related tags found
No related merge requests found
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
cmake/boardcore.cmake
+1
-0
1 addition, 0 deletions
cmake/boardcore.cmake
src/shared/drivers/sdspi/sdspi.cpp
+601
-0
601 additions, 0 deletions
src/shared/drivers/sdspi/sdspi.cpp
src/shared/drivers/sdspi/sdspi.h
+52
-0
52 additions, 0 deletions
src/shared/drivers/sdspi/sdspi.h
with
654 additions
and
0 deletions
cmake/boardcore.cmake
+
1
−
0
View file @
be295624
...
@@ -55,6 +55,7 @@ foreach(OPT_BOARD ${BOARDS})
...
@@ -55,6 +55,7 @@ foreach(OPT_BOARD ${BOARDS})
${
SBS_BASE
}
/src/shared/drivers/timer/PWM.cpp
${
SBS_BASE
}
/src/shared/drivers/timer/PWM.cpp
${
SBS_BASE
}
/src/shared/drivers/timer/TimestampTimer.cpp
${
SBS_BASE
}
/src/shared/drivers/timer/TimestampTimer.cpp
${
SBS_BASE
}
/src/shared/drivers/runcam/Runcam.cpp
${
SBS_BASE
}
/src/shared/drivers/runcam/Runcam.cpp
${
SBS_BASE
}
/src/shared/drivers/sdspi/sdspi.cpp
${
SBS_BASE
}
/src/shared/drivers/spi/SPITransaction.cpp
${
SBS_BASE
}
/src/shared/drivers/spi/SPITransaction.cpp
${
SBS_BASE
}
/src/shared/drivers/usart/USART.cpp
${
SBS_BASE
}
/src/shared/drivers/usart/USART.cpp
${
SBS_BASE
}
/src/shared/drivers/i2c/I2CDriver.cpp
${
SBS_BASE
}
/src/shared/drivers/i2c/I2CDriver.cpp
...
...
This diff is collapsed.
Click to expand it.
src/shared/drivers/sdspi/sdspi.cpp
0 → 100644
+
601
−
0
View file @
be295624
/* Copyright (c) 2023 Skyward Experimental Rocketry
* Authors: Federico Lolli
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include
<miosix.h>
#include
<cstdio>
#include
<errno.h>
//Note: enabling debugging might cause deadlock when using sleep() or reboot()
//The bug won't be fixed because debugging is only useful for driver development
///\internal Debug macro, for normal conditions
//#define DBG iprintf
#define DBG(x,...) do {} while(0)
///\internal Debug macro, for errors only
//#define DBGERR iprintf
#define DBGERR(x,...) do {} while(0)
namespace
miosix
{
///\internal Type of card (1<<0)=MMC (1<<1)=SDv1 (1<<2)=SDv2 (1<<2)|(1<<3)=SDHC
static
unsigned
char
cardType
=
0
;
/*
* Definitions for MMC/SDC command.
* A command has the following format:
* - 1 bit @ 0 (start bit)
* - 1 bit @ 1 (transmission bit)
* - 6 bit which identify command index (CMD0..CMD63)
* - 32 bit command argument
* - 7 bit CRC
* - 1 bit @ 1 (end bit)
* In addition, ACMDxx are the sequence of two commands, CMD55 and CMDxx
* These constants have the following meaninig:
* - bit #7 @ 1 indicates that it is an ACMD. send_cmd() will send CMD55, then
* clear this bit and send the command with this bit @ 0 (which is start bit)
* - bit #6 always @ 1, because it is the transmission bit
* - remaining 6 bit represent command index
*/
#define CMD0 (0x40+0)
/* GO_IDLE_STATE */
#define CMD1 (0x40+1)
/* SEND_OP_COND (MMC) */
#define ACMD41 (0xC0+41)
/* SEND_OP_COND (SDC) */
#define CMD8 (0x40+8)
/* SEND_IF_COND */
#define CMD9 (0x40+9)
/* SEND_CSD */
#define CMD10 (0x40+10)
/* SEND_CID */
#define CMD12 (0x40+12)
/* STOP_TRANSMISSION */
#define CMD13 (0x40+13)
/* SEND_STATUS */
#define ACMD13 (0xC0+13)
/* SD_STATUS (SDC) */
#define CMD16 (0x40+16)
/* SET_BLOCKLEN */
#define CMD17 (0x40+17)
/* READ_SINGLE_BLOCK */
#define CMD18 (0x40+18)
/* READ_MULTIPLE_BLOCK */
#define CMD23 (0x40+23)
/* SET_BLOCK_COUNT (MMC) */
#define ACMD23 (0xC0+23)
/* SET_WR_BLK_ERASE_COUNT (SDC) */
#define CMD24 (0x40+24)
/* WRITE_BLOCK */
#define CMD25 (0x40+25)
/* WRITE_MULTIPLE_BLOCK */
#define CMD42 (0x40+42)
/* LOCK_UNLOCK */
#define CMD55 (0x40+55)
/* APP_CMD */
#define CMD58 (0x40+58)
/* READ_OCR */
// SSPCR0 Bit-Definitions
#define CPOL 6
#define CPHA 7
// SSPCR1 Bit-Defintions
#define SSE 1
#define MS 2
#define SCR 8
// SSPSR Bit-Definitions
#define TNF 1
#define RNE 2
#define BSY 4
#define SPI_SCK_PIN 17 // SCK P0.17 out
#define SPI_MISO_PIN 18 // MISO P0.18 in
#define SPI_MOSI_PIN 19 // MOSI P0.19 out
#define SPI_SS_PIN 20 // CS p0.20 out
#define SPI_SCK_FUNCBIT 2
#define SPI_MISO_FUNCBIT 4
#define SPI_MOSI_FUNCBIT 6
#define SPI_SS_FUNCBIT 8
///\internal Maximum speed 14745600/2=7372800
#define SPI_PRESCALE_MIN 2
///\internal Select/unselect card
#define CS_LOW() IOCLR0 = (1<<SPI_SS_PIN)
#define CS_HIGH() IOSET0 = (1<<SPI_SS_PIN)
//Function prototypes
static
unsigned
char
send_cmd
(
unsigned
char
cmd
,
unsigned
int
arg
);
/**
* \internal
* Initialize SPI
*/
static
void
spi_1_init
()
{
unsigned
char
incoming
;
PCONP
|=
(
1
<<
10
);
//Enable SPI1
// setup GPIO
IODIR0
|=
(
1
<<
SPI_SCK_PIN
)
|
(
1
<<
SPI_MOSI_PIN
)
|
(
1
<<
SPI_SS_PIN
);
IODIR0
&=
~
(
1
<<
SPI_MISO_PIN
);
// Unselect card
CS_HIGH
();
// Set GPIO mode
PINSEL1
&=
~
(
(
3
<<
SPI_SCK_FUNCBIT
)
|
(
3
<<
SPI_MISO_FUNCBIT
)
|
(
3
<<
SPI_MOSI_FUNCBIT
)
|
(
3
<<
SPI_SS_FUNCBIT
)
);
// setup Pin-Functions - keep automatic CS disabled during init
PINSEL1
|=
(
(
2
<<
SPI_SCK_FUNCBIT
)
|
(
2
<<
SPI_MISO_FUNCBIT
)
|
(
2
<<
SPI_MOSI_FUNCBIT
)
);
// enable SPI-Master - slowest speed
SSPCR0
=
((
8
-
1
)
<<
0
)
|
(
0
<<
CPOL
)
|
(
0x20
<<
SCR
);
SSPCR1
=
(
1
<<
SSE
);
// low speed during init
SSPCPSR
=
254
;
// Send 20 spi commands with card not selected
for
(
int
i
=
0
;
i
<
20
;
i
++
)
{
while
(
!
(
SSPSR
&
(
1
<<
TNF
))
)
;
//Wait
SSPDR
=
0xff
;
while
(
!
(
SSPSR
&
(
1
<<
RNE
))
)
;
//Wait
incoming
=
SSPDR
;
(
void
)
incoming
;
}
}
/**
* \internal
* Send and receive one byte through SPI
*/
static
unsigned
char
spi_1_send
(
unsigned
char
outgoing
)
{
while
(
!
(
SSPSR
&
(
1
<<
TNF
)))
;
SSPDR
=
outgoing
;
while
(
!
(
SSPSR
&
(
1
<<
RNE
)))
;
return
SSPDR
;
}
/**
* \internal
* Used for debugging, print 8 bit error code from SD card
*/
static
void
print_error_code
(
unsigned
char
value
)
{
switch
(
value
)
{
case
0x40
:
DBGERR
(
"Parameter error
\n
"
);
break
;
case
0x20
:
DBGERR
(
"Address error
\n
"
);
break
;
case
0x10
:
DBGERR
(
"Erase sequence error
\n
"
);
break
;
case
0x08
:
DBGERR
(
"CRC error
\n
"
);
break
;
case
0x04
:
DBGERR
(
"Illegal command
\n
"
);
break
;
case
0x02
:
DBGERR
(
"Erase reset
\n
"
);
break
;
case
0x01
:
DBGERR
(
"Card is initializing
\n
"
);
break
;
default:
DBGERR
(
"Unknown error 0x%x
\n
"
,
value
);
break
;
}
}
/**
* \internal
* Return 1 if card is OK, otherwise print 16 bit error code from SD card
*/
static
char
sd_status
()
{
short
value
=
send_cmd
(
CMD13
,
0
);
value
<<=
8
;
value
|=
spi_1_send
(
0xff
);
switch
(
value
)
{
case
0x0000
:
return
1
;
case
0x0001
:
DBGERR
(
"Card is Locked
\n
"
);
/*//Try to fix the problem by erasing all the SD card.
char e=send_cmd(CMD16,1);
if(e!=0) print_error_code(e);
e=send_cmd(CMD42,0);
if(e!=0) print_error_code(e);
spi_1_send(0xfe); // Start block
spi_1_send(1<<3); //Erase all disk command
spi_1_send(0xff); // Checksum part 1
spi_1_send(0xff); // Checksum part 2
e=spi_1_send(0xff);
iprintf("Reached here 0x%x\n",e);//Should return 0xe5
while(spi_1_send(0xff)!=0xff);*/
break
;
case
0x0002
:
DBGERR
(
"WP erase skip or lock/unlock cmd failed
\n
"
);
break
;
case
0x0004
:
DBGERR
(
"General error
\n
"
);
break
;
case
0x0008
:
DBGERR
(
"Internal card controller error
\n
"
);
break
;
case
0x0010
:
DBGERR
(
"Card ECC failed
\n
"
);
break
;
case
0x0020
:
DBGERR
(
"Write protect violation
\n
"
);
break
;
case
0x0040
:
DBGERR
(
"Invalid selection for erase
\n
"
);
break
;
case
0x0080
:
DBGERR
(
"Out of range or CSD overwrite
\n
"
);
break
;
default:
if
(
value
>
0x00FF
)
print_error_code
((
unsigned
char
)(
value
>>
8
));
else
DBGERR
(
"Unknown error 0x%x
\n
"
,
value
);
break
;
}
return
-
1
;
}
/**
* \internal
* Wait until card is ready
*/
static
unsigned
char
wait_ready
()
{
unsigned
char
result
;
spi_1_send
(
0xff
);
for
(
int
i
=
0
;
i
<
460800
;
i
++
)
//Timeout ~500ms
{
result
=
spi_1_send
(
0xff
);
if
(
result
==
0xff
)
return
0xff
;
if
(
i
%
500
==
0
)
DBG
(
"*
\n
"
);
}
DBGERR
(
"Error: wait_ready()
\n
"
);
return
result
;
}
/**
* \internal
* Send a command to the SD card
* \param cmd one among the #define'd commands
* \param arg command's argument
* \return command's r1 response. If command returns a longer response, the user
* can continue reading the response with spi_1_send(0xff)
*/
static
unsigned
char
send_cmd
(
unsigned
char
cmd
,
unsigned
int
arg
)
{
unsigned
char
n
,
res
;
if
(
cmd
&
0x80
)
{
// ACMD<n> is the command sequence of CMD55-CMD<n>
cmd
&=
0x7f
;
res
=
send_cmd
(
CMD55
,
0
);
if
(
res
>
1
)
return
res
;
}
// Select the card and wait for ready
CS_HIGH
();
CS_LOW
();
if
(
cmd
==
CMD0
)
{
//wait_ready on CMD0 seems to cause infinite loop
spi_1_send
(
0xff
);
}
else
{
if
(
wait_ready
()
!=
0xff
)
return
0xff
;
}
// Send command
spi_1_send
(
cmd
);
// Start + Command index
spi_1_send
((
unsigned
char
)(
arg
>>
24
));
// Argument[31..24]
spi_1_send
((
unsigned
char
)(
arg
>>
16
));
// Argument[23..16]
spi_1_send
((
unsigned
char
)(
arg
>>
8
));
// Argument[15..8]
spi_1_send
((
unsigned
char
)
arg
);
// Argument[7..0]
n
=
0x01
;
// Dummy CRC + Stop
if
(
cmd
==
CMD0
)
n
=
0x95
;
// Valid CRC for CMD0(0)
if
(
cmd
==
CMD8
)
n
=
0x87
;
// Valid CRC for CMD8(0x1AA)
spi_1_send
(
n
);
// Receive response
if
(
cmd
==
CMD12
)
spi_1_send
(
0xff
);
// Skip a stuff byte when stop reading
n
=
10
;
// Wait response, try 10 times
do
res
=
spi_1_send
(
0xff
);
while
((
res
&
0x80
)
&&
--
n
);
return
res
;
// Return with the response value
}
/**
* \internal
* Receive a data packet from the SD card
* \param buf data buffer to store received data
* \param byte count (must be multiple of 4)
* \return true on success, false on failure
*/
static
bool
rx_datablock
(
unsigned
char
*
buf
,
unsigned
int
btr
)
{
unsigned
char
token
;
for
(
int
i
=
0
;
i
<
0xffff
;
i
++
)
{
token
=
spi_1_send
(
0xff
);
if
(
token
!=
0xff
)
break
;
}
if
(
token
!=
0xfe
)
return
false
;
// If not valid data token, retutn error
do
{
// Receive the data block into buffer
*
buf
=
spi_1_send
(
0xff
);
buf
++
;
*
buf
=
spi_1_send
(
0xff
);
buf
++
;
*
buf
=
spi_1_send
(
0xff
);
buf
++
;
*
buf
=
spi_1_send
(
0xff
);
buf
++
;
}
while
(
btr
-=
4
);
spi_1_send
(
0xff
);
// Discard CRC
spi_1_send
(
0xff
);
return
true
;
// Return success
}
/**
* \internal
* Send a data packet to the SD card
* \param buf 512 byte data block to be transmitted
* \param token data start/stop token
* \return true on success, false on failure
*/
static
bool
tx_datablock
(
const
unsigned
char
*
buf
,
unsigned
char
token
)
{
unsigned
char
resp
;
if
(
wait_ready
()
!=
0xff
)
return
false
;
spi_1_send
(
token
);
// Xmit data token
if
(
token
!=
0xfd
)
{
// Is data token
for
(
int
i
=
0
;
i
<
256
;
i
++
)
{
// Xmit the 512 byte data block
spi_1_send
(
*
buf
);
buf
++
;
spi_1_send
(
*
buf
);
buf
++
;
}
spi_1_send
(
0xff
);
// CRC (Dummy)
spi_1_send
(
0xff
);
resp
=
spi_1_send
(
0xff
);
// Receive data response
if
((
resp
&
0x1f
)
!=
0x05
)
// If not accepted, return error
return
false
;
}
return
true
;
}
//
// class SPISDDriver
//
intrusive_ref_ptr
<
SPISDDriver
>
SPISDDriver
::
instance
()
{
static
FastMutex
m
;
static
intrusive_ref_ptr
<
SPISDDriver
>
instance
;
Lock
<
FastMutex
>
l
(
m
);
if
(
!
instance
)
instance
=
new
SPISDDriver
();
return
instance
;
}
ssize_t
SPISDDriver
::
readBlock
(
void
*
buffer
,
size_t
size
,
off_t
where
)
{
if
(
where
%
512
||
size
%
512
)
return
-
EFAULT
;
unsigned
int
lba
=
where
/
512
;
unsigned
int
nSectors
=
size
/
512
;
unsigned
char
*
buf
=
reinterpret_cast
<
unsigned
char
*>
(
buffer
);
Lock
<
FastMutex
>
l
(
mutex
);
DBG
(
"SPISDDriver::readBlock(): nSectors=%d
\n
"
,
nSectors
);
if
(
!
(
cardType
&
8
))
lba
*=
512
;
// Convert to byte address if needed
unsigned
char
result
;
if
(
nSectors
==
1
)
{
// Single block read
result
=
send_cmd
(
CMD17
,
lba
);
// READ_SINGLE_BLOCK
if
(
result
!=
0
)
{
print_error_code
(
result
);
CS_HIGH
();
return
-
EBADF
;
}
if
(
rx_datablock
(
buf
,
512
)
==
false
)
{
DBGERR
(
"Block read error
\n
"
);
CS_HIGH
();
return
-
EBADF
;
}
}
else
{
// Multiple block read
//DBGERR("Mbr\n");//debug only
result
=
send_cmd
(
CMD18
,
lba
);
// READ_MULTIPLE_BLOCK
if
(
result
!=
0
)
{
print_error_code
(
result
);
CS_HIGH
();
return
-
EBADF
;
}
do
{
if
(
!
rx_datablock
(
buf
,
512
))
break
;
buf
+=
512
;
}
while
(
--
nSectors
);
send_cmd
(
CMD12
,
0
);
// STOP_TRANSMISSION
if
(
nSectors
!=
0
)
{
DBGERR
(
"Multiple block read error
\n
"
);
CS_HIGH
();
return
-
EBADF
;
}
}
CS_HIGH
();
return
size
;
}
ssize_t
SPISDDriver
::
writeBlock
(
const
void
*
buffer
,
size_t
size
,
off_t
where
)
{
if
(
where
%
512
||
size
%
512
)
return
-
EFAULT
;
unsigned
int
lba
=
where
/
512
;
unsigned
int
nSectors
=
size
/
512
;
const
unsigned
char
*
buf
=
reinterpret_cast
<
const
unsigned
char
*>
(
buffer
);
Lock
<
FastMutex
>
l
(
mutex
);
DBG
(
"SPISDDriver::writeBlock(): nSectors=%d
\n
"
,
nSectors
);
if
(
!
(
cardType
&
8
))
lba
*=
512
;
// Convert to byte address if needed
unsigned
char
result
;
if
(
nSectors
==
1
)
{
// Single block write
result
=
send_cmd
(
CMD24
,
lba
);
// WRITE_BLOCK
if
(
result
!=
0
)
{
print_error_code
(
result
);
CS_HIGH
();
return
-
EBADF
;
}
if
(
tx_datablock
(
buf
,
0xfe
)
==
false
)
// WRITE_BLOCK
{
DBGERR
(
"Block write error
\n
"
);
CS_HIGH
();
return
-
EBADF
;
}
}
else
{
// Multiple block write
//DBGERR("Mbw\n");//debug only
if
(
cardType
&
6
)
send_cmd
(
ACMD23
,
nSectors
);
//Only if it is SD card
result
=
send_cmd
(
CMD25
,
lba
);
// WRITE_MULTIPLE_BLOCK
if
(
result
!=
0
)
{
print_error_code
(
result
);
CS_HIGH
();
return
-
EBADF
;
}
do
{
if
(
!
tx_datablock
(
buf
,
0xfc
))
break
;
buf
+=
512
;
}
while
(
--
nSectors
);
if
(
!
tx_datablock
(
0
,
0xfd
))
// STOP_TRAN token
{
DBGERR
(
"Multiple block write error
\n
"
);
CS_HIGH
();
return
-
EBADF
;
}
}
CS_HIGH
();
return
size
;
}
int
SPISDDriver
::
ioctl
(
int
cmd
,
void
*
arg
)
{
DBG
(
"SPISDDriver::ioctl()
\n
"
);
if
(
cmd
!=
IOCTL_SYNC
)
return
-
ENOTTY
;
Lock
<
FastMutex
>
l
(
mutex
);
CS_LOW
();
unsigned
char
result
=
wait_ready
();
CS_HIGH
();
if
(
result
==
0xff
)
return
0
;
else
return
-
EFAULT
;
}
SPISDDriver
::
SPISDDriver
()
:
Device
(
Device
::
BLOCK
)
{
const
int
MAX_RETRY
=
20
;
//Maximum command retry before failing
spi_1_init
();
/* init at low speed */
unsigned
char
resp
;
int
i
;
for
(
i
=
0
;
i
<
MAX_RETRY
;
i
++
)
{
resp
=
send_cmd
(
CMD0
,
0
);
if
(
resp
==
1
)
break
;
}
DBG
(
"CMD0 required %d commands
\n
"
,
i
+
1
);
if
(
resp
!=
1
)
{
print_error_code
(
resp
);
DBGERR
(
"Init failed
\n
"
);
CS_HIGH
();
return
;
//Error
}
unsigned
char
n
,
cmd
,
ty
=
0
,
ocr
[
4
];
// Enter Idle state
if
(
send_cmd
(
CMD8
,
0x1aa
)
==
1
)
{
/* SDHC */
for
(
n
=
0
;
n
<
4
;
n
++
)
ocr
[
n
]
=
spi_1_send
(
0xff
);
// Get return value of R7 resp
if
((
ocr
[
2
]
==
0x01
)
&&
(
ocr
[
3
]
==
0xaa
))
{
// The card can work at vdd range of 2.7-3.6V
for
(
i
=
0
;
i
<
MAX_RETRY
;
i
++
)
{
resp
=
send_cmd
(
ACMD41
,
1UL
<<
30
);
if
(
resp
==
0
)
{
if
(
send_cmd
(
CMD58
,
0
)
==
0
)
{
// Check CCS bit in the OCR
for
(
n
=
0
;
n
<
4
;
n
++
)
ocr
[
n
]
=
spi_1_send
(
0xff
);
if
(
ocr
[
0
]
&
0x40
)
{
ty
=
12
;
DBG
(
"SDHC, block addressing supported
\n
"
);
}
else
{
ty
=
4
;
DBG
(
"SDHC, no block addressing
\n
"
);
}
}
else
DBGERR
(
"CMD58 failed
\n
"
);
break
;
//Exit from for
}
else
print_error_code
(
resp
);
}
DBG
(
"ACMD41 required %d commands
\n
"
,
i
+
1
);
}
else
DBGERR
(
"CMD8 failed
\n
"
);
}
else
{
/* SDSC or MMC */
if
(
send_cmd
(
ACMD41
,
0
)
<=
1
)
{
ty
=
2
;
cmd
=
ACMD41
;
/* SDSC */
DBG
(
"SD card
\n
"
);
}
else
{
ty
=
1
;
cmd
=
CMD1
;
/* MMC */
DBG
(
"MMC card
\n
"
);
}
for
(
i
=
0
;
i
<
MAX_RETRY
;
i
++
)
{
resp
=
send_cmd
(
cmd
,
0
);
if
(
resp
==
0
)
{
if
(
send_cmd
(
CMD16
,
512
)
!=
0
)
{
ty
=
0
;
DBGERR
(
"CMD16 failed
\n
"
);
}
break
;
//Exit from for
}
else
print_error_code
(
resp
);
}
DBG
(
"CMD required %d commands
\n
"
,
i
+
1
);
}
if
(
ty
==
0
)
{
CS_HIGH
();
return
;
//Error
}
cardType
=
ty
;
if
(
sd_status
()
<
0
)
{
DBGERR
(
"Status error
\n
"
);
CS_HIGH
();
return
;
//Error
}
CS_HIGH
();
//Configure the SPI interface to use the 7.4MHz high speed mode
SSPCR0
=
((
8
-
1
)
<<
0
)
|
(
0
<<
CPOL
);
SSPCPSR
=
SPI_PRESCALE_MIN
;
DBG
(
"Init done...
\n
"
);
}
}
//namespace miosix
This diff is collapsed.
Click to expand it.
src/shared/drivers/sdspi/sdspi.h
0 → 100644
+
52
−
0
View file @
be295624
/* Copyright (c) 2023 Skyward Experimental Rocketry
* Authors: Federico Lolli
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include
"sdspi.h"
#include
<miosix.h>
#include
<filesystem/devfs/devfs.h>
namespace
Boardcore
{
/**
* Driver for interfacing to an SD card through SPI
*/
class
SPISDDriver
:
public
miosix
::
Device
{
public:
virtual
ssize_t
readBlock
(
void
*
buffer
,
size_t
size
,
off_t
where
);
virtual
ssize_t
writeBlock
(
const
void
*
buffer
,
size_t
size
,
off_t
where
);
virtual
int
ioctl
(
int
cmd
,
void
*
arg
);
private:
/**
* Constructor
*/
SPISDDriver
();
miosix
::
FastMutex
mutex
;
};
}
//namespace Boardcore
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