📄 mqspi.c
字号:
/*
Neptune LTE Multiple-Queue SPI driver
----------------------------
(c) motoprogger 2008
*/
#include "../libs/motolibs.h"
#include "watchdog.h"
#include "gpio.h"
#include "mqspi.h"
typedef struct
{
hword configA;
hword configB;
} MQSPI_CSCFG;
typedef struct
{
hword statusA;
hword statusB;
} MQSPI_QST;
typedef struct
{
hword queueA;
hword queueB;
hword queueC;
} MQSPI_FQ;
typedef struct
{
hword pointer;
hword mode;
} MQSPI_SPICD;
#define MQSPI_BASE 0x24851000
#define MQSPI_MCON_REGISTER hword_ptr(MQSPI_BASE+0x000)
#define MQSPI_QCFG_L_REGISTER hword_ptr(MQSPI_BASE+0x002)
#define MQSPI_QCFG_H_REGISTER hword_ptr(MQSPI_BASE+0x004)
#define MQSPI_MTRIG_REGISTER hword_ptr(MQSPI_BASE+0x006)
#define MQSPI_STPR_L_REGISTER hword_ptr(MQSPI_BASE+0x008)
#define MQSPI_STPR_H_REGISTER hword_ptr(MQSPI_BASE+0x00A)
#define MQSPI_SDEF_REGISTER hword_ptr(MQSPI_BASE+0x00C)
#define MQSPI_SFLG_REGISTER hword_ptr(MQSPI_BASE+0x00E)
#define MQSPI_SFLG_REGISTER hword_ptr(MQSPI_BASE+0x00E)
#define MQSPI_SPIM_REGISTER hword_ptr(MQSPI_BASE+0x010)
#define MQSPI_STFF_L_REGISTER hword_ptr(MQSPI_BASE+0x012)
#define MQSPI_STFF_H_REGISTER hword_ptr(MQSPI_BASE+0x014)
#define MQSPI_STFE_L_REGISTER hword_ptr(MQSPI_BASE+0x016)
#define MQSPI_STFE_H_REGISTER hword_ptr(MQSPI_BASE+0x018)
#define MQSPI_QRE_L_REGISTER hword_ptr(MQSPI_BASE+0x01A)
#define MQSPI_QRE_H_REGISTER hword_ptr(MQSPI_BASE+0x01C)
#define MQSPI_SDI_MD_L_REGISTER hword_ptr(MQSPI_BASE+0x01E)
#define MQSPI_SDI_MD_H_REGISTER hword_ptr(MQSPI_BASE+0x020)
#define MQSPI_CDPS1_REGISTER hword_ptr(MQSPI_BASE+0x022)
#define MQSPI_CDMS1_REGISTER hword_ptr(MQSPI_BASE+0x024)
#define MQSPI_CDPS2_REGISTER hword_ptr(MQSPI_BASE+0x026)
#define MQSPI_CDMS2_REGISTER hword_ptr(MQSPI_BASE+0x028)
#define MQSPI_CSCFG_REGISTERS ((volatile MQSPI_CSCFG * ) ((void * ) (MQSPI_BASE+0x02A)))
#define MQSPI_QST_REGISTERS (MQSPI_QST * ) ((void * ) (MQSPI_BASE+0x052))
#define MQSPI_SST_REGISTER hword_ptr(MQSPI_BASE+0x05A)
#define MQSPI_FQ_REGISTERS (MQSPI_FQ * ) ((void * ) (MQSPI_BASE+0x05C))
#define MQSPI_CONTROL_DATA_RAM ((MQSPI_SPICD * ) ((void * ) (MQSPI_BASE+0x400)))
#define MQSPI_IO_DATA_RAM ((hword * ) ((void * ) (MQSPI_BASE+0x480)))
#define set_bit(hw_l,hw_h,bit,cond) { \
hword reg,mask; \
mask=1<<(bit&15); \
if (bit<16) reg=hw_l; \
else reg=hw_h; \
if (!(cond)) reg&=~mask; \
else reg|=mask; \
if (bit<16) hw_l=reg; \
else hw_h=reg; \
}
#define block_hword_offset(block) (block<<4)
word triggers;
hword mem_blocks; /* 32 bytes each, 512 bytes => 16 blocks */
word trig_assign[64]; /* 0-31 for write, 32-63 for read, 255=no block assigned */
hword bus_sel; /* A bus select bit per chip-select */
void mqspi_reset(byte bus)
{
hword mask;
byte i;
switch(bus)
{
case MQSPI_BUS_ALL:
mask=4;
break;
case MQSPI_BUS_1:
mask=2;
break;
case MQSPI_BUS_2:
mask=1;
break;
default:
mask=0;
break;
}
MQSPI_MCON_REGISTER|=mask;
while(MQSPI_MCON_REGISTER&mask);
if (bus==MQSPI_BUS_ALL)
{
triggers=0;
mem_blocks=0;
for (i=0; i<64; i++) trig_assign[i]=255;
}
}
void mqspi_enable(byte bus, bool enable)
{
hword mask,cr;
cr=MQSPI_MCON_REGISTER;
switch(bus) {
case MQSPI_BUS_ALL:
mask=0x20;
break;
case MQSPI_BUS_1:
mask=0x10;
break;
case MQSPI_BUS_2:
mask=8;
break;
default:
mask=0;
break;
}
if (enable) cr|=mask;
else cr&=~mask;
MQSPI_MCON_REGISTER=cr;
}
void mqspi_configure_cs(byte cs, byte bus, byte clkdiv, byte flags, byte dat, byte dbt)
{
if (cs<10 && bus==MQSPI_BUS_1 || bus==MQSPI_BUS_2)
{
MQSPI_CSCFG_REGISTERS[cs].configA=((clkdiv-1)&0x7f)<<5|flags&MQSPI_CSCFG_FLAGS_MASK;
MQSPI_CSCFG_REGISTERS[cs].configB=(dat&0x7f)<<7|dbt&0x7f;
if (bus==MQSPI_BUS_1) bus_sel&=~(1<<cs);
else bus_sel|=1<<cs;
}
}
byte mqspi_get_trigger()
{
byte i;
for (i=0; i<32; i++)
{
if (!(triggers&1<<i))
{
triggers|=1<<i;
return i;
}
}
return 255;
}
void mqspi_trigger_config(byte trigger, byte priority, byte count, byte cs)
{
hword reg;
if (trigger<32 && (triggers&1<<trigger) && priority==MQSPI_PRIORITY_NORMAL || priority==MQSPI_PRIORITY_HIGH && count>0 && count<=64 && cs<10)
{
set_bit(MQSPI_STPR_L_REGISTER,MQSPI_STPR_H_REGISTER,trigger,priority==MQSPI_PRIORITY_HIGH);
reg=MQSPI_CONTROL_DATA_RAM[trigger].mode;
reg&=0x1F0;
reg|=cs&0xF|((count-1)&0x3F)<<9;
MQSPI_CONTROL_DATA_RAM[trigger].mode=reg;
}
}
byte mqspi_alloc()
{ word i;
for (i=0; i<16; i++)
if (!(mem_blocks&1<<i))
{
mem_blocks|=1<<i;
return i;
}
return 255;
}
void mqspi_free(byte block)
{
mem_blocks&=~(1<<block);
}
void mqspi_trigger_free_buffs(byte trigger)
{
if (trig_assign[trigger]!=255)\
{
mqspi_free(trig_assign[trigger]);
trig_assign[trigger]=255;
}
if (trig_assign[trigger+32]!=255)
{
mqspi_free(trig_assign[trigger+32]);
trig_assign[trigger+32]=255;
}
}
bool mqspi_trigger_alloc_buffs(byte trigger,bool read)
{
byte wbuf,rbuf;
mqspi_trigger_free_buffs(trigger);
wbuf=mqspi_alloc();
if (wbuf==255) return false;
if (read)
{
rbuf=mqspi_alloc();
if (rbuf==255)
{
mqspi_free(wbuf);
return false;
}
}
else rbuf=255;
trig_assign[trigger]=wbuf;
trig_assign[trigger+32]=rbuf;
return true;
}
bool mqspi_trigger_assign_data(byte trigger, hword * data, byte msglen, bool read)
{
if (trigger<32 && triggers&(1<<trigger) && msglen>0 && msglen<=32)
{
hword i,reg,wbase,rbase;
wbase=trigger<<4;
set_bit(MQSPI_QRE_L_REGISTER,MQSPI_QRE_H_REGISTER,trigger,read);
if (!mqspi_trigger_alloc_buffs(trigger,read)) return false;
wbase=block_hword_offset(trig_assign[trigger]);
if (read) rbase=block_hword_offset(trig_assign[trigger+32]);
else rbase=0;
MQSPI_CONTROL_DATA_RAM[trigger].pointer=wbase<<8|rbase;
reg=MQSPI_CONTROL_DATA_RAM[trigger].mode;
reg&=~0x1F0;
reg|=(msglen-1)<<4;
for (i=0; i<(msglen+1)>>1; i++) MQSPI_IO_DATA_RAM[wbase+i]=data[i];
return true;
}
return false;
}
void mqspi_trigger_activate(byte trigger)
{
if (trigger<0x20)
{
MQSPI_MTRIG_REGISTER=trigger&0x1f|0x20;
if (trigger<0x10) MQSPI_STFF_L_REGISTER=1<<trigger;
else MQSPI_STFF_H_REGISTER=1<<(trigger-0x10);
}
}
bool mqspi_trigger_check_busy(byte trigger)
{
if (trigger<0x20)
{
if (trigger<0x10) return !(MQSPI_STFF_L_REGISTER&(1<<trigger));
else return !(MQSPI_STFF_H_REGISTER&(1<<(trigger-0x10)));
}
return false;
}
void mqspi_trigger_wait(byte trigger)
{
while(mqspi_trigger_check_busy) wdog_service();
}
bool mqspi_trigger_fetch_data(byte trigger, hword * data)
{
byte rbase,msglen,i;
if (trigger<32 && trig_assign[trigger+0x20]!=255)
{
rbase=MQSPI_CONTROL_DATA_RAM[trigger].pointer&0xff;
msglen=MQSPI_CONTROL_DATA_RAM[trigger].mode>>4&0x1f+1;
for (i=0; i<(msglen+1)>>1; i++) data[i]=MQSPI_IO_DATA_RAM[rbase+i];
return true;
}
return false;
}
void mqspi_trigger_free(byte trigger)
{
mqspi_trigger_free_buffs(trigger);
triggers&=~(1<<trigger);
}
bool mqspi_transcieve(hword *wdata, hword *rdata, byte length, byte cs, byte count, byte priority)
{
byte trig;
trig=mqspi_get_trigger();
if (trig==255) return false;
mqspi_trigger_config(trig,priority,count,cs);
if (!mqspi_trigger_assign_data(trig,wdata,length,rdata!=0))
{
mqspi_trigger_free(trig);
return false;
}
mqspi_trigger_activate(trig);
mqspi_trigger_wait(trig);
if (rdata!=0) mqspi_trigger_fetch_data(trig,rdata);
mqspi_trigger_free(trig);
return true;
}
void mqspi_init()
{
/* TODO: write init */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -