1 | #if BOARD==EVK1100
|
2 | #define AVR32_PDCA_CHANNEL_USED_RX AVR32_PDCA_PID_SPI1_RX
|
3 | #define AVR32_PDCA_CHANNEL_USED_TX AVR32_PDCA_PID_SPI1_TX
|
4 | #elif BOARD==EVK1101
|
5 | #define AVR32_PDCA_CHANNEL_USED_RX AVR32_PDCA_PID_SPI_RX
|
6 | #define AVR32_PDCA_CHANNEL_USED_TX AVR32_PDCA_PID_SPI_TX
|
7 | #elif BOARD==EVK1105
|
8 | #define AVR32_PDCA_CHANNEL_USED_RX AVR32_PDCA_PID_SPI0_RX
|
9 | #define AVR32_PDCA_CHANNEL_USED_TX AVR32_PDCA_PID_SPI0_TX
|
10 | #else
|
11 | # error No known AVR32 board defined
|
12 | #endif
|
13 | #define AVR32_PDCA_CHANNEL_SPI_TX 1 // In the example we will use the pdca channel 1. // TODO: should be #0?
|
14 |
|
15 | volatile avr32_pdca_channel_t* pdca_channeltx;
|
16 | // Used to indicate the end of PDCA transfer
|
17 | volatile Bool end_of_transfer;
|
18 |
|
19 | /* interrupt handler to notify if the Data reception from flash is
|
20 | * over, in this case lunch the Memory(ram_buffer) to USART transfer and
|
21 | * disable interrupt*/
|
22 | #if __GNUC__
|
23 | __attribute__((__interrupt__))
|
24 | #elif __ICCAVR32__
|
25 | __interrupt
|
26 | #endif
|
27 | static void pdca_int_handler(void)
|
28 | {
|
29 | // Disable all interrupts.
|
30 | Disable_global_interrupt();
|
31 |
|
32 | // Disable unnecessary channel
|
33 | pdca_disable(AVR32_PDCA_CHANNEL_SPI_TX);
|
34 |
|
35 | // Enable all interrupts.
|
36 | Enable_global_interrupt();
|
37 |
|
38 | end_of_transfer = true;
|
39 | }
|
40 |
|
41 | void local_pdca_init(void * adr)
|
42 | {
|
43 | // this channel is used to activate the clock of the SPI by sending a dummy variables
|
44 | pdca_channel_options_t pdca_options_SPI_TX ={ // pdca channel options
|
45 |
|
46 | .addr = (void *)adr, // memory address.
|
47 | .size = 512, // transfer counter: here the size of the string
|
48 | .r_addr = NULL, // next memory address after 1st transfer complete
|
49 | .r_size = 0, // next transfer counter not used here
|
50 | .pid = AVR32_PDCA_CHANNEL_USED_TX, // select peripheral ID - data are on reception from SPI1 RX line
|
51 | .transfer_size = PDCA_TRANSFER_SIZE_BYTE // select size of the transfer: 8,16,32 bits
|
52 | };
|
53 |
|
54 | // Init PDCA transmission channel
|
55 | pdca_init_channel(AVR32_PDCA_CHANNEL_SPI_TX, &pdca_options_SPI_TX);
|
56 |
|
57 | INTC_register_interrupt(&pdca_int_handler, AVR32_PDCA_IRQ_1, AVR32_INTC_INT1); // pdca_channel_spi1_RX = 0
|
58 | }
|
59 |
|
60 | //! @brief This function writes one MMC sector from a ram buffer
|
61 | //!
|
62 | //! DATA FLOW is: RAM => SD/MMC
|
63 | //!
|
64 | //!
|
65 | //! NOTE (please read) :
|
66 | //! - First call (if sequential write) must be preceded by a call to the sd_mmc_spi_write_open() function
|
67 | //! - An address error will not detected here, but with the call of sd_mmc_spi_get_status() function
|
68 | //! - The program exits the functions with the memory card busy !
|
69 | //!
|
70 | //! @param ram pointer to ram buffer
|
71 | //!
|
72 | //! @return bit
|
73 | //! The write succeeded -> true
|
74 | //! The write failed -> false
|
75 | //!
|
76 | bool sd_mmc_spi_write_sector_from_ram(const void *ram)
|
77 | {
|
78 | const uint8_t *_ram = ram;
|
79 | uint16_t i;
|
80 |
|
81 | // wait for MMC not busy
|
82 | if (false == sd_mmc_spi_wait_not_busy())
|
83 | return false;
|
84 |
|
85 | spi_selectChip(SD_MMC_SPI, SD_MMC_SPI_NPCS); // select SD_MMC_SPI
|
86 |
|
87 | // issue command
|
88 | if(card_type == SD_CARD_2_SDHC) {
|
89 | r1 = sd_mmc_spi_command(MMC_WRITE_BLOCK, gl_ptr_mem>>9);
|
90 | } else {
|
91 | r1 = sd_mmc_spi_command(MMC_WRITE_BLOCK, gl_ptr_mem);
|
92 | }
|
93 |
|
94 | // check for valid response
|
95 | if(r1 != 0x00)
|
96 | {
|
97 | spi_unselectChip(SD_MMC_SPI, SD_MMC_SPI_NPCS);
|
98 | return false;
|
99 | }
|
100 | // send dummy
|
101 | spi_write(SD_MMC_SPI,0xFF); // give clock again to end transaction
|
102 |
|
103 | // send data start token
|
104 | spi_write(SD_MMC_SPI,MMC_STARTBLOCK_WRITE);
|
105 |
|
106 | #if 0
|
107 | // write data
|
108 | for(i=0;i<MMC_SECTOR_SIZE;i++)
|
109 | {
|
110 | spi_write(SD_MMC_SPI,*_ram++);
|
111 | }
|
112 | #else
|
113 | local_pdca_init((void const *)ram);
|
114 | pdca_load_channel(
|
115 | AVR32_PDCA_CHANNEL_SPI_TX,
|
116 | (void *)ram,
|
117 | 512);
|
118 | end_of_transfer = false;
|
119 | pdca_enable_interrupt_transfer_complete(AVR32_PDCA_CHANNEL_SPI_TX);
|
120 | pdca_channeltx =(volatile avr32_pdca_channel_t*) pdca_get_handler(AVR32_PDCA_CHANNEL_SPI_TX); // get the correct PDCA channel pointer
|
121 | pdca_channeltx->cr = AVR32_PDCA_TEN_MASK; // enable TX PDCA transfer
|
122 |
|
123 | while(!end_of_transfer);
|
124 |
|
125 | // pdca_disable_interrupt_transfer_complete(AVR32_PDCA_CHANNEL_SPI_TX);
|
126 | #endif
|
127 |
|
128 | spi_write(SD_MMC_SPI,0xFF); // send CRC (field required but value ignored)
|
129 | spi_write(SD_MMC_SPI,0xFF);
|
130 |
|
131 | // read data response token
|
132 | r1 = sd_mmc_spi_send_and_read(0xFF);
|
133 | if( (r1&MMC_DR_MASK) != MMC_DR_ACCEPT)
|
134 | {
|
135 | spi_write(SD_MMC_SPI,0xFF); // send dummy bytes
|
136 | spi_write(SD_MMC_SPI,0xFF);
|
137 | spi_unselectChip(SD_MMC_SPI, SD_MMC_SPI_NPCS);
|
138 | return false; // return ERROR byte
|
139 | }
|
140 |
|
141 | spi_write(SD_MMC_SPI,0xFF); // send dummy bytes
|
142 | spi_write(SD_MMC_SPI,0xFF);
|
143 |
|
144 | // release chip select
|
145 | spi_unselectChip(SD_MMC_SPI, SD_MMC_SPI_NPCS); // unselect SD_MMC_SPI
|
146 | gl_ptr_mem += 512; // Update the memory pointer.
|
147 |
|
148 | // wait card not busy after last programming operation
|
149 | i=0;
|
150 | while (false == sd_mmc_spi_wait_not_busy())
|
151 | {
|
152 | i++;
|
153 | if (i == 10)
|
154 | return false;
|
155 | }
|
156 |
|
157 | return true; // Write done
|
158 | }
|