新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > NANDFlashd的讀寫(基于s3c2440)

        NANDFlashd的讀寫(基于s3c2440)

        作者: 時間:2016-11-20 來源:網絡 收藏

        本文引用地址:http://www.104case.com/article/201611/318935.htm
        1. #ifndef__TEST_H__
        2. #define__TEST_H__
        3. #include"def.h"
        4. #defineMAX_NAND_BLOCK2048//一共2048塊
        5. #defineNAND_PAGE_SIZE2048//每塊main區2k字節=2048
        6. typedefstructnand_id_info//芯片的ID信息
        7. {
        8. U8IDm;//廠商ID
        9. U8IDd;//設備ID
        10. U8ID3rd;
        11. U8ID4th;
        12. U8ID5th;
        13. }nand_id_info;
        14. typedefstructbad_block_info//登記壞塊
        15. {
        16. U8area[MAX_NAND_BLOCK];//0表示非壞塊,1表示壞塊
        17. U32sum;//壞塊的總數
        18. }bad_block_info;
        19. //NAND操作指令
        20. #defineNAND_CMD_READ_1st0x00
        21. #defineNAND_CMD_READ_2st0x30
        22. #defineNAND_CMD_RANDOM_WRITE0x85//隨機寫
        23. #defineNAND_CMD_RANDOM_READ_1st0x05
        24. #defineNAND_CMD_RANDOM_READ_2st0xe0
        25. #defineNAND_CMD_READ_CB_1st0x00//將NAND里一塊內容寫進另一塊
        26. #defineNAND_CMD_READ_CB_2st0x35
        27. #defineNAND_CMD_READ_ID0x90
        28. #defineNAND_CMD_RES0xff//復位命令
        29. #defineNAND_CMD_WRITE_PAGE_1st0x80
        30. #defineNAND_CMD_WRITE_PAGE_2st0x10
        31. #defineNAND_CMD_BLOCK_ERASE_1st0x60//擦除命令
        32. #defineNAND_CMD_BLOCK_ERASE_2st0xd0
        33. #defineNAND_CMD_READ_STATUS0x70
        34. //NAND中斷向量
        35. #defineINT_NFCON24
        36. //NFCONFHCLK=100MHZ
        37. #defineS3C2440_NFCONF_TACLS_init(1<<12)
        38. #defineS3C2440_NFCONF_TWRPH0_init(4<<8)
        39. #defineS3C2440_NFCONF_TWRPH1_init(0<<4)
        40. #defineS3C2440_NFCONF_BusWidth_init(0)
        41. #defineS3C2440_NFCONF_init()(rNFCONF=S3C2440_NFCONF_TACLS_init|/
        42. S3C2440_NFCONF_TWRPH0_init|/
        43. S3C2440_NFCONF_TWRPH1_init|/
        44. S3C2440_NFCONF_BusWidth_init)
        45. //NFCONT
        46. #defineS3C2440_NFCONT_LockTight_init(0<<13)
        47. #defineS3C2440_NFCONT_SoftLock_init(0<<12)
        48. #defineS3C2440_NFCONT_EnbIllegalAccINT_init(1<<10)
        49. #defineS3C2440_NFCONT_EnbRnBINT_init(0<<9)
        50. #defineS3C2440_NFCONT_RnB_TransMode_init(0<<8)
        51. #defineS3C2440_NFCONT_SpareECCLock_init(1<<6)
        52. #defineS3C2440_NFCONT_MainECCLock_init(1<<5)
        53. #defineS3C2440_NFCONT_InitECC_init(1<<4)
        54. #defineS3C2440_NFCONT_Reg_nCE_init(1<<1)//初始配置片選無效
        55. #defineS3C2440_NFCONT_MODE_init(0)
        56. #defineS3C2440_NFCONT_init()(rNFCONT=S3C2440_NFCONT_LockTight_init|/
        57. S3C2440_NFCONT_SoftLock_init|/
        58. S3C2440_NFCONT_EnbIllegalAccINT_init|/
        59. S3C2440_NFCONT_EnbRnBINT_init|/
        60. S3C2440_NFCONT_RnB_TransMode_init|/
        61. S3C2440_NFCONT_SpareECCLock_init|/
        62. S3C2440_NFCONT_MainECCLock_init|/
        63. S3C2440_NFCONT_InitECC_init|/
        64. S3C2440_NFCONT_Reg_nCE_init|/
        65. S3C2440_NFCONT_MODE_init)
        66. //NFSTAT
        67. #defineS3C2440_NFSTAT_init()(rNFSTAT&=0x3)
        68. //NFESTAT0
        69. #defineS3C2440_NFESTAT0_init()(rNFESTAT0=0)
        70. //NFESTAT1
        71. #defineS3C2440_NFESTAT1_init()(rNFESTAT1=0)
        72. //
        73. #defineselect_nand()(rNFCONT&=~(1<<1))
        74. #definedis_select_nand()(rNFCONT|=1<<1)
        75. #definecontroller_enable()(rNFCONT|=1)
        76. #definecontroller_disable()(rNFCONT&=~1)
        77. //
        78. voidnand_flash_init(void);//初始化
        79. voidnand_read_id(void);
        80. externintnand_block_erase(U32num);//num要刪除的塊號
        81. externintnand_page_write(U32addr,U8*buffer,U32size);//addr要寫的起始頁地址,buffer要寫的緩存,size要寫的字節大小最大為4G
        82. externintnand_page_read(U32addr,U8*buffer,U32size);//addr開始頁地址,從每頁00地址開始讀
        83. externintnand_random_read(U32paddr,U32offset,U8*data);//隨機讀數據paddr頁地址,offset頁內偏移地址
        84. externintnand_random_write(U32paddr,U32offset,U8data);//隨機寫,paddr頁地址,offset頁內區最后一個地偏移地址
        85. externvoidnand_test_bad_block(void);//測試壞塊函數,并標記在nand_bbi變量里和spare里(如果非0xff則為壞塊)
        86. #endif
        87. #include"2440addr.h"
        88. #include"test.h"
        89. #include"def.h"
        90. #defineNAND_DEBUG1//打印一些串口調試信息
        91. #defineUSE_ECC1//使用ECC驗證
        92. nand_id_infonand_id;//定義登記芯片ID的全局變量
        93. bad_block_infonand_bbi;//定義來登記壞的全局變量
        94. voidinit_nand_bbi(void)//初始化變量
        95. {
        96. U32i;
        97. nand_bbi.sum=0;
        98. for(i=0;i
        99. nand_bbi.area[i]=0;//全部初始化為0
        100. }
        101. voidnand_mask_bad_block(U32n)//標志壞塊,n是壞塊的塊號
        102. {
        103. #ifdefNAND_DEBUG
        104. Uart_Printf("NANDfoundandmaskabadblock=%d.",n);
        105. #endif
        106. if(nand_bbi.area[n]!=1)
        107. {
        108. nand_bbi.area[n]=1;
        109. nand_bbi.sum++;
        110. nand_random_write(n*64,2048+64-1,0);//每塊的第一個spare的最后一個字節,標志本塊是否為壞塊,非0xff為壞塊
        111. }
        112. }
        113. intdetect_nand_busy(void)//檢測是否忙
        114. {
        115. U32a;
        116. a=0;
        117. while(!(rNFSTAT&(1<<2)))
        118. {
        119. a++;
        120. if(a==5000000)//等待超時
        121. {
        122. Uart_Printf("/r/nError:DetectNandBusytimeout!!!/r/n");
        123. rNFSTAT|=(1<<2);//清忙標志
        124. return-1;//錯誤返回-1
        125. }
        126. }
        127. rNFSTAT|=(1<<2);//清忙標志
        128. return1;
        129. }
        130. voidnand_reset(void)//NAND復位
        131. {
        132. rNFCMD=NAND_CMD_RES;
        133. detect_nand_busy();//檢測忙
        134. }
        135. voidcontrol_start(void)//芯片開啟
        136. {
        137. select_nand();
        138. controller_enable();
        139. rNFSTAT|=(1<<2);//清忙標志
        140. nand_reset();
        141. }
        142. voidcontrol_end(void)//芯片關閉
        143. {
        144. dis_select_nand();
        145. controller_disable();
        146. }
        147. voidecc_main_init(void)//初始化ECC值
        148. {
        149. rNFCONT|=1<<4;//initEcc
        150. }
        151. voidecc_main_start(void)//開鎖mainECC
        152. {
        153. rNFCONT&=~(1<<5);//unlock
        154. }
        155. voidecc_main_end(void)//鎖定mainECC
        156. {
        157. rNFCONT|=1<<5;//lock
        158. }
        159. voidecc_spare_start(void)//開鎖spareECC
        160. {
        161. rNFCONT&=~(1<<6);//unlock
        162. }
        163. voidecc_spare_end(void)//鎖定spareECC
        164. {
        165. rNFCONT|=1<<6;//lock
        166. }
        167. void__irqnandINT(void)//NAND中斷函數
        168. {
        169. //此處寫處理代碼
        170. #ifdefNAND_DEBUG
        171. Uart_Printf("/r/nNandError...Ininterruptnow!!!");//只有錯誤才會進入中斷
        172. #endif
        173. rSRCPND|=0x1<
        174. rINTPND|=0x1<
        175. }
        176. voidnand_read_id(void)//讀取芯片ID信息
        177. {
        178. control_start();//開控制
        179. rNFCMD=NAND_CMD_READ_ID;
        180. rNFADDR=0;
        181. //讀芯片ID
        182. nand_id.IDm=(U8)rNFDATA8;
        183. nand_id.IDd=(U8)rNFDATA8;
        184. nand_id.ID3rd=(U8)rNFDATA8;
        185. nand_id.ID4th=(U8)rNFDATA8;
        186. nand_id.ID5th=(U8)rNFDATA8;
        187. //打印ID信息
        188. #ifdefNAND_DEBUG
        189. Uart_Printf("/r/nReadNANDFlashID:");
        190. Uart_Printf("/r/nNANDMarkcode:0x%x",nand_id.IDm);
        191. Uart_Printf("/r/nNANDDevicecode:0x%x",nand_id.IDd);
        192. Uart_Printf("/r/nNAND3rdIDcode:0x%x",nand_id.ID3rd);
        193. Uart_Printf("/r/nNAND4thIDcode:0x%x",nand_id.ID4th);
        194. Uart_Printf("/r/nNAND5thIDcode:0x%x",nand_id.ID5th);
        195. #endif
        196. control_end();//關控制
        197. }
        198. //擦出時只要給定塊所在頁的地址,就能擦除整個塊
        199. intnand_block_erase(U32num)//num要刪除的塊號
        200. {
        201. num=num*64;//每塊的第一頁
        202. control_start();//開控制
        203. nand_reset();//復位
        204. rNFCMD=NAND_CMD_BLOCK_ERASE_1st;
        205. rNFADDR=num&0xff;
        206. rNFADDR=(num>>8)&0xff;
        207. rNFADDR=(num>>16)&0xff;
        208. rNFCMD=NAND_CMD_BLOCK_ERASE_2st;
        209. detect_nand_busy();
        210. rNFCMD=NAND_CMD_READ_STATUS;//讀狀態
        211. if(rNFDATA8&1)//最低位可以判斷擦除和寫是否成功
        212. {
        213. #ifdefNAND_DEBUG
        214. Uart_Printf("/r/nError:nanderaseerror...block=0x%x",num/64);
        215. #endif
        216. control_end();//關控制
        217. nand_mask_bad_block(num/64);//登記為壞塊
        218. return-1;//刪除錯誤返回0
        219. }
        220. control_end();//關控制
        221. #ifdefNAND_DEBUG
        222. Uart_Printf("/r/nNANDblock%derasecompleted.",num/64);
        223. #endif
        224. return1;//擦除成功
        225. }
        226. intnand_page_write(U32addr,U8*buffer,U32size)//addr要寫的起始頁地址,buffer要寫的緩存,size要寫的字節大小最大為4G
        227. {
        228. U32i,n,p,temp,ecc;
        229. U8*bu;
        230. bu=buffer;
        231. temp=0;
        232. n=size/2048+(((size%2048)==0)?0:1);//計算出要寫的頁數,小于一頁的部分當作一頁
        233. for(i=0;i
        234. {
        235. control_start();//開控制
        236. nand_reset();//復位
        237. #ifdefUSE_ECC
        238. ecc_main_init();
        239. ecc_main_start();//可以產生main區ECC
        240. #endif
        241. rNFCMD=NAND_CMD_WRITE_PAGE_1st;
        242. rNFADDR=0;//從每頁的0地址開始
        243. rNFADDR=0;//從每頁的0地址開始
        244. rNFADDR=(addr)&0xff;
        245. rNFADDR=(addr>>8)&0xff;
        246. rNFADDR=(addr>>16)&0xff;
        247. for(p=0;p<2048;p++)//寫入一頁
        248. {
        249. temp=temp+1;
        250. if(temp>size)
        251. {
        252. rNFDATA8=0xff;//多余的填寫0xff
        253. }
        254. else
        255. {
        256. rNFDATA8=*(bu+p);
        257. }
        258. }
        259. //delay_lhg(100,100);//
        260. #ifdefUSE_ECC
        261. ecc_main_end();//鎖定main區ecc
        262. ecc=rNFMECC0;
        263. ecc_spare_start();//解鎖spare區ECC
        264. //mainECC值寫入備用區的頭0~4個地址內
        265. rNFDATA8=ecc&0xff;
        266. rNFDATA8=(ecc>>8)&0xff;
        267. rNFDATA8=(ecc>>16)&0xff;
        268. rNFDATA8=(ecc>>24)&0xff;
        269. ecc_spare_end();//鎖定spare區ECC
        270. //delay_lhg(100,100);//
        271. ecc=rNFSECC;//spareECC值寫入備用區的5~6兩個地址內
        272. rNFDATA8=ecc&0xff;
        273. rNFDATA8=(ecc>>8)&0xff;
        274. #endif
        275. bu=bu+2048;//頁增量
        276. addr++;
        277. rNFCMD=NAND_CMD_WRITE_PAGE_2st;
        278. detect_nand_busy();//檢測忙
        279. rNFCMD=NAND_CMD_READ_STATUS;//讀狀態
        280. if(rNFDATA8&1)
        281. {
        282. #ifdefNAND_DEBUG
        283. Uart_Printf("/r/nnandwritepageerror:pageaddr=0x%d",addr-1);//寫入失敗,以后改進
        284. #endif
        285. control_end();//關控制
        286. nand_mask_bad_block((addr-1)/64);//登記為壞塊
        287. return-1;//寫入錯誤返回-1
        288. }
        289. control_end();//關控制
        290. }
        291. return1;//成功返回1
        292. }
        293. intnand_page_read(U32addr,U8*buffer,U32size)//addr開始頁地址,從每頁00地址開始讀,size為需要讀的字節數
        294. {
        295. U32i,n,p,temp,ecc;
        296. U8*bu,no;
        297. bu=buffer;
        298. temp=0;
        299. n=size/2048+(((size%2048)==0)?0:1);//計算出要讀的頁數,小于一頁的部分當作一頁
        300. for(i=0;i
        301. {
        302. control_start();//開控制
        303. nand_reset();//復位
        304. #ifdefUSE_ECC
        305. rNFESTAT0=0;//復位錯誤標志位
        306. ecc_main_init();
        307. ecc_main_start();//可以產生main區ECC
        308. #endif
        309. rNFCMD=NAND_CMD_READ_1st;
        310. rNFADDR=0;
        311. rNFADDR=0;
        312. rNFADDR=addr&0xff;
        313. rNFADDR=(addr>>8)&0xff;
        314. rNFADDR=(addr>>16)&0xff;
        315. rNFCMD=NAND_CMD_READ_2st;
        316. detect_nand_busy();
        317. for(p=0;p<2048;p++)
        318. {
        319. temp=temp+1;
        320. if(temp>size)
        321. {
        322. no=rNFDATA8;//多余的讀出來扔掉
        323. }
        324. else
        325. {
        326. *(bu+p)=rNFDATA8;
        327. }
        328. }
        329. #ifdefUSE_ECC
        330. rNFESTAT0=0;
        331. ecc_main_end();//鎖定main區ECC
        332. //delay_lhg(100,100);//
        333. ecc_spare_start();//解鎖spare區ecc
        334. ecc=rNFDATA8;//從flash讀出main區ECC,四個字節
        335. no=rNFDATA8;
        336. ecc|=((U32)no)<<8;
        337. no=rNFDATA8;
        338. ecc|=((U32)no)<<16;
        339. no=rNFDATA8;
        340. ecc|=((U32)no)<<24;
        341. rNFMECCD0=((ecc&0xff00)<<8)|(ecc&0xff);//硬件檢驗mainECC
        342. rNFMECCD1=((ecc&0xff000000)>>8)|((ecc&0xff0000)>>16);
        343. ecc_spare_end();//鎖定spare區ecc
        344. //delay_lhg(100,100);//
        345. ecc=rNFDATA8;//從flash讀出spare區ECC的值
        346. no=rNFDATA8;
        347. ecc|=((U32)no)<<8;
        348. rNFSECCD=((ecc&0xff00)<<8)|(ecc&0xff);//硬件檢驗spareECC
        349. //delay_lhg(100,100);//延時一會
        350. ecc=rNFESTAT0&0xffffff;//ecc只是臨時用一下錯誤狀態,并非ecc內容
        351. if(ecc!=0)//有錯誤
        352. {
        353. //以后再優化
        354. #ifdefNAND_DEBUG
        355. Uart_Printf("/r/nNandecccheckerror...pageaddr=0x%x,NFESTAT0=0x%x",addr,ecc);
        356. #endif
        357. nand_mask_bad_block((addr+i)/64);//登記為壞塊
        358. return-1;
        359. }
        360. #endif
        361. bu=bu+2048;
        362. addr++;
        363. control_end();//關控制
        364. }
        365. return1;
        366. }
        367. intnand_random_read(U32paddr,U32offset,U8*data)//隨機讀數據paddr頁地址,offset頁內偏移地址
        368. {
        369. control_start();//開控制
        370. nand_reset();//復位
        371. rNFCMD=NAND_CMD_READ_1st;
        372. rNFADDR=0;
        373. rNFADDR=0;
        374. rNFADDR=paddr&0xff;
        375. rNFADDR=(paddr>>8)&0xff;
        376. rNFADDR=(paddr>>16)&0xff;
        377. rNFCMD=NAND_CMD_READ_2st;
        378. detect_nand_busy();
        379. rNFCMD=NAND_CMD_RANDOM_READ_1st;
        380. rNFADDR=offset&0xff;//寫入頁內偏移地址
        381. rNFADDR=(offset>>8)&0xff;
        382. rNFCMD=NAND_CMD_RANDOM_READ_2st;
        383. *data=rNFDATA8;
        384. control_end();
        385. return1;
        386. }
        387. intnand_random_write(U32paddr,U32offset,U8data)//隨機寫,paddr頁地址,offset頁內偏移地址
        388. {
        389. control_start();//開控制
        390. nand_reset();//復位
        391. rNFCMD=NAND_CMD_WRITE_PAGE_1st;
        392. rNFADDR=0;
        393. rNFADDR=0;
        394. rNFADDR=paddr&0xff;
        395. rNFADDR=(paddr>>8)&0xff;
        396. rNFADDR=(paddr>>16)&0xff;
        397. rNFCMD=NAND_CMD_RANDOM_WRITE;
        398. rNFADDR=offset&0xff;//寫入頁內偏移地址
        399. rNFADDR=(offset>>8)&0xff;
        400. rNFDATA8=data;
        401. rNFCMD=NAND_CMD_WRITE_PAGE_2st;
        402. detect_nand_busy();//檢測忙
        403. rNFCMD=NAND_CMD_READ_STATUS;//讀狀態
        404. if(rNFDATA8&1)
        405. {
        406. #ifdefNAND_DEBUG
        407. Uart_Printf("/r/nError:nandrandomwriteerror...paddr=0x%x,offset=0x%x",paddr,offset);
        408. #endif
        409. return-1;//刪除錯誤返回0
        410. }
        411. control_end();
        412. return1;//成功返回1
        413. }
        414. voidnand_test_bad_block(void)//測試壞塊函數,并標記spare區最后一個地址,如果非0xff則為壞塊
        415. {
        416. U8dest[64*2048];//一個塊的main區容量
        417. U8src[64*2048];
        418. U32i,k;
        419. #ifdefNAND_DEBUG
        420. Uart_Printf("/r/ntestandmaskbadblockisbegain./r/n");
        421. #endif
        422. //main區檢測
        423. for(i=0;i<64*2048;i++)
        424. {
        425. dest[i]=0xff;//初始化緩沖區
        426. src[i]=0;
        427. }
        428. //刪除所有塊
        429. for(i=0;i
        430. {
        431. nand_block_erase(i);
        432. }
        433. for(i=0;i
        434. {
        435. nand_page_write(i*64,src,64*2048);
        436. nand_page_read(i*64,dest,64*2048);//使用了ecc校驗讀出來即可登記壞塊信息
        437. }
        438. for(i=0;i<64*2048;i++)
        439. {
        440. dest[i]=0;//初始化緩沖區
        441. src[i]=0xff;
        442. }
        443. //刪除所有塊
        444. for(i=0;i
        445. {
        446. nand_block_erase(i);
        447. }
        448. for(i=0;i
        449. {
        450. nand_page_write(i*64,src,64*2048);
        451. nand_page_read(i*64,dest,64*2048);//使用了ecc校驗讀出來即可登記壞塊信息
        452. }
        453. //
        454. //spare區檢測
        455. for(i=0;i<64;i++)
        456. {
        457. dest[i]=0xff;//初始化緩沖區
        458. src[i]=0;
        459. }
        460. //刪除所有塊
        461. for(i=0;i
        462. {
        463. nand_block_erase(i);
        464. }
        465. for(i=0;i
        466. {
        467. if(nand_bbi.area[i/64]==1)//如果是壞塊則跳過
        468. continue;
        469. for(k=0;k<64;k++)
        470. {
        471. nand_random_write(i,2048+k,src[k]);
        472. nand_random_read(i,2048+k,&dest[k]);
        473. if(dest[k]!=src[k])//不相等則登記為壞塊
        474. {
        475. nand_mask_bad_block(i/64);
        476. break;
        477. }
        478. }
        479. }
        480. for(i=0;i<64;i++)
        481. {
        482. dest[i]=0x0;//初始化緩沖區
        483. src[i]=0xff;
        484. }
        485. //刪除所有塊
        486. for(i=0;i
        487. {
        488. nand_block_erase(i);
        489. }
        490. for(i=0;i
        491. {
        492. if(nand_bbi.area[i/64]==1)//如果是壞塊則跳過
        493. continue;
        494. for(k=0;k<64;k++)
        495. {
        496. nand_random_write(i,2048+k,src[k]);
        497. nand_random_read(i,2048+k,&dest[k]);
        498. if(dest[k]!=src[k])//不相等則登記為壞塊
        499. {
        500. nand_mask_bad_block(i/64);
        501. break;
        502. }
        503. }
        504. }
        505. #ifdefNAND_DEBUG
        506. Uart_Printf("/r/ntestandmaskbadblockisover./r/n");
        507. #endif
        508. }
        509. voidnand_flash_init(void)//初始化
        510. {
        511. #ifdefNAND_DEBUG
        512. Uart_Printf("/r/nNANDFLASHinit");//
        513. #endif
        514. //中斷入口地址
        515. pISR_NFCON=(U32)nandINT;
        516. //配置GPIO
        517. rGPGUP|=0x7<<13;//GPG13~15關閉上位
        518. rGPGCON&=~((U32)0x3f<<26);//GPG13~15為輸入
        519. //初始化各寄存器
        520. S3C2440_NFCONF_init();
        521. S3C2440_NFCONT_init();
        522. S3C2440_NFSTAT_init();
        523. S3C2440_NFESTAT0_init();
        524. S3C2440_NFESTAT1_init();
        525. //關于中斷
        526. rINTMSK&=~(0x1<
        527. rINTMOD&=~(0x1<
        528. rSRCPND|=0x1<
        529. rINTPND|=0x1<
        530. //init_nand_bbi();//初始化全局變量
        531. nand_read_id();//讀ID
        532. //nand_test_bad_block();//測試并登記壞塊
        533. }




        評論


        技術專區

        關閉
        主站蜘蛛池模板: 安宁市| 加查县| 家居| 兴化市| 瓮安县| 芦溪县| 宝坻区| 来宾市| 北辰区| 郧西县| 凤台县| 会泽县| 澳门| 宜川县| 福建省| 淮阳县| 湖口县| 东乡族自治县| 古丈县| 乐业县| 连城县| 砀山县| 乌拉特中旗| 姚安县| 彭山县| 宾川县| 中卫市| 定日县| 商南县| 岐山县| 湘乡市| 杭锦后旗| 湟源县| 明光市| 承德县| 穆棱市| 元江| 三门县| 报价| 迁西县| 木兰县|