Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
Nodemcu Firmware
Commits
9cde0bbb
Commit
9cde0bbb
authored
Oct 08, 2015
by
devsaurus
Browse files
add SPI transaction support
parent
8c419b8a
Changes
5
Hide whitespace changes
Inline
Side-by-side
app/driver/spi.c
View file @
9cde0bbb
...
...
@@ -85,26 +85,27 @@ void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, unsigned databi
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_MTDO_U
,
2
);
//configure io to spi mode
}
SET_PERI_REG_MASK
(
SPI_USER
(
spi_no
),
SPI_CS_SETUP
|
SPI_CS_HOLD
|
SPI_DOUTDIN
|
SPI_USR_MOSI
);
//set clock polarity
// TODO: This doesn't work
//if (cpol == 1) {
// SET_PERI_REG_MASK(SPI_CTRL2(spi_no), (SPI_CK_OUT_HIGH_MODE<<SPI_CK_OUT_HIGH_MODE_S));
//} else {
// SET_PERI_REG_MASK(SPI_CTRL2(spi_no), (SPI_CK_OUT_LOW_MODE<<SPI_CK_OUT_LOW_MODE_S));
//}
//os_printf("SPI_CTRL2 is %08x\n",READ_PERI_REG(SPI_CTRL2(spi_no)));
//set clock phase
if
(
cpha
==
1
)
{
SET_PERI_REG_MASK
(
SPI_USER
(
spi_no
),
SPI_CK_OUT_EDGE
|
SPI_CK_I_EDGE
);
}
else
{
CLEAR_PERI_REG_MASK
(
SPI_USER
(
spi_no
),
SPI_CK_OUT_EDGE
|
SPI_CK_I_EDGE
);
}
SET_PERI_REG_MASK
(
SPI_USER
(
spi_no
),
SPI_CS_SETUP
|
SPI_CS_HOLD
|
SPI_DOUTDIN
|
SPI_USR_MOSI
|
SPI_RD_BYTE_ORDER
|
SPI_WR_BYTE_ORDER
);
//set clock polarity
// TODO: This doesn't work
//if (cpol == 1) {
// SET_PERI_REG_MASK(SPI_CTRL2(spi_no), (SPI_CK_OUT_HIGH_MODE<<SPI_CK_OUT_HIGH_MODE_S));
//} else {
// SET_PERI_REG_MASK(SPI_CTRL2(spi_no), (SPI_CK_OUT_LOW_MODE<<SPI_CK_OUT_LOW_MODE_S));
//}
//os_printf("SPI_CTRL2 is %08x\n",READ_PERI_REG(SPI_CTRL2(spi_no)));
//set clock phase
if
(
cpha
==
1
)
{
SET_PERI_REG_MASK
(
SPI_USER
(
spi_no
),
SPI_CK_OUT_EDGE
|
SPI_CK_I_EDGE
);
}
else
{
CLEAR_PERI_REG_MASK
(
SPI_USER
(
spi_no
),
SPI_CK_OUT_EDGE
|
SPI_CK_I_EDGE
);
}
CLEAR_PERI_REG_MASK
(
SPI_USER
(
HSPI
),
SPI_FLASH_MODE
|
SPI_
WR_BYTE_ORDER
|
SPI_
USR_MISO
|
SPI_RD_BYTE_ORDER
|
SPI_USR_ADDR
|
SPI_USR_COMMAND
|
SPI_USR_DUMMY
);
CLEAR_PERI_REG_MASK
(
SPI_USER
(
spi_no
),
SPI_FLASH_MODE
|
SPI_USR_MISO
|
SPI_USR_ADDR
|
SPI_USR_COMMAND
|
SPI_USR_DUMMY
);
//clear Daul or Quad lines transmission mode
CLEAR_PERI_REG_MASK
(
SPI_CTRL
(
spi_no
),
SPI_QIO_MODE
|
SPI_DIO_MODE
|
SPI_DOUT_MODE
|
SPI_QOUT_MODE
);
...
...
@@ -151,6 +152,126 @@ void spi_mast_byte_write(uint8 spi_no, uint8 *data)
*
data
=
(
uint8
)(
READ_PERI_REG
(
SPI_W0
(
spi_no
))
&
0xff
);
}
/******************************************************************************
* FunctionName : spi_mast_set_mosi
* Description : Enter provided data into MOSI buffer.
* The data is regarded as a sequence of bits with length 'bitlen'.
* It will be written left-aligned starting from position 'offset'.
* Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
* uint8 offset - offset into MOSI buffer (number of bits)
* uint8 bitlen - valid number of bits in data
* uint32 data - data to be written into buffer
*******************************************************************************/
void
spi_mast_set_mosi
(
uint8
spi_no
,
uint8
offset
,
uint8
bitlen
,
uint32
data
)
{
uint8
wn
,
wn_offset
,
wn_bitlen
;
uint32
wn_data
;
if
(
spi_no
>
1
)
return
;
// handle invalid input number
if
(
bitlen
>
32
)
return
;
// handle invalid input number
while
(
READ_PERI_REG
(
SPI_CMD
(
spi_no
))
&
SPI_USR
);
// determine which SPI_Wn register is addressed
wn
=
offset
>>
5
;
if
(
wn
>
15
)
return
;
// out of range
wn_offset
=
offset
&
0x1f
;
if
(
32
-
wn_offset
<
bitlen
)
{
// splitting required
wn_bitlen
=
32
-
wn_offset
;
wn_data
=
data
>>
(
bitlen
-
wn_bitlen
);
}
else
{
wn_bitlen
=
bitlen
;
wn_data
=
data
;
}
do
{
// write payload data to SPI_Wn
SET_PERI_REG_BITS
(
REG_SPI_BASE
(
spi_no
)
+
0x40
+
wn
*
4
,
BIT
(
wn_bitlen
)
-
1
,
wn_data
,
32
-
(
wn_offset
+
wn_bitlen
));
// prepare writing of dangling data part
wn
+=
1
;
wn_offset
=
0
;
if
(
wn
<=
15
)
bitlen
-=
wn_bitlen
;
else
bitlen
=
0
;
// force abort
wn_bitlen
=
bitlen
;
wn_data
=
data
;
}
while
(
bitlen
>
0
);
}
/******************************************************************************
* FunctionName : spi_mast_transaction
* Description : Start a transaction and wait for completion.
* Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
* uint8 cmd_bitlen - Valid number of bits in cmd_data.
* uint16 cmd_data - Command data.
* uint8 addr_bitlen - Valid number of bits in addr_data.
* uint32 addr_data - Address data.
* uint8 mosi_bitlen - Valid number of bits in MOSI buffer.
* uint8 dummy_bitlen - Number of dummy cycles.
* uint8 miso_bitlen - number of bits to be captured in MISO buffer.
*******************************************************************************/
void
spi_mast_transaction
(
uint8
spi_no
,
uint8
cmd_bitlen
,
uint16
cmd_data
,
uint8
addr_bitlen
,
uint32
addr_data
,
uint8
mosi_bitlen
,
uint8
dummy_bitlen
,
uint8
miso_bitlen
)
{
if
(
spi_no
>
1
)
return
;
// handle invalid input number
while
(
READ_PERI_REG
(
SPI_CMD
(
spi_no
))
&
SPI_USR
);
// default disable COMMAND, ADDR, MOSI, DUMMY, MISO
CLEAR_PERI_REG_MASK
(
SPI_USER
(
spi_no
),
SPI_USR_COMMAND
|
SPI_USR_ADDR
|
SPI_USR_MOSI
|
SPI_USR_DUMMY
|
SPI_USR_MISO
);
// default set bit lengths
WRITE_PERI_REG
(
SPI_USER1
(
spi_no
),
((
addr_bitlen
-
1
)
&
SPI_USR_ADDR_BITLEN
)
<<
SPI_USR_ADDR_BITLEN_S
|
((
mosi_bitlen
-
1
)
&
SPI_USR_MOSI_BITLEN
)
<<
SPI_USR_MOSI_BITLEN_S
|
((
dummy_bitlen
-
1
)
&
SPI_USR_DUMMY_CYCLELEN
)
<<
SPI_USR_DUMMY_CYCLELEN_S
|
((
miso_bitlen
-
1
)
&
SPI_USR_MISO_BITLEN
)
<<
SPI_USR_MISO_BITLEN_S
);
// handle the transaction components
if
(
cmd_bitlen
>
0
)
{
uint16
cmd
=
cmd_data
<<
(
16
-
cmd_bitlen
);
// align to MSB
cmd
=
(
cmd
>>
8
)
|
(
cmd
<<
8
);
// swap byte order
WRITE_PERI_REG
(
SPI_USER2
(
spi_no
),
((
cmd_bitlen
-
1
&
SPI_USR_COMMAND_BITLEN
)
<<
SPI_USR_COMMAND_BITLEN_S
)
|
(
cmd
&
SPI_USR_COMMAND_VALUE
));
SET_PERI_REG_MASK
(
SPI_USER
(
spi_no
),
SPI_USR_COMMAND
);
}
if
(
addr_bitlen
>
0
)
{
WRITE_PERI_REG
(
SPI_ADDR
(
spi_no
),
addr_data
<<
(
32
-
addr_bitlen
));
SET_PERI_REG_MASK
(
SPI_USER
(
spi_no
),
SPI_USR_ADDR
);
}
if
(
mosi_bitlen
>
0
)
{
SET_PERI_REG_MASK
(
SPI_USER
(
spi_no
),
SPI_USR_MOSI
);
}
if
(
dummy_bitlen
>
0
)
{
SET_PERI_REG_MASK
(
SPI_USER
(
spi_no
),
SPI_USR_DUMMY
);
}
if
(
miso_bitlen
>
0
)
{
SET_PERI_REG_MASK
(
SPI_USER
(
spi_no
),
SPI_USR_MISO
);
}
// start transaction
SET_PERI_REG_MASK
(
SPI_CMD
(
spi_no
),
SPI_USR
);
while
(
READ_PERI_REG
(
SPI_CMD
(
spi_no
))
&
SPI_USR
);
}
/******************************************************************************
* FunctionName : spi_byte_write_espslave
* Description : SPI master 1 byte transmission function for esp8266 slave,
...
...
app/include/driver/spi.h
View file @
9cde0bbb
...
...
@@ -22,6 +22,10 @@ void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, unsigned databi
//use spi send 8bit data
void
spi_mast_byte_write
(
uint8
spi_no
,
uint8
*
data
);
void
spi_set_mosi
(
uint8
spi_no
,
uint8
offset
,
uint8
bitlen
,
uint32
data
);
void
spi_mast_transaction
(
uint8
spi_no
,
uint8
cmd_bitlen
,
uint16
cmd_data
,
uint8
addr_bitlen
,
uint32
addr_data
,
uint8
mosi_bitlen
,
uint8
dummy_bitlen
,
uint8
miso_bitlen
);
//transmit data to esp8266 slave buffer,which needs 16bit transmission ,
//first byte is master command 0x04, second byte is master data
void
spi_byte_write_espslave
(
uint8
spi_no
,
uint8
data
);
...
...
app/modules/spi.c
View file @
9cde0bbb
...
...
@@ -57,7 +57,7 @@ static int spi_send( lua_State *L )
MOD_CHECK_ID
(
spi
,
id
);
if
(
lua_gettop
(
L
)
<
2
)
return
luaL_error
(
L
,
"
wrong arg type
"
);
return
luaL_error
(
L
,
"
too few args
"
);
for
(
argn
=
2
;
argn
<=
lua_gettop
(
L
);
argn
++
)
{
...
...
@@ -68,7 +68,7 @@ static int spi_send( lua_State *L )
numdata
=
(
int
)
luaL_checkinteger
(
L
,
argn
);
if
(
numdata
<
0
||
numdata
>
255
)
return
luaL_error
(
L
,
"wrong arg range"
);
platform_spi_
send_recv
(
id
,
numdata
);
platform_spi_
transaction
(
id
,
8
,
numdata
,
0
,
0
,
0
,
0
,
0
);
wrote
++
;
}
else
if
(
lua_istable
(
L
,
argn
)
)
...
...
@@ -81,7 +81,7 @@ static int spi_send( lua_State *L )
lua_pop
(
L
,
1
);
if
(
numdata
<
0
||
numdata
>
255
)
return
luaL_error
(
L
,
"wrong arg range"
);
platform_spi_
send_recv
(
id
,
numdata
);
platform_spi_
transaction
(
id
,
8
,
numdata
,
0
,
0
,
0
,
0
,
0
);
}
wrote
+=
i
;
if
(
i
<
datalen
)
...
...
@@ -91,7 +91,7 @@ static int spi_send( lua_State *L )
{
pdata
=
luaL_checklstring
(
L
,
argn
,
&
datalen
);
for
(
i
=
0
;
i
<
datalen
;
i
++
)
platform_spi_
send_recv
(
id
,
pdata
[
i
]
);
platform_spi_
transaction
(
id
,
8
,
pdata
[
i
]
,
0
,
0
,
0
,
0
,
0
);
wrote
+=
i
;
if
(
i
<
datalen
)
break
;
...
...
@@ -126,14 +126,89 @@ static int spi_recv( lua_State *L )
return
1
;
}
// Lua: spi.set_mosi( id, offset, bitlen, data1, [data2], ..., [datan] )
static
int
spi_set_mosi
(
lua_State
*
L
)
{
unsigned
id
=
luaL_checkinteger
(
L
,
1
);
unsigned
offset
=
luaL_checkinteger
(
L
,
2
);
unsigned
bitlen
=
luaL_checkinteger
(
L
,
3
);
unsigned
argn
;
MOD_CHECK_ID
(
spi
,
id
);
if
(
offset
<
0
||
offset
>
511
)
{
return
luaL_error
(
L
,
"offset out of range"
);
}
if
(
bitlen
<
1
||
bitlen
>
32
)
{
return
luaL_error
(
L
,
"bitlen out of range"
);
}
if
(
lua_gettop
(
L
)
<
4
)
{
return
luaL_error
(
L
,
"too few args"
);
}
for
(
argn
=
4
;
argn
<=
lua_gettop
(
L
);
argn
++
,
offset
+=
bitlen
)
{
u32
data
=
luaL_checkinteger
(
L
,
argn
);
if
(
offset
+
bitlen
>
512
)
return
luaL_error
(
L
,
"data range exceeded > 512 bits"
);
if
(
platform_spi_set_mosi
(
id
,
offset
,
bitlen
,
data
)
!=
PLATFORM_OK
)
return
luaL_error
(
L
,
"failed"
);
}
return
0
;
}
// Lua: spi.transaction( id, cmd_bitlen, cmd_data, addr_bitlen, addr_data, mosi_bitlen, dummy_bitlen, miso_bitlen )
static
int
spi_transaction
(
lua_State
*
L
)
{
unsigned
id
=
luaL_checkinteger
(
L
,
1
);
unsigned
cmd_bitlen
=
luaL_checkinteger
(
L
,
2
);
u32
cmd_data
=
luaL_checkinteger
(
L
,
3
);
unsigned
addr_bitlen
=
luaL_checkinteger
(
L
,
4
);
u32
addr_data
=
luaL_checkinteger
(
L
,
5
);
unsigned
mosi_bitlen
=
luaL_checkinteger
(
L
,
6
);
unsigned
dummy_bitlen
=
luaL_checkinteger
(
L
,
7
);
unsigned
miso_bitlen
=
luaL_checkinteger
(
L
,
8
);
MOD_CHECK_ID
(
spi
,
id
);
if
(
cmd_bitlen
<
0
||
cmd_bitlen
>
16
)
{
return
luaL_error
(
L
,
"cmd_bitlen out of range"
);
}
if
(
addr_bitlen
<
0
||
addr_bitlen
>
32
)
{
return
luaL_error
(
L
,
"addr_bitlen out of range"
);
}
if
(
mosi_bitlen
<
0
||
mosi_bitlen
>
512
)
{
return
luaL_error
(
L
,
"mosi_bitlen out of range"
);
}
if
(
dummy_bitlen
<
0
||
dummy_bitlen
>
256
)
{
return
luaL_error
(
L
,
"dummy_bitlen out of range"
);
}
if
(
miso_bitlen
<
0
||
miso_bitlen
>
511
)
{
return
luaL_error
(
L
,
"miso_bitlen out of range"
);
}
if
(
platform_spi_transaction
(
id
,
cmd_bitlen
,
cmd_data
,
addr_bitlen
,
addr_data
,
mosi_bitlen
,
dummy_bitlen
,
miso_bitlen
)
!=
PLATFORM_OK
)
return
luaL_error
(
L
,
"failed"
);
return
0
;
}
// Module function map
#define MIN_OPT_LEVEL 2
#include "lrodefs.h"
const
LUA_REG_TYPE
spi_map
[]
=
{
{
LSTRKEY
(
"setup"
),
LFUNCVAL
(
spi_setup
)
},
{
LSTRKEY
(
"send"
),
LFUNCVAL
(
spi_send
)
},
{
LSTRKEY
(
"recv"
),
LFUNCVAL
(
spi_recv
)
},
{
LSTRKEY
(
"setup"
),
LFUNCVAL
(
spi_setup
)
},
{
LSTRKEY
(
"send"
),
LFUNCVAL
(
spi_send
)
},
{
LSTRKEY
(
"recv"
),
LFUNCVAL
(
spi_recv
)
},
{
LSTRKEY
(
"set_mosi"
),
LFUNCVAL
(
spi_set_mosi
)
},
{
LSTRKEY
(
"transaction"
),
LFUNCVAL
(
spi_transaction
)
},
#if LUA_OPTIMIZE_MEMORY > 0
{
LSTRKEY
(
"MASTER"
),
LNUMVAL
(
PLATFORM_SPI_MASTER
)
},
{
LSTRKEY
(
"SLAVE"
),
LNUMVAL
(
PLATFORM_SPI_SLAVE
)
},
...
...
app/platform/platform.c
View file @
9cde0bbb
...
...
@@ -449,6 +449,32 @@ spi_data_type platform_spi_send_recv( unsigned id, spi_data_type data )
return
data
;
}
int
platform_spi_set_mosi
(
uint8_t
id
,
uint8_t
offset
,
uint8_t
bitlen
,
spi_data_type
data
)
{
if
(
offset
+
bitlen
>
512
)
return
PLATFORM_ERR
;
spi_mast_set_mosi
(
id
,
offset
,
bitlen
,
data
);
return
PLATFORM_OK
;
}
int
platform_spi_transaction
(
uint8_t
id
,
uint8_t
cmd_bitlen
,
spi_data_type
cmd_data
,
uint8_t
addr_bitlen
,
spi_data_type
addr_data
,
uint8_t
mosi_bitlen
,
uint8_t
dummy_bitlen
,
uint8_t
miso_bitlen
)
{
if
((
cmd_bitlen
>
16
)
||
(
addr_bitlen
>
32
)
||
(
mosi_bitlen
>
512
)
||
(
dummy_bitlen
>
256
)
||
(
miso_bitlen
>
512
))
return
PLATFORM_ERR
;
spi_mast_transaction
(
id
,
cmd_bitlen
,
cmd_data
,
addr_bitlen
,
addr_data
,
mosi_bitlen
,
dummy_bitlen
,
miso_bitlen
);
return
PLATFORM_OK
;
}
// ****************************************************************************
// Flash access functions
...
...
app/platform/platform.h
View file @
9cde0bbb
...
...
@@ -103,6 +103,12 @@ uint32_t platform_spi_setup( unsigned id, int mode, unsigned cpol, unsigned cpha
spi_data_type
platform_spi_send_recv
(
unsigned
id
,
spi_data_type
data
);
void
platform_spi_select
(
unsigned
id
,
int
is_select
);
int
platform_spi_set_mosi
(
uint8_t
id
,
uint8_t
offset
,
uint8_t
bitlen
,
spi_data_type
data
);
int
platform_spi_transaction
(
uint8_t
id
,
uint8_t
cmd_bitlen
,
spi_data_type
cmd_data
,
uint8_t
addr_bitlen
,
spi_data_type
addr_data
,
uint8_t
mosi_bitlen
,
uint8_t
dummy_bitlen
,
uint8_t
miso_bitlen
);
// *****************************************************************************
// UART subsection
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment