今天爲大家介紹的是ADI DSP一個很實用的功能,在上電的時候,SHARC DSP能夠作爲從啓動, 使用外部控制器啓動DSP程序。文中例程以ADI的SHARC 浮點DSP爲例,通過STM32F407芯片SPI接口發送DSP程序啓動,其他芯片原理也類似。
硬件方案
如圖,STM32通過SPI與SHARC DSP連接,STM32爲主,DSP爲從。圖中共6根線,其中IO1,IO2在啓動時只用到了其中一個IO1, MISO啓動程序無用。但都畫出來了,在後續的工作中有使用,本文只介紹啓動這一塊,所以只用到了4根線:IO1,MOSI,SPICLK,SPIDS。其中IO1用作STM32發送代碼的流速度控制。SPI的這幾根線相信大家都是很熟悉的,不再介紹。
需要說明的是DSP有2組SPI,必須使用第一組SPI作爲啓動。SPIDS的選擇必須是DPI_PBEN04,否則也是無法啓動。
軟件方案
這裏,定義IO1 爲高電平空閒,低電平忙。忙就是說此時MCU應該停止發送數據。當然也可以定義IO1爲高電平忙,低電平空閒,那就是說接下來修改的地方與本文有所差異了。本文中IO1連接的是DSP DPI_PBEN11 引腳。
1 . DSP 啓動代碼修改
從DSP安裝目錄(C:\Program Files (x86)\Analog Devices\VisualDSP 5.1.2\214xx\ldr) 中拷貝489_spi 工程出來。用VDSP打開工程下489_spi.asm文件,將ZERO_LDATA段和ZERO_L48段按以下代碼修改。
// ============================== ZERO_LDATA ===================================
// Use core to init 16/32/64-bit internal buffers to zero (saves space in LDR)
//------------------------------------------------------------------------------
ZERO_LDATA:
bit clr FLAGS FLG4;
nop;
nop;
I0=R3; //R3 passes destination address (LW, NW, or SW)
R0=0; //Value used to write zero's to memory
R1=0; //neighbor register used to write upper 32 bits if LW accesses
LCNTR=R2, DO ZERO_WRITE_END UNTIL lce; // R2 passes logical word count
ZERO_WRITE_END: DM(I0,M6)=R0; // write zero to x16, x32, or x64 memory
bit set FLAGS FLG4;
nop; nop;
JUMP READ_BOOT_INFO;// fetch next section-header
//================================ ZERO_L48 ===================================
// Use core to initialize 48/40-bit internal memory to zero
//------------------------------------------------------------------------------
ZERO_L48:
bit clr FLAGS FLG4;
nop;
nop;
I0=R3; //R3 passes destination address
PX=0;
LCNTR=R2, do L48_WRITE_END until lce;
L48_WRITE_END: dm(i0,m6)=PX;
bit set FLAGS FLG4;
nop;
nop;
JUMP READ_BOOT_INFO; // fetch next section-header
//==============================================================================
在user_init段中進行IO1的初始化。
user_init:
bit set FLAGS FLG4O;
nop;
nop;
bit clr FLAGS FLG4;
nop;
nop;
SRU(HIGH, DPI_PBEN11_I);
SRU(FLAG4_O,DPI_PB11_I);
......
bit set FLAGS FLG4;
nop;
nop;
rts;
修改完成後重新編譯工程,生成489_Spi.dxe。
2. 設置DSP 應用程序
如圖,在工程右鍵選擇project options,找到Load->General標籤,按照如下圖進行設置。當然Format也可以選擇其他,我這裏選擇8Bit二進制,是因爲實際上DSP程序是放在STM32內部Flash中。這裏要把剛剛編譯出來的內核文件填入箭頭的文本框,然後點擊確定。
至此DSP的設置已經完成,編譯應用工程,生成xxx.ldr。
3. STM32的設置
STM32的工作是將xxx.ldr二進制文件通過SPI發送。首先對STM32 SPI進行配置,源碼如下:
SPI_I2S_DeInit(spi);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = dataBit==SPI_DataSize_16b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(spi, &SPI_InitStructure);
SPI_Cmd(spi, ENABLE);
配置完成後,開始發送DSP程序。流程如下,這裏的p是short類型,16位。首先發送768*2字節到DSP,在DSP的datasheet中已經說明了爲什麼是1536字節,這裏也不再解釋,就這麼做吧。然後判斷IO狀態,低電平(忙)則等待。否則繼續發送。
GPIO_ResetBits(pdevice->GPIO_cs, pdevice->GPIO_cs_pin);
for(i=0 ;i < 768 ; i++){
spi->DR = p[i];
while ((spi->SR & SPI_I2S_FLAG_TXE) == RESET);
}
while(GPIO_ReadInputDataBit(pdevice->GPIO_busy,pdevice->GPIO_busy_pin) ==0);
for (; i < size; i++)
{
spi->DR = p[i];
while ((spi->SR & SPI_I2S_FLAG_TXE) == RESET);
while(GPIO_ReadInputDataBit(pdevice->GPIO_busy,pdevice->GPIO_busy_pin) ==0);
}
GPIO_SetBits(pdevice->GPIO_cs, pdevice->GPIO_cs_pin);
如果想要了解更多知識,可以關注公衆號【DSP-Tech】.你也可以加我微信,和我一起共同成長學習吧。