+ inline void uwait(uint16_t u)
+ {
+ uint16_t t0 = TAR;
+ while((TAR - t0) <= u);
+ }
+
+ inline void TOSH_wait()
+ {
+ nop(); nop();
+ }
+
+ /* Initialize the SPI pins to allow bit-bang communication with the AT25DF */
+ void at25df_init()
+ {
+ TOSH_MAKE_UC_SIMO_OUTPUT();
+ TOSH_MAKE_UC_SCK_OUTPUT();
+ TOSH_MAKE_FLH_CS_OUTPUT();
+ TOSH_SET_FLH_CS_PIN();
+ TOSH_SET_UC_SCK_PIN();
+ TOSH_SET_UC_SIMO_PIN();
+ TOSH_wait();
+ }
+
+ /* Send a bit */
+ void at25df_wbit(bool set)
+ {
+ if (set)
+ TOSH_SET_UC_SIMO_PIN();
+ else
+ TOSH_CLR_UC_SIMO_PIN();
+ TOSH_SET_UC_SCK_PIN();
+ TOSH_CLR_UC_SCK_PIN();
+ }
+
+ /* Send a byte */
+ void at25df_wbyte(uint8_t byte)
+ {
+ /* Bits of a byte are sent most significant bit first */
+ uint8_t mask = 0x80;
+
+ while (mask) {
+ at25df_wbit(byte & mask);
+ mask >>= 1;
+ }
+ }
+
+ /* Begin a communications transaction */
+ void at25df_begin()
+ {
+ TOSH_wait();
+ TOSH_CLR_FLH_CS_PIN();
+ TOSH_CLR_UC_SCK_PIN();
+ }
+
+ /* End a communiations transaction */
+ void at25df_end()
+ {
+ TOSH_SET_FLH_CS_PIN();
+ TOSH_SET_UC_SCK_PIN();
+ TOSH_SET_UC_SIMO_PIN();
+ }
+
+ /* Send the Write Enable command */
+ void at25df_wren()
+ {
+ at25df_begin();
+ at25df_wbyte(0x06); /* WREN */
+ at25df_end();
+ }
+
+ /* Zero all bits in the status register */
+ void at25df_wrsr(uint8_t value)
+ {
+ at25df_begin();
+ at25df_wbyte(0x01); /* WRSR */
+ at25df_wbyte(value);
+ at25df_end();
+ }
+
+ /* Globally unprotect all sectors. */
+ void at25df_unprotect()
+ {
+ /* After power-up or AT25DF reset, all sectors of the AT25DF are write
+ * protected. The first WRSR clears the SPRL bit, the second WRSR clears
+ * the sector protect bits, globally unprotecting all sectors and making
+ * them writeable.
+ */
+ at25df_wren();
+ at25df_wrsr(0);
+ at25df_wren();
+ at25df_wrsr(0);
+ }
+
+ /* Put the flash chip into deep power down mode */
+ void at25df_dpd()
+ {
+ at25df_begin();
+ at25df_wbyte(0xb9); /* DPD */
+ at25df_end();
+ }
+
+ /* Resume from deep power-down */
+ void at25df_rdpd()
+ {
+ at25df_begin();
+ at25df_wbyte(0xab); /* RDPD */
+ at25df_end();
+ }
+