Skip to content

Commit b4aa24e

Browse files
Merge pull request #339 from victorpv/patch-3
F1 SDIO first version
2 parents c12ad24 + 1db95cf commit b4aa24e

File tree

5 files changed

+1337
-0
lines changed

5 files changed

+1337
-0
lines changed

STM32F1/cores/maple/sdio.cpp

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
/******************************************************************************
2+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
3+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
4+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
5+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
6+
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
7+
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
8+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
9+
* SOFTWARE.
10+
*****************************************************************************/
11+
12+
/**
13+
* @file libmaple/sdio.c
14+
* @author stevstrong
15+
* @brief Secure digital input/output interface.
16+
*/
17+
18+
#include <libmaple/sdio.h>
19+
#include <libmaple/gpio.h>
20+
#include <boards.h>
21+
#include "wirish.h"
22+
23+
24+
//#include <libmaple/libmaple.h>
25+
//#include <libmaple/rcc.h>
26+
//#include <series/gpio.h>
27+
//#include "wirish.h"
28+
//#include "boards.h"
29+
//
30+
31+
#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
32+
33+
sdio_dev * SDIO = SDIO_BASE;
34+
35+
#define DELAY_LONG 10
36+
#define DELAY_SHORT 1
37+
38+
uint8_t dly = DELAY_LONG; // microseconds delay after accessing registers
39+
40+
/*
41+
* SDIO convenience routines
42+
*/
43+
void sdio_gpios_init(void)
44+
{
45+
gpio_set_mode(PIN_MAP[BOARD_SDIO_D0].gpio_device, PIN_MAP[BOARD_SDIO_D0].gpio_bit, GPIO_AF_OUTPUT_PP);
46+
gpio_set_mode(PIN_MAP[BOARD_SDIO_D1].gpio_device, PIN_MAP[BOARD_SDIO_D1].gpio_bit, GPIO_AF_OUTPUT_PP);
47+
gpio_set_mode(PIN_MAP[BOARD_SDIO_D2].gpio_device, PIN_MAP[BOARD_SDIO_D2].gpio_bit, GPIO_AF_OUTPUT_PP);
48+
gpio_set_mode(PIN_MAP[BOARD_SDIO_D3].gpio_device, PIN_MAP[BOARD_SDIO_D3].gpio_bit, GPIO_AF_OUTPUT_PP);
49+
gpio_set_mode(PIN_MAP[BOARD_SDIO_CLK].gpio_device, PIN_MAP[BOARD_SDIO_CLK].gpio_bit, GPIO_AF_OUTPUT_PP);
50+
gpio_set_mode(PIN_MAP[BOARD_SDIO_CMD].gpio_device, PIN_MAP[BOARD_SDIO_CMD].gpio_bit, GPIO_AF_OUTPUT_PP);
51+
/*
52+
* Todo just remove it, not needed for F1.
53+
*/
54+
/*
55+
gpio_set_af_mode(BOARD_SDIO_D0, 12);
56+
gpio_set_af_mode(BOARD_SDIO_D1, 12);
57+
gpio_set_af_mode(BOARD_SDIO_D2, 12);
58+
gpio_set_af_mode(BOARD_SDIO_D3, 12);
59+
gpio_set_af_mode(BOARD_SDIO_CLK, 12);
60+
gpio_set_af_mode(BOARD_SDIO_CMD, 12);
61+
*/
62+
}
63+
64+
void sdio_gpios_deinit(void)
65+
{
66+
gpio_set_mode(PIN_MAP[BOARD_SDIO_D0].gpio_device, PIN_MAP[BOARD_SDIO_D0].gpio_bit, GPIO_INPUT_FLOATING);
67+
gpio_set_mode(PIN_MAP[BOARD_SDIO_D1].gpio_device, PIN_MAP[BOARD_SDIO_D1].gpio_bit, GPIO_INPUT_FLOATING);
68+
gpio_set_mode(PIN_MAP[BOARD_SDIO_D2].gpio_device, PIN_MAP[BOARD_SDIO_D2].gpio_bit, GPIO_INPUT_FLOATING);
69+
gpio_set_mode(PIN_MAP[BOARD_SDIO_D3].gpio_device, PIN_MAP[BOARD_SDIO_D3].gpio_bit, GPIO_INPUT_FLOATING);
70+
gpio_set_mode(PIN_MAP[BOARD_SDIO_CLK].gpio_device, PIN_MAP[BOARD_SDIO_CLK].gpio_bit, GPIO_INPUT_FLOATING);
71+
gpio_set_mode(PIN_MAP[BOARD_SDIO_CMD].gpio_device, PIN_MAP[BOARD_SDIO_CMD].gpio_bit, GPIO_INPUT_FLOATING);
72+
73+
/*
74+
* Todo just remove it, not needed for F1.
75+
*/
76+
/*
77+
gpio_set_af_mode(BOARD_SDIO_D0, 0);
78+
gpio_set_af_mode(BOARD_SDIO_D1, 0);
79+
gpio_set_af_mode(BOARD_SDIO_D2, 0);
80+
gpio_set_af_mode(BOARD_SDIO_D3, 0);
81+
gpio_set_af_mode(BOARD_SDIO_CLK, 0);
82+
gpio_set_af_mode(BOARD_SDIO_CMD, 0);
83+
*/
84+
}
85+
86+
/**
87+
* @brief Initialize and reset the SDIO device.
88+
*/
89+
void sdio_init(void)
90+
{
91+
rcc_clk_enable(RCC_SDIO);
92+
rcc_reset_dev(RCC_SDIO);
93+
}
94+
95+
void sdio_power_on(void)
96+
{
97+
SDIO->POWER = SDIO_POWER_PWRCTRL_ON;
98+
// After a data write, data cannot be written to this register for three SDIOCLK clock periods
99+
// plus two PCLK2 clock periods.
100+
delay_us(DELAY_LONG);
101+
}
102+
103+
void sdio_power_off(void)
104+
{
105+
SDIO->POWER = SDIO_POWER_PWRCTRL_OFF;
106+
// After a data write, data cannot be written to this register for three SDIOCLK clock periods
107+
// plus two PCLK2 clock periods.
108+
delay_us(DELAY_LONG);
109+
}
110+
111+
void sdio_set_clock(uint32_t clk)
112+
{
113+
if (clk>24000000UL) clk = 24000000UL; // limit the SDIO master clock to 24MHz
114+
115+
if (clk<1000000) dly = DELAY_LONG;
116+
else dly = DELAY_SHORT;
117+
118+
sdio_disable();
119+
SDIO->CLKCR = (SDIO->CLKCR & (~(SDIO_CLKCR_CLKDIV|SDIO_CLKCR_BYPASS))) | SDIO_CLKCR_CLKEN | (((SDIOCLK/clk)-2)&SDIO_CLKCR_CLKDIV);
120+
delay_us(dly);
121+
}
122+
123+
void sdio_set_dbus_width(uint16_t bus_w)
124+
{
125+
SDIO->CLKCR = (SDIO->CLKCR & (~SDIO_CLKCR_WIDBUS)) | bus_w;
126+
delay_us(dly);
127+
}
128+
129+
void sdio_set_dblock_size(uint8_t dbsize)
130+
{
131+
SDIO->DCTRL = (SDIO->DCTRL&(~SDIO_DCTRL_DBLOCKSIZE)) | ((dbsize&0xF)<<4);
132+
delay_us(dly);
133+
}
134+
135+
void sdio_enable(void)
136+
{
137+
SDIO->CLKCR |= SDIO_CLKCR_CLKEN;
138+
delay_us(dly);
139+
}
140+
141+
void sdio_disable(void)
142+
{
143+
SDIO->CLKCR ^= SDIO_CLKCR_CLKEN;
144+
delay_us(dly);
145+
}
146+
147+
/**
148+
* @brief Configure and enable the SDIO device.
149+
*/
150+
void sdio_begin(void)
151+
{
152+
sdio_gpios_init();
153+
sdio_init();
154+
sdio_power_on();
155+
// Set initial SCK rate.
156+
sdio_set_clock(400000);
157+
delay_us(200); // generate 80 pulses at 400kHz
158+
}
159+
160+
/**
161+
* @brief Disables the SDIO device.
162+
*/
163+
void sdio_end(void)
164+
{
165+
sdio_disable();
166+
while ( sdio_cmd_xfer_ongoing() );
167+
sdio_power_off();
168+
rcc_clk_disable(RCC_SDIO);
169+
sdio_gpios_deinit();
170+
}
171+
172+
/**
173+
* @brief Send command by the SDIO device.
174+
*/
175+
uint8_t sdio_cmd_send(uint16_t cmd_index_resp_type, uint32_t arg)
176+
{
177+
uint8_t retries = 10; // in case of errors
178+
do { // retry command if errors detected
179+
// clear interrupt flags - IMPORTANT!!!
180+
SDIO->ICR = SDIO_ICR_CMD_FLAGS;
181+
// write command
182+
SDIO->ARG = arg;
183+
SDIO->CMD = (uint32_t)(SDIO_CMD_CPSMEN | cmd_index_resp_type );
184+
while ( (SDIO->STA&SDIO_STA_CMDACT) ) ; // wait for actual command transfer to finish
185+
// wait for response, if the case
186+
if ( cmd_index_resp_type&(SDIO_CMD_WAIT_SHORT_RESP|SDIO_CMD_WAIT_LONG_RESP) ) {
187+
while ( !(SDIO->STA&(SDIO_STA_CMDREND|SDIO_STA_CMD_ERROR_FLAGS)) ) ;
188+
} else break; // no response required
189+
if ( SDIO->STA&(SDIO_STA_CMDREND|SDIO_STA_CTIMEOUT) )
190+
break; // response received or timeout
191+
// ignore CRC error for CMD5 and ACMD41
192+
if ( ((cmd_index_resp_type&SDIO_CMD_CMDINDEX)==5) || ((cmd_index_resp_type&SDIO_CMD_CMDINDEX)==41) )
193+
break;
194+
} while ( (--retries) );
195+
return (uint8_t)retries;
196+
}
197+
198+
#endif // defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)

0 commit comments

Comments
 (0)