예제 #1
0
/*!
 * Read SPI device ID.
 *
 * \param id Three byte character array, which receives
 *           the CPU ID.
 */
void SpiFlashId(u_char * id)
{
    u_char i;

    for (i = 0; i < 3; i++) {
        SpiByte(0x30);
        SpiByte(0x00);
        SpiByte(i);
        id[i] = SpiByte(0x00);
    }
}
예제 #2
0
/*!
 * \brief Read memory chip status.
 */
static uint8_t SpiMemStatus(uint8_t cs)
{
    uint8_t rc;

    if (cs == SPIMEM_CS_BIT) {
        sbi(SPIMEM_CS_PORT, cs);
    } else {
        cbi(SPIMEM_CS_PORT, cs);
    }
    SpiByte(0x57);
    rc = SpiByte(0);

    if (cs == SPIMEM_CS_BIT) {
        cbi(SPIMEM_CS_PORT, cs);
    } else {
        sbi(SPIMEM_CS_PORT, cs);
    }

    return rc;
}
예제 #3
0
/*!
 * \brief Write byte to the target's flash memory.
 *
 * The target must have been erased by a previous call
 * to SpiFlashErase().
 *
 * \param high Must be 0 to write the low byte or 8 to
 *             write the high byte.
 * \param addr Word address to write to.
 * \param data Byte value to write.
 *
 * \return 0 on success, -1 otherwise.
 */
int SpiFlashWriteByte(u_char high, u_short addr, u_char data)
{
    u_char d;

    if (data != 0xff) {
        SpiByte(0x40 | high);
        SpiByte(addr >> 8);
        SpiByte(addr & 0xFF);
        SpiByte(data);

        /*
         * During programming a value of 0x7F appears at the memory location. 
         * If we are programming this value, we delay execution by 10 ms.
         * Otherwise we poll the memory location until we read back the 
         * programmed value.
         */
        if (data == 0x7f)
            NutDelay(10);
        else {
            for (d = 0; d < 255; d++) {

                /*
                 * Read program flash byte.
                 */
                SpiByte(0x20 | high);
                SpiByte(addr >> 8);
                SpiByte(addr & 0xFF);
                if (SpiByte(0xFF) == data)
                    break;
            }
            if (d == 255)
                return -1;
        }
    }
예제 #4
0
/*!
 * \brief Enable SPI device flash programming.
 *
 * \return 0 if device could be located, -1 otherwise.
 */
int SpiFlashEnable(void)
{
    u_char i;
    u_char rc;

    /*
     * PB0(O): SS
     * PB1(O): SCK
     * PB2(O): MOSI
     * PB3(I): MISO
     *
     * PB4(O): Reset target
     * PB5(-): Unused
     * PB6(-): Unused
     * PB7(-): Unused
     */

    /*
     * SCK and MOSI outputs need configuration, 
     * even if SPI mode is enabled.
     */
    cbi(PORTB, 1);
    sbi(DDRB, 1);
    cbi(PORTB, 2);
    sbi(DDRB, 2);

    /*
     * Enable pull-up on MISO.
     */
    sbi(PORTB, 3);

    for (i = 0; i < 32; i++) {

        /*
         * Set reset low.
         */
        cbi(PORTB, 4);
        sbi(DDRB, 4);

        /*
         * Set slave select pin  to output. Otherwise a low signal 
         * on this pin might force us to SPI slave mode.
         */
        sbi(DDRB, 0);
        outp(BV(MSTR) | BV(SPE) | BV(SPR0), SPCR);

        /*
         * Try to enable programming.
         */
        SpiByte(0xAC);
        SpiByte(0x53);
        rc = SpiByte(0xFF);
        SpiByte(0xff);

        if (rc == 0x53)
            return 0;

        /*
         * Programming enable failed. This may be because the
         * target is not synchronized. A positive pulse on the
         * clock line should help.
         */
        outp(0, SPCR);
        sbi(PORTB, 1);
        cbi(PORTB, 1);
    }
    return -1;
}