ATA/PIO-Mode (CF-Kort) problem #¤@£%$&/{)[= arg

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46989
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

ATA/PIO-Mode (CF-Kort) problem #¤@£%$&/{)[= arg

Inlägg av TomasL »

Håller på med lite rutiner för att läsa av en PATA-Disk (CF-Kort), men har stött på problem.
När jag skall läsa en sektor, så skriver jag i vanlig ordning till register 2-6 antal sektorer att läsa, samt Sektor LBA, därefter skriver jag kommando 0x20 till kommandoregistret.

Därefter pollar jag statusregistret, men får bara 0x50 tillbaka (drive ready) inte som sig bör 0x58 (drive ready, data available), har i nuläget begränsat till 200 pollningar innan jag timar ut.

EN fundering, jag sätter CS0 i början av funktionen och låter den vara satt hela tiden, kan man göra så, eller behöver man släcka CS0 mellan varje skrivning/läsning.

Använder mig av PIC32MX795F512L och PMP-porten.
Processorn snurrar i 80MHz, PBUS i 40, använder 1,12,3 i waitstates för porten, som jag fattat det så är det enbart den mittersta som spelar roll, dvs längden på Write/Read-stroben, vilket bör ge minst 300 ns, adresslinor och CS sköter jag manuellt.


Portdefinitionen

Kod: Markera allt

#define PMP_CONTROL (PMP_ON | PMP_IDLE_CON | PMP_MUX_OFF | PMP_READ_WRITE_EN | PMP_READ_POL_LO |\
                     PMP_WRITE_POL_LO | PMP_LATCH_POL_HI )
                     

#define PMP_MODE        (PMP_IRQ_OFF | PMP_AUTO_ADDR_OFF | PMP_DATA_BUS_16 | PMP_MODE_MASTER2 |\
                     PMP_WAIT_BEG_1 | PMP_WAIT_MID_12 | PMP_WAIT_END_3 )

#define PMP_PORT        (PMP_PEN_OFF )

#define PMP_INTERRUPT	   (PMP_INT_OFF)
Koden för att läsa en sektor

Kod: Markera allt

uint8 MDD_CFPMP_SectorRead(uint32 sector_addr, uint8 * buffer)
{
   	uint8 test, error;
  	uint16 temp, i1;
   	uint16 i = 0;
	mCF_PMP_SEL_CS0;
   	mCF_PMP_DES_CS1;

    MDD_CFPMP_CFwrite( R_COUNT, 1); 
    MDD_CFPMP_CFwrite( R_SECT, sector_addr);
    MDD_CFPMP_CFwrite( R_CYLO, sector_addr>>8);
    MDD_CFPMP_CFwrite( R_CYHI, sector_addr>>16);
    MDD_CFPMP_CFwrite( R_DRIVE, ((uint8)(sector_addr>>24) & 0xf)|0xe0);  // always select card #0
    MDD_CFPMP_CFwrite( R_CMD, C_SECTOR_READ);
	PMPClearManualAdress();
	mPMP_ShortDelay;
   // Dummy read to get the first byte
   	//PMPMasterRead();
	mPMP_ShortDelay;
	i1=0;
    while ((test = MDD_CFPMP_CFread( R_STATUS)) != S_READY)
    {
      mPMP_ShortDelay;
      mPMP_ShortDelay;
      i1++;
      if (i1==200)
      {
      	while (1);	//error disk not ready.
      	}
      // If error flag is set . . . 
      if (MDD_CFPMP_CFread (R_STATUS) & 0x01)
       {	
          	
          	error=MDD_CFPMP_CFread (R_ERROR);
          	return FALSE;
       }
    }

	//PMPSetManualAdress(R_DATA);
  	//PMADDR = R_DATA | (PMADDR & 0xC000);
   
   //MDD_CFPMP_CFread (R_DATA);
   	PMPSetManualAdress(R_DATA);
   	temp=PMPMasterRead();	//Dummy read
   	mPMP_ShortDelay;
   	i=0;
   	while (i < 512)
   	{
      MDD_CFPMP_CFwait();
      temp= PMPMasterRead();
      buffer[i++] =  (uint8) temp;
      buffer[i++] =  (uint8) (temp>>8);
      mPMP_ShortDelay;
      mPMP_ShortDelay;
      
   	}

    //PMPClearManualAdress();
    mCF_PMP_DES_CS0;        // CF deselected when done

   return TRUE;       
} // read_sector
För att skriva till disken (ett ord)

Kod: Markera allt

void MDD_CFPMP_CFwrite( uint8 add, uint16 d)
// add  : CF register 
// d    : data
{
	uint32 i;	
	MDD_CFPMP_CFwait();
   	PMPSetManualAdress(add);
   	mPMP_ShortDelay;
   	PMPMasterWrite(d);
   //for (i=0; i< 100000; i++);
   	mPMP_ShortDelay;
   	PMPClearManualAdress();
   
} // CFwrite
För att läsa ett ord

Kod: Markera allt

uint16 MDD_CFPMP_CFread( uint8 add)
// add  :   register address
{
   	uint16 d;
	uint32 i;
   	MDD_CFPMP_CFwait();
   	PMPSetManualAdress(add);
	 
   	d=(uint16) PMPMasterRead();
   //MDD_CFPMP_DATABinput;
//for (i=0; i< 100000; i++);
   //PMADDR = (uint16)add | (PMADDR & 0xC000);

   //d = PMDIN1;      // get the data
   	mPMP_ShortDelay;
	PMPClearManualAdress();
   	return d;
} // CFread
PMPMasterRead och Write är lib-funktioner, vilka är enkla

Läsa

Kod: Markera allt

	while(mIsPMPBusy());
	return(PMDIN);
Och skriva

Kod: Markera allt

	while(mIsPMPBusy());
	PMDIN = value;
Nån som har ideer?
Senast redigerad av TomasL 13 januari 2012, 20:41:30, redigerad totalt 1 gång.
Användarvisningsbild
jesper
Inlägg: 722
Blev medlem: 12 juni 2006, 16:04:08
Ort: Laem Mae Phim, Thailand

Re: ATA/PIO-Mode (CF-Kort) problem

Inlägg av jesper »

Kollade lite gammal CF/ATA kod jag hade från mina yampp projekt.
Jag kan inte svara för all PIC grejset, men din ATA kod gör rätt saker. Dock har jag lite annan kod runt status checket.

Istället för att läsa Status registret, läser jag Alt_Status.
Efter att ha skickat 0x20 kommandot, set status wait så här ut:

Kod: Markera allt

//
// wait for the CF card to deassert BUSY and assert DRQ
// 
u08 cf_wait_drq(void)
{
	u08 stat;

   //
	// loop reading ALT STATUS until BUSY is cleared
	//
	while ( (cf_rba(ATAPI_AltStat) & SR_BUSY) == SR_BUSY ); 	// Wait for ! BUSY

	//
	// then read STATUS register to reset interrupt
	//
	stat = cf_rba(ATAPI_Status);

	if ( stat & SR_ERR )		// fail on error
		return 0;

	if ( ! (stat & SR_DRQ) )	// failure if DRQ not set
		return 0;

   return 1;
}
Vet inte om det kan hjälpa.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46989
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: ATA/PIO-Mode (CF-Kort) problem

Inlägg av TomasL »

Har också funderat på alt_status, men den enda skillnaden, om jag fattat saken rätt är att om jag läser statusregistret så släcks eventuella interrupt, vilket inte sker om man läser alt_status.
Eftersom jag inte använder mig av interrupt i nuläget, spelar det ingen roll.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46989
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: ATA/PIO-Mode (CF-Kort) problem

Inlägg av TomasL »

Nu var det lilla problemet löst, det är nästan så man skäms.
Hade räknat fel på fördröjningen efter reset, så jag försökte accessa kortet alldeles för tidigt.
Det visade sig att jag bara hade 3ms fördröjning efter det att reseten släpptes, ändrade loopen till en miljon istället för de 30k jag hade innan, så nu har jag i runda slängar 125ms istället och då kan jag problemfritt komma åt det.

Dock har ett annat problem dyckt upp, vilket jag inte begriper:

Jag kan utan problem läsa in MBR, dvs fysisk sektor, vilket i nuläget tar cirka 18us.

Det är när jag skall läsa in bootsektorn som problemen kommer, allt är ok utom de sista 2 byten, vilka skall vara 0x55 och 0xAA, där läser jag 0x00 på båda byten, alltid samma varje gång.
Kikar jag på kortet i HxD så finns signaturen där, efterföljande bytes läser jag ok, det är just specifikt dessa två byte jag inte läser rätt.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46989
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: ATA/PIO-Mode (CF-Kort) problem

Inlägg av TomasL »

Detta gör mig knäpp.

Hivar jag in CF-kortet i en USB-adapter så läser PC'n det utan problem, vi diskeditorn kan jag konstatera att både MBR och Bootsektorn är som de skall.

När jag sedan försöker läsa kortet med min PIC32 händer följande mystiska sak.

Sektor 0 dvs MBR läses in utan problem, sedan skall första partitionen läsas in, startar i sektor 32, jag läser in de första 508 byten helt problemfritt, de stämmer byte för byte.
De 4 siste byte blir helt felaktiga, de två sista skall innehålla signaturen 0x55 och 0xAA men blir alltid 0x00 varje gång.

Har också lekt med att duplicera sektorena, samma fel på de två sista byten.

Detta kan inte vara ett mjukvarufel eller hårdvarufel från min sida (ser inte på vilket sätt det skulle gå till).
Har kopplat in lysdioder på samtliga signaler mellan processor och CF-kort, och singelstegat igenom läsningen, och det kommer inga data ur CF-kortet.
Logikanalysatorn bekräftar samma sak.

Satt i ett annat CF kort, helt OK, kan läsa bägge sektorerna utan problem.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46989
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: ATA/PIO-Mode (CF-Kort) problem #¤@£%$&/{)[= arg

Inlägg av TomasL »

Har fixat fram ett antal fler CF-kort, 8MB, 16MB, 32MB och 128MB, samtliga kort, när jag försöker läsa från dem ger samma resultat, de sista 2 byten blir fel, och det verkar bara gälla sektor 1 och 32, typ.
I stället för att läsa signaturerna 0xAA och 0x55 läser jag 0x00, alla andra bytes i sektorn stämmer med vad diverse Hex-dump program visar.
Har även bytt ut PMP-rutinerna mot "bitbanging" mot berörda portar samma resultat, så vad i h......e är fel.
Skriv svar