久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

專注電子技術學習與研究
當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

2440裸機學習心得(下)

作者:佚名   來源:本站原創   點擊數:  更新時間:2012年03月19日   【字體:

 

       攝像頭驅動
一些概念:
攝像接口的主時鐘信號由USB PLL產生,它的頻率為96MHz,再經過分頻處理后輸出給攝像頭,攝像頭再根據該時鐘信號產生三個同步時鐘信號(像素時鐘、幀同步時鐘和行同步時鐘),反過來再輸入回s3c2440
OV9650內部有大量的寄存器需要配置,這就需要另外的數據接口。
OV9650的數據接口稱為SCCB(串行攝像控制總線),它由兩條數據線組成:一個是用于傳輸時鐘信號的SIO_C,另一個是用于傳輸數據信號的SIO_DSCCB的傳輸協議IIC的極其相似,只不過IIC在每傳輸完一個字節后,接收數據的一方要發送一位的確認數據,而SCCB一次要傳輸9位數據,前8位為有用數據,而第9位數據在寫周期中是Don’t-Care(即不必關心位),在讀周期中是NA位。SCCB定義數據傳輸的基本單元為相(phase),即一個相傳輸一個字節數據。
SCCB只包括三種傳輸周期,即3相寫傳輸周期(三個相依次為設備從地址,內存地址,所寫數據),2相寫傳輸周期(兩個相依次為設備從地址,內存地址)和2相讀傳輸周期(兩個相依次為設備從地址,所讀數據)。當需要寫操作時,應用3相寫傳輸周期,當需要讀操作時,依次應用2相寫傳輸周期和2相讀傳輸周期。(這些讀寫和IIC一樣~
 
OV9650有兩個只讀寄存器——0x1C0x1D,用于存放廠家ID,數據分別為0x7F0xA2,我們可以通過讀取它們來判斷s3c2440是否連接了OV9650。當確認連接了OV9650后,我們就可以把VGA640×480)模式下YUV彩色空間的配置數組寫入OV9650  (二維數組:第一個表示寄存器地址,第二個表示要寫入的數據
 
注意比較三個變量的含義:
Width          = 640                     //源寬度
PrDstWidth   =480                   //目標寬度
SrcWidth      =640 - WinHorOffset*2;      //偏移后寬度
驅動函數編寫步驟:
         外圍基礎準備硬件初始化
IIC初始化 LCD初始化 UPLL時鐘初始化(96M, 0V9650系統時鐘)
GPIO初始化(GPJ),硬件和軟件復位攝像頭(GPJ12CAMERARESETrCIGCTRL
         0V9650寄存器配置
A、讀取OV9650廠商ID,驗證是否工作
      B、復位所有OV9650寄存器
      C、配置OV9650寄存器(用規定的二維數組直接配)
         攝像頭接口初始化
        攝像頭接口的一些寄存器初始化:rCIGCTRLrCIWDOFST rCISRCFMT
      rCIPRTRGFMTrCIPRTAREA
B、設置內存首地址為LCD緩存數組首地址    rCIPRCLRSA1~4
C、計算水平和垂直縮放比率和位移量,以及主水平、垂直比率
放入以下三個寄存器中rCIPRSCPRERATIOrCIPRSCPREDST rCIPRSCCTRL
         中斷函數開啟和指向
         控制臺菜單的編寫與實現
        顯示視頻
rCIPRSCCTRL|=(1<<15);                   //預覽縮放開啟
      rCIIMGCPT =(1<<31)|(1<<29);          //預覽縮放捕捉使能
        截圖,定格
rCIPRSCCTRL &=~(1<<15);                   //預覽縮放關閉
rCIIMGCPT &=~((1<<31)|(1<<29));          //預覽縮放捕捉不使能
視頻定格后,LCD_BUFFER數組就是圖像數據
        放大,縮小
調節偏移量HOffsetVOffset,每次改變后重新初始化攝像頭接口
 
四個額外寫出需注意的函數:
1、計算主突發長度和剩余突發長度         CalculateBurstSize
2/計算預縮放比率及移位量                 CalculatePrescalerRatioShift
3、中斷函數(只清中斷,不干別的)       camera_interrupt 
4SCCB總線函數的讀寫(像IIC    Rd_SCCBWr_SCCB
 
 
 
 
 
   網卡驅動
DM9000的一些基本概念
DM9000對外來說只有兩個端口——地址口和數據口,地址口用于輸入內部寄存器的地址,而數據口則完成對某一寄存器的讀寫。DM9000CMD引腳用來區分這兩個端口,當CMD引腳為0時,DM9000的數據線上傳輸的是寄存器地址,當CMD引腳為1時,傳輸的是讀寫數據
       我們把DM9000A8A9接為高電平,把A4~A7接為低電平,并且把DM9000AEN接到s3c2440nGCS4引腳上,則DM9000的端口基址為0x20000300,如果再把DM9000CMD引腳接到s3c2440ADDR2引腳上0x20000304(怎么計算?)
查了一下書,是和存儲控制器有關系,每個nGCSx對應128M地址空間,8nGCSx對應1G地址。
nGCS4剛好對應0x20000000開始的地址,但為什么是0x20000300?
再加上IObase300
如果將 DM9000CMD引腳接到s3c2440ADDR2,由于CMD引腳的高低電平決定地址口和數據口,那么,ADDR20時,訪問的
就是地址口,所以地址口的起始地址為 ARRD20的情況,即0x20000000 ADDR21時,(LADDR3~LADDR0 = 0100)訪問的就是數
據口,所以數據口的地址即 0x20000004
如果要寫入DM9000中的某個寄存器,則先把該寄存器的地址賦予DM_ADDR_PORT,然后再把要寫入的數據賦予DM_DATA_PORT即可。讀取DM9000中的某個寄存器也類似。
DM9000寄存器介紹在數據手冊11頁開始:
 
DM9000內部有0x3FF大小的SRAM用于接受和發送數據緩存。在發送或接收數據包之前,數據是暫存在這個SRAM中的。當需要連續發送或接收數據時,我們需要分別把DM9000寄存器MWCMDMRCMD賦予數據端口,這樣就指定了SRAM中的某個地址,并且在傳輸完一個數據后,指針會指向SRAM中的下一個地址,從而完成了連續訪問數據的目的。
 
基于ARP協議的DM9000編寫步驟
         初始化EINT7中斷,設置中斷函數入口
       因為DM9000的數據中斷引腳INT是連接到s3c2440的外部中斷7引腳上的
         編寫好讀和寫DM9000寄存器函數,用其配置DM9000的寄存器
       并使其用中斷方式接收網卡數據,查詢方式發送數據
       (這步挺難的,很多寄存器要配置,對照著Datasheet和別人的程序)
       注:DM9000內的寄存器的地址宏定義時,不用管基址,直接按OFFSET定義
         編寫好DM9000發送和接受函數(位寬為16
分別把DM9000寄存器MWCMDMRCMD賦予數據端口
       接受數據時要注意,按照規定的格式來編寫
         定義一個符合ARP協議格式的數組,用于數據傳輸
將該數組作為發送函數形參發給PC機請求包
         編寫中斷函數,清屏蔽
將接收函數中的數組內容,用串口打印出控制臺
 
 
 
   SD卡驅動
SD(全名為Secure Digital Memory Card,安全數碼卡)
 s3c2440集成了SD控制器,可以方便地讀寫SDMMC和對SDIO進行操作。
可以用SDIO控制器來編,也可用SPI總線來編
SDIO的應用是未來嵌入式系統最重要的接口技術之一,會取代目前GPIO式的SPI接口
 
具體的CMD 命令協議內容自己看回資料了。
我使用的SD卡為手機的內存卡(不是MMC),型號為SDHC_V20_CARD,支持 PLV2.0協議
主要講  編寫簡單的SD讀寫步驟:
         準備工作,編寫要使用到一堆東西:
         檢查SDIO命令發送,接收是否結束函數Chk_CMD_End(int cmd, int be_resp)
         使用到的 CMD ACMD 函數(這部分要配置寄存器,要查值,比較難,參考別人的吧)
         編寫一個要用的結構體SD_STRUCT,用于記錄cCardTypeiCardRCA
         SD卡識別模式:
初始化:時鐘400KType B, clk enableSD卡模式,FIFO reset
CMD 0 ——》reset指令
CMD 8——》工作電壓范圍,初始化SDHC卡,看是否支持PLV2.0,返回類型
CMD 55——》RCA0x0,使用ACMD41前必須使用
ACMD 41——》識別卡能否在給定的VDD下工作
CMD 2——》查卡的CID 信息
CMD 3——》要求系統給SD卡發送一個新相對地址 RCA
改時鐘頻率:25M,準備進入transfer狀態
CMD 7——》進入 transfer狀態
ACMD 6——》設置總線寬度為 4bit
 
         數據傳輸模式:
若需要擦除:
{
 CMD 32——》start address
 CMD 33——》end address
 CMD 38 ——》erase
}注意:擦除后必須要進行復位,即重新初始化前面步驟,不然不能進行讀寫
 
單塊寫      多塊寫
       CMD 7——》transfer模式
       單塊讀多塊讀
 
拓展:
將攝像頭捕捉的圖像,寫進SD卡中,然后再還原顯示出來
注意一個點:
就是要將LCD_BUFFER[480][272]的二維數組轉化LCD_BUFFER_SD[480*272]一維
一個疑問?好像只需 51200就可將整幅圖像都顯示出來,而不需要480*272那么多
 
附加部分(有空研究):
文件系統的構建:
 
 
 
 
12NORFLASH 操作
norflashEN29LV160AB
norflash的操作主要就是讀、寫、擦除和識別
EN29LV160AB的數據寬度可以是8位字節型,也可以是16位的字型,它由某一引腳配置實現的。在這里我們選擇字型
BYTE#位置硬件接地,直接默認為Word Mode16位)
寫操作只能使“1”變為“0”,而只有擦除才能使“0”變為“1”。因此在寫之前一定要先擦除
norflash另一個比較常用的操作是讀取芯片的ID
NorFlash啟動,nGCS0NorFlash,起始地址為0x00x0000 0000 0x0800 0000NorFlash
 
注意幾個地方:
1#define    CMD_ADDR0              *((volatile U16 *)(0x555<<1+flash_base))
之所以又把norflash中的地址向左移一位(即乘以2),是因為我們是把s3c2440ADDR1連接到了norflashA0上的緣故,(自己看原理圖),容易理解,等于本來最低位的數被推后沒了,要左移拉回來。
 
2check_toggle函數(校驗函數)中
      oldtoggle = *((volatile U16 *)0x0);   newtoggle = *((volatile U16 *)0x0);
      表示兩次讀值
if((oldtoggle & 0x40)==(newtoggle & 0x40))       //表示兩次的DQ6是否相同
if(newtoggle & 0x20)           //DQ5是否為1
 
幾個常用的函數:
讀函數       read_en29lv160ab(U32 addr)
return *((volatile U16 *)(addr));// 數據要轉為16
寫函數       en29lv160ab_program(U32 addr, U16 dat)
第一個周期是把命令0xAA寫入地址為0x555的命令寄存器中,
第二個周期是把命令0x55寫入地址為0x2AA命令寄存器中,
第三個周期是把命令0xA0再寫入地址為0x555命令寄存器中,
第四個周期為真正地把要寫入的數據寫入到norflash的地址中。
復位函數         reset_en29lv160ab(void)
              是向任一地址寫入復位命令0xF0
擦除函數    en29lv160ab_sector_erase(U32 section_addr)
              第一個周期是把命令0xAA寫入地址為0x555的命令寄存器中,
第二個周期是把命令0x55寫入地址為0x2AA命令寄存器中,
第三個周期是把命令0x80再寫入地址為0x555命令寄存器中,
第四個周期是把命令0xAA寫入地址為0x555的命令寄存器中,
第五個周期是把命令0x55再寫入地址為0x2AA命令寄存器中,
第六個周期是把命令0x30寫入要擦除塊的首地址內
驗證函數    check_toggle()
              連續兩次讀取數據總線上的數據,判斷數據總線上的第6位數值(DQ6)是否翻轉,如果沒有翻轉則正確,否則還要判斷第5位(DQ5),以確定是否是因為超時而引起的翻轉。
ID函數 get_en29lv160ab_id()
第一個周期是把命令0xAA寫入地址為0x555的命令寄存器中,
第二個周期是把命令0x55寫入地址為0x2AA命令寄存器中,
第三個周期是把命令0x90再寫入地址為0x555命令寄存器中,
第四個周期為讀取地址為0x100中的內容,即廠商ID0x1C)。
讀取設備ID的過程的前三個周期與讀取廠商ID相同,第四個周期是讀取地址為0x01中的內容,即設備ID0x2249
 
問題1
原來真的是寫得塊地址問題,寫到前面的0x400就行,寫后一點如0xf0000就讀不出來了,0x0000 0000 0x0800 0000NorFlash,為什么后面的不行呢?
 
 
 
 
問題2
本來擦除后寫完能讀出寫的內容,但再復位后不寫,只讀回上次地址,發現讀出不同的數據
 
而且好像擦除后就算返回return 1也沒用,擦后讀回那地址,也不是全部數據為0的,也是有值的
 
 
13NANDFLASH操作
nandflashK9F2G08U0A,它是8位的nandflash
一個劣勢是很容易產生壞塊,因此在使用nandflash時,往往要利用校驗算法發現壞塊并標注出來
K9F2G08U0A的一頁為(2K64)字節(加號前面的2K表示的是main區容量,加號后面的64表示的是spare區容量),它的一塊為64頁,而整個設備包括了2048個塊
內存容量大小計算:
 
要實現用8IO口來要訪問這么大的容量,K9F2G08U0A規定了用5個周期來實現。
列地址是用于尋址頁內空間,行地址用于尋址頁,如果要直接訪問塊,則需要從地址A18開始。
 
CMD_STATUS讀狀態命令可以實現讀取設備內的狀態寄存器,通過該命令可以獲知寫操作或擦除操作是否完成(判斷第6位),以及是否成功完成(判斷第0位)。
 
 
自己編寫NANDFLASH的步驟:(進行塊擦除,頁寫,頁讀)
1、在頭文件中列出相關的固量 和 函數 宏
             常用的各種命令集;一些基于NANDFLASH控制器的基本函數
             ECC應用和使能nandflash片選;NFSTAT寄存器
             一些返回判斷值的宏定義
2、寫出幾個基本的初始化函數:
        管腳,寄存器初始化函數 ; 復位函數 ; 讀NAND ID號函數
3、相關的檢測判斷函數:
        A、檢測是否寫擦除成功函數NF_toggle:通過NF_CMD(CMD_STATUS)狀態位                
        B、測試是否壞塊函數NF_testBadBlock:讀取2054處壞塊標志位
        C、寫壞塊標志函數NF_MarkBadBlock:寫標志到 2054處
4、讀、寫、擦除函數:
        具體自己看代碼了,有兩點要注意了:
        A、讀操作 檢測正確性是通過ECC檢驗碼,而寫和擦除是通過toggle函數
        B、隨機讀寫 是 在讀頁,寫頁的基礎上 加上的部分
 
注意區別兩個東西:
1、ECC檢驗碼的判斷
讀操作來說,我們還要繼續讀取spare區的相應地址內容,已得到上次寫操作時所存儲的main區和spare區的ECC,并把這些數據分別放入NFMECCD0/1NFSECCD的相應位置中。最后我們就可以通過讀取NFESTAT0/1(因為K9F2G08U0A8IO口,因此這里只用到了NFESTAT0)中的低4位來判斷讀取的數據是否正確,其中第0位和第1位為main區指示錯誤,第2位和第3位為spare區指示錯誤。
 
2、壞塊的判斷
對于寫頁和擦除操作來說,通過toggle函數檢測:
NF_CMD(CMD_STATUS);                 //讀狀態命令
//判斷狀態值的第6位是否為1,即是否在忙
//判斷狀態值的第0位是否為0,為0則寫操作正確,否則錯誤
    若第0位操作錯誤,則該塊為 壞塊
3main區和spare區的解鎖只為了產生ECC碼,一旦產生后,就要鎖上,打開另外區的,不要影響互相順序的ECC碼產生
 
 
擴展:從NANDFLASH啟動程序
當檢測到是由nandflash啟動時,系統會自動把nandflash中的前4k字節的數據加載到Steppingstone中,然后把該Steppingstone映射為Bank0,因此系統會從Steppingstone開始運行程序,從而實現了s3c2440nandflash自啟動的功能
通過在Steppingstone中,把程序的其余部分復制到RAM中,程序運行時由Steppingstone轉移到該RAM中,SRAM起始地址0x30000000
 RdNF2SDRAMC語言編寫的一段把nandflash中的數據復制到SRAM的程序
看看這函數,了解一下就行了
 
 
附加:nandflash、norflash、SDRAM的區別:
ROM在系統停止供電的時候仍然可以保持數據,
RAM通常都是在掉電之后就丟失數據,典型的RAM就是計算機的內存。
SRAM速度非常快,是目前讀寫最快的存儲設備了,但是它也非常昂貴,所以只在要求很苛刻的地方使用,譬如CPU的一級緩沖,二級緩沖
動態RAMDynamic RAM/DRAM),DRAM保留數據的時間很短,速度也比SRAM慢,不過它還是比任何的ROM都要快,但從價格上來說DRAM相比SRAM要便宜很多,計算機內存就是DRAM

RAM
SRAM
DRAM
SDRAM,DDR RAM等
ROM
EROM,E2PROM等
NANDFLASHNORFALSH
 

 
 
 
 
 
 
 
 
 
 


 

NORNAND是現在市場上兩種主要的非易失閃存技術。Intel1988年首先開發出NOR flash技術,徹底改變了原先由EPROMEEPROM一統天下的局面
NOR比較好操作,因為集成了系統地址線和數據線在芯片內,而NAND只有8I/O,要操作,還需要結合相應硬件,如2440里有的 NAND控制器。
 
 
14、基于OHCIUSB主機(僅做了枚舉)
發現了一個很好的博客講這個的:http://lancelot.blog.51cto.com/393579/328233
部分經典內容摘要:
OHCI規范中,最重要的幾個概念是端點(EndPoint - ED)、傳輸描述符(Transport Descriptor - TD)、主機控制器通信區(HCCA)。其中ED負責確定傳輸類型(控制傳輸、批量傳輸、同步傳輸和中斷傳輸)。TD確定傳輸參數。HCCA用于確定數據傳輸是否完畢。
 
OHCI(基本流程)
進行控制/批量傳輸的主要處理流程如下:
1、創建控制/批量傳輸的ED列表;
2、創建ED下的TD列表;
3、設置命令到相應寄存器開始數據傳輸;
4、在中斷處理程序中判斷數據傳輸是否結束;
 
在OHCI層,主要完成如下功能:
 通過控制端口讀寫數據(包含SETUP、DATA、STATUS等3個TD);
 通過控制端口發送設置命令(沒有DATA的TD);
 通過批量端口讀數據;
 通過批量端口寫數據;
 中斷處理程序;
 
OHCI的體系下,判斷數據是否傳輸完畢是需要通過中斷程序來判斷的,當USB主機設置了HcControlHcCommandStatus寄存器開始傳輸數據后,AM9200 自動開始數據傳輸,并且定期的檢查HcDoneHead寄存器的內容,并且將其轉移到HCCA.DoneHead。然后產生中斷,觸發中斷處理程序。
在中斷處理程序中需要判斷當前結束的TD是否是當前命令的最后一個TD,這樣才能確保整個ED處理完畢。
進行U盤的數據傳輸時需要通過批量傳輸端口收發數據,所使用的協議為Mass Storage協議
 
要學習的一種數據結構與結構體結合應用的模式:
聲明時:
typedef struct _ED {
      …………
} ED, *P_ED;
 
__inline void CreateEd( unsigned int EDAddr   ,   ………….)
{
       P_ED    pED = (P_ED)  EDAddr; //這個在函數中創建結構體pED來初始化
pED->Control =…………………….
}
 
調用時,因16字節對齊:
__align(16) ED ed;     (聲明)
CreateEd(
              (unsigned int) &ed,       // ED Address
             ………….
              );                     
 
簡單的USB設備枚舉,讀取描述符:(控制傳輸步驟)
         搞好最重要的3個數據結構:
端點描述符ED,傳輸描述符TD和共享數據域HCCA
       由于HCCA只是創建一個空間域,不需要初始化
       EDTD在設備枚舉時需要不同初始化,故還要創建兩個
       初始化結構體函數:CreateEd CreateGenTd
         初始化OCHI寄存器(僅限枚舉部分,不涉及中斷)
復位,設置幀間隔,初始化HcDoneHead設置HC為運行狀態
HCCA(開拓一片域)
         檢測是否有USB設備
設一定的時間檢測,如 for(i=0;i<100000;i++)
         設備枚舉的5個過程:第一步,主機得到設備描述符
第二步 為設備分配地址
第三步,主機用新的地址再次獲取設備描述符
第四步,主機讀取設備全部配置描述符
第五步,主機發送SETUP數據包,用以設置配置,允許所有端點進入工作狀態。
注意:控制寫傳輸需要3TD:第一個發送Setup包,第二個用于接收握手或零長度的數據包,第三個用于發送狀態;
控制讀傳輸需要4TD:第一個發送Setup包,第二個用于接收數據,第三個用于發送一個零長度的數據包,,第四個用于接收狀態
 
具體有兩種方法判斷TD是否傳送完成:
         中斷法
初始化好中斷寄存器rHcInterruptEnable |= (1<<1)|(1<<31);
rHcInterruptStatus |= (1<<1);
pISR_USBH = (int)USBH_interrupt;
rINTMSK = ~BIT_USBH;
當有TD完成時,便進入中斷。
如何判斷枚舉過程中每一步是否最后一個TD完成呢?
可以通過TD創造函數中DelayInterruptDI變量設置來巧妙解決
DI=0x7時,即使TD完成也不會進入中斷的,故可以只在每一階段最后的TD設為非0x7,其余的設為0x7,這樣進入中斷就代表是最后數據發送完成了
 
2、狀態檢測法:
       可以通過rHcCommandStatus寄存器中第二位是否1來判斷Controllistfilled
       當其為1時,表示還有TD在隊列,沒發送完成
             0時,表示無TD在隊列,全部發送完
       可以這樣檢測:while(rHcCommandStatus&&0x02)
                     {
                            Delay(50);
                     }           
具體的UFI讀寫設備參考網上的吧(弄了很久,還沒弄成功)
       1、查詢
       2、讀余量
       3、讀寫扇區
 
 好啦,到這里,算是結束了,開始帶LINUX系統的真正學習啦,GO
一切都會有新的開始。。。。。。。。。。
關閉窗口

相關文章

主站蜘蛛池模板: 成人深夜小视频 | 亚洲精品一级 | 久久精品欧美一区二区三区不卡 | 一区二区三区成人 | 欧美综合视频在线 | 一区二区三区视频在线 | 丝袜美腿av| 91影院| 国产精品成人在线 | 国产a区 | 免费精品在线视频 | 国产精品久久久久久婷婷天堂 | 人人爽人人爽 | 国产日韩欧美在线观看 | 日本一区二区三区视频在线 | 精品人伦一区二区三区蜜桃网站 | 中文字幕综合 | 在线观看免费国产 | 久久99精品久久久 | 中文字幕乱码亚洲精品一区 | 久草电影网 | 人人草人人干 | 嫩草影院网址 | 视频一区二区中文字幕 | 国产综合精品一区二区三区 | 欧美日韩久久久 | 国产乱码精品1区2区3区 | 99精品视频网 | 国产精久久久久久 | 自拍视频网站 | 欧美日产国产成人免费图片 | 精品1区2区 | 久久精品国产v日韩v亚洲 | 国产精品18久久久 | 性色视频在线观看 | 一区二区三区四区电影视频在线观看 | 国产精品成人一区 | 精品一二三| av资源中文在线 | 伊人久久麻豆 | 欧美电影免费观看高清 |