核磁專案3月22日@TOC
CMD檔案的解讀
將此引腳置為低電平,表示為微電腦模式,向量表指向Boot Rom。
1 | ROM : origin = 0x3FF000, length = 0x000FC0 /* boot ROM available if MP/MCn=0 */ |
程式從這兒開始。
再看看儲存器映像。
分配程式空間
1 | PRAMH0 : origin = 0x3f8000, length = 0x003000boot ROM available if MP/MCn=0 */ |
但是存在一個問題,就是我佔用了保留的空間,因為CMD命令顯示程式空間不夠,很可能會出問題。如果出問題了,第一個解決辦法是,將程式空間放到外擴RAM Zone2中,因為上傳的資料花不了那麼空間;第二個辦法就是換晶片,換個RAM空間多一點的晶片。
PAGE 1 就是分配資料空間,注意要對應起來,外設和一些C的資料空間,一般模板是兩個CMD檔案,我只用了一個檔案。
如果說 MEMORY 命令是定義每個東西的位置。那麼SECTION命令就是,將所有相關的程式,資料分配到固定位置。
main函式的解讀
一些加標頭檔等等的操作不在贅述。包括對資料夾的設定,什麼檔案怎麼放等等。
首先定義一些網路相關的變數
1 2 3 4 5 6 | uint8 server_ip[4]={<!-- -->192,168,1,101}; uint16 server_port=5000; uint16 local_port=6000; uint16 len=0; uint8 buffer[2048]; boot ROM available if MP/MCn=0 */ |
網路客戶端連接埠,網路客戶端ip,本地連接埠,
len代表socket快取裡面還剩餘的空間,buffer陣列存的是從W5500裡面讀取到的資料。這個下文再分析
對系統的初始化
關看門狗;
1 2 3 4 5 6 | void DisableDog(void) {<!-- --> EALLOW; SysCtrlRegs.WDCR= 0x0068; EDIS; } |
初始化鎖相環,定義時鐘;
1 2 3 | EALLOW; SysCtrlRegs.PLLCR.bit.DIV = val; EDIS; |
Val 就是一個數,4-bit PLL Select。時鐘=外部時鐘*Val/2
初始化外設時鐘
1 2 3 4 5 | SysCtrlRegs.HISPCP.all = 0x0000; SysCtrlRegs.LOSPCP.all = 0x0002; SysCtrlRegs.PCLKCR.bit.EVAENCLK=1; SysCtrlRegs.PCLKCR.bit.EVBENCLK=1; SysCtrlRegs.PCLKCR.bit.SPIENCLK=1; |
這些外設時鐘一般都是預設的高速還是低速時鐘,高速和低速時鐘是透過主頻分頻而來。如上程式碼所示,高速不分頻,低速分兩次,就是除以4.本專案晶振為10M,主頻50M,高速50M,低速12,5M.事件A,B都是高速。spi為低速。此處存在一個問題,中斷的時鐘開不開。
對SPI的GPIO口的初始化
硬體如圖。四個介面分別為F1,F2,F3,F4
1 2 3 4 5 6 7 8 9 10 | void InitSpiaGpio(void) {<!-- --> EALLOW; GpioMuxRegs.GPFMUX.bit.SPISIMOA_GPIOF0=1; GpioMuxRegs.GPFMUX.bit.SPISOMIA_GPIOF1=1; GpioMuxRegs.GPFMUX.bit.SPICLKA_GPIOF2=1; GpioMuxRegs.GPFMUX.bit.SPISTEA_GPIOF3=1; EDIS; } |
程式直接如圖,2812貌似不用設定方向和上拉什麼的,只需要配置為SPI的介面,這個存疑。也就是他的復用。配置為普通IO的話,暫存器寫0,復用外設則寫1。
對SPI的重定IO口的初始化
存在疑惑,它的中斷需不需要用上,由圖,gpioa9,配置他的io和方向,是一個輸出。程式碼如圖
1 2 3 4 5 6 7 | void gpio_config(void) {<!-- --> EALLOW; GpioMuxRegs.GPAMUX.bit.CAP2Q2_GPIOA9=0;//GPA9 RSTn,設定為i/o GpioMuxRegs.GPADIR.bit.GPIOA9= 1;//方向輸出;1:輸出;0:輸入 EDIS; } |
然後是一些關中斷的操作
對SPI本身的初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 | void spi_init() {<!-- --> SpiaRegs.SPICCR.bit.SPISWRESET = 0;//重定SPI SpiaRegs.SPICCR.all = 0x000F; //0000 0000 0000 1111 //0~3,位元組控制為16位;4,禁止SPI回送;5,保留;6,上升輸出,下降輸入;7,重定 SpiaRegs.SPICTL.all = 0x0006; // 00000000 0000 0110 中斷無效,使能發送引腳,主機模式 無相位延時 禁止中斷 // Enable master mode, normal phase, // enable talk, and SPI int disabled. SpiaRegs.SPISTS.all = 0x0000; //溢位中斷,禁止SPI中斷; 重定系統 SpiaRegs.SPIBRR = 0x0009; //SPI波特率=12.5M/10=1.25MHZ;0000 1001 SpiaRegs.SPIPRI.bit.FREE = 1; //Set so breakpoints don't disturb xmission SpiaRegs.SPICCR.bit.SPISWRESET = 1; } |
這兒就需要查暫存器進行一個修改了,DSP做主機,W5500做從機
波特率設定
SPICCR暫存器:此暫存器0~3位決定在一個移送序列中,作為單個字元被移動的位的數量這裡我們設定為16位。
此暫存器的第6位代表的時鐘極性,透過兩個位才能確定SPI發送和接收的方式。一個是SPICCR.CLKPOLARITY,一個是SPCTL.CLK_PHASE。共有四種方式。但是W5500只支援兩種,0和3。問題來了,主機和從機的模式是否一致,還是只需要設定主機的模式。我認為應該只用設計主機的模式,所以我設定為模式0。上升沿發送,下降沿接收,無延時
SPIPRI 這個設定為x 1 ,忽略了中斷,可能會有問題。
重定W5500
1 2 3 4 5 6 7 | void Reset_W5500(void)//reset {<!-- --> GpioDataRegs.GPADAT.bit.GPIOA9 = 0; delay_loop(); GpioDataRegs.GPADAT.bit.GPIOA9 = 1; delay_loop(); } |
設定預設網路相關的變數
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | void set_default(void) // 設定預設MAC、IP、GW、SUB、DNS {<!-- --> uint8 mac[6]={<!-- -->0x00,0x08,0xdc,0x11,0x11,0x11}; uint8 lip[4]={<!-- -->192,168,1,88}; uint8 sub[4]={<!-- -->255,255,255,0}; uint8 gw[4]={<!-- -->192,168,1,1}; uint8 dns[4]={<!-- -->8,8,8,8}; memcpy(ConfigMsg.lip, lip, 4); //printf("lip: %d.%d.%d.%d ",lip[0],lip[1],lip[2],lip[3]); memcpy(ConfigMsg.sub, sub, 4); //printf("sub: %d.%d.%d.%d ",sub[0],sub[1],sub[2],sub[3]); memcpy(ConfigMsg.gw, gw, 4); //printf("gw: %d.%d.%d.%d ",gw[0],gw[1],gw[2],gw[3]); memcpy(ConfigMsg.mac, mac,6); memcpy(ConfigMsg.dns,dns,4); //printf("dns: %d.%d.%d.%d ",dns[0],dns[1],dns[2],dns[3]); ConfigMsg.dhcp=0; ConfigMsg.debug=1; ConfigMsg.fw_len=0; ConfigMsg.state=NORMAL_STATE; ConfigMsg.sw_ver[0]=FW_VER_HIGH; ConfigMsg.sw_ver[1]=FW_VER_LOW; } |
除錯網路的時候肯定得改一些IP地址什麼的。
設定網路,
1 2 3 4 5 | 向W5500寫入什麼東西,mac,sub,gw lip。 值得關注的是對Socket的初始化,將他的Socket 0 調成16K 程式碼: uint8 txsize[MAX_SOCK_NUM] = {<!-- -->16,0,0,0,0,0,0,0}; // 選擇8個Socket每個Socket發送快取的大小,在w5500.c的void sysinit()有設定過程 uint8 rxsize[MAX_SOCK_NUM] = {<!-- -->16,0,0,0,0,0,0,0}; // 選擇8個Socket每個Socket接收快取的大小,在w5500.c的void sysinit()有設定過程 |
while1程式
首先是一個Switch
去讀取Sn_SR暫存器的值,看他是否為0x13
代表為TCP工作模式。然後根據連接埠和IP連接。
1 2 | case SOCK_INIT: connect(0, server_ip,server_port); |
然後再讀,是否為0x17
代表連接成功,進行下一步。
讀取該位,Sn_IR_CON,表示建立連線。
讀取Sn_RX_RSR,len=getSn_RX_RSR(0);看他還有多少空間
Sn_RX_RSR 顯示了 Socket n 接收快取中已接收和儲存的資料大小。
len不為0,
1 2 3 4 5 6 7 | if(len>0) {<!-- --> //memset(buffer,'0',strlen(buffer)); recv(0,buffer,len); send(0,buffer,len); } |
這樣就把w5500裡面的資料,存到了buffer陣列裡面,然後在sendbuffer裡面的資料到W5500.就完成了一個LOOPback的迴環。