add SPI transaction support
This commit is contained in:
parent
8c419b8a3b
commit
9cde0bbb83
155
app/driver/spi.c
155
app/driver/spi.c
|
@ -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_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 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 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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) },
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue