Estoy empezando a mirar el SPI en el AT91SAM7S y aunque le he puesto tiempo no logro hacerlo funcionar, me gustaria separar un problema de codigo de un problema de hard.
Si alguien miro la datasheet del SPI o tiene alguna info, bienvenido sea.
Aca el codigo de ejemplo que arme, para la incializacion del SPI.
eSpiInitError eSpiInit(eCSDevice device)
{
unsigned portLONG ulConfig = (unsigned int) AT91C_PA12_MISO | (unsigned int) AT91C_PA13_MOSI | (unsigned int) AT91C_PA14_SPCK;
/*Enable Pull ups*/
AT91F_PIO_CfgPullup(AT91C_BASE_PIOA, AT91C_PA12_MISO|AT91C_PA13_MOSI|AT91C_PA14_SPCK );
/*Enable SPI Clocks*/
AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, 1 << AT91C_ID_SPI);
/*Enable SPI module*/
AT91F_SPI_Enable(AT91C_BASE_SPI);
/*Enable SPI PIO (SI, SO, SCK, CS)*/
switch (device)
{
case ChipSelect0: ulConfig |= (unsigned int) AT91C_PA11_NPCS0; break;
case ChipSelect1: ulConfig |= (unsigned int) AT91C_PA31_NPCS1; break;
case ChipSelect2: ulConfig |= (unsigned int) AT91C_PA10_NPCS2; break;
case ChipSelect3: ulConfig |= (unsigned int) AT91C_PA22_NPCS3; break;
default: return spiInitMaxCs;
}
AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, ulConfig, 0);
/*Reset the module*/
AT91F_SPI_Reset(AT91C_BASE_SPI);
/*Configure Master mode comunication with Variable Peripheral Select and Chip select w/o decode*/
AT91F_SPI_CfgMode(AT91C_BASE_SPI, AT91C_SPI_MSTR | AT91C_SPI_PS_VARIABLE);
/*Disable SPI*/
//AT91F_PMC_DisablePeriphClock(AT91C_BASE_PMC, ((unsigned int) 1 << AT91C_ID_SPI));
//AT91F_SPI_Disable (AT91C_BASE_SPI);
/*Mark module as enabled, store config data*/
spiPort[device].enabled = 1;
return spiInitSuccess;
}
Rutina de transmision por DMA (no miren que bloquea en el while, es solamente para probar que anda, despues se usara ints y servicios del RTOS).
unsigned portCHAR cSpiReadWrite(pSpiRWdata pData)
{
unsigned portCHAR errCode;
volatile int nRDR;
unsigned portCHAR bHoldCS = 0;
if (pData->holdCS) {bHoldCS = AT91C_SPI_CSAAT;}
/*Configure for the selected Chip Select, the clock phase, bits per transfer, baud rate and
if Chip Select Active After Transfer
*/
AT91F_SPI_CfgCs(AT91C_BASE_SPI, pData->device, AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | (pData->clockDivider << 8) | (bHoldCS));
/*Open the PDC module*/
AT91F_PDC_Open(AT91C_BASE_PDC_SPI);
/*Disable Spi activity during PDC initialization*/
AT91F_PDC_DisableRx(AT91C_BASE_PDC_SPI);
AT91F_PDC_DisableTx(AT91C_BASE_PDC_SPI);
/*Has bytes to write*/
if (pData->sizeW == 0)
{
AT91F_SPI_SendFrame (AT91C_BASE_SPI, (char *) pData->dataR, pData->sizeR, 0, 0);
}
else
{
AT91F_SPI_SendFrame (AT91C_BASE_SPI, (char *) pData->dataW, pData->sizeW, 0, 0);
}
/*Has bytes to read*/
if (pData->sizeR > 0)
{
AT91F_SPI_ReceiveFrame (AT91C_BASE_SPI, (char*) pData->dataR, pData->sizeR, 0, 0);
AT91F_PDC_EnableRx (AT91C_BASE_PDC_SPI);
}
/*Enable Transmission*/
AT91F_PDC_EnableTx(AT91C_BASE_PDC_SPI);
/*Configure and enable interrupts*/
//AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SPI, AT91C_AIC_PRIOR_LOWEST + 1, AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, ( void (*)(void) ) vSpiISREntry);
//AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SPI);
/*Test: wait to complete*/
while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXBUFE) == 0 || (AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RXBUFF) == 0);
AT91F_PDC_Close (AT91C_BASE_PDC_SPI);
/* Flush SPI RDR buffer (in case there is pending data)*/
nRDR = AT91F_SPI_GetChar (AT91C_BASE_SPI);
return errCode;
}
No logro siquiera que maneje la linea de CS, (que lo deberia hacer por hardware), ademas el codigo bloquea sobre el while y nunca sigue.
Alguen tiene un ejemplo sobre KEIL?