• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "gd32f4xx.h"
17 #include "gd32f4xx_systick.h"
18 #include "exmc_sdram.h"
19 
20 /* define mode register content */
21 /* burst length */
22 #define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000)
23 #define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001)
24 #define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002)
25 #define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0003)
26 
27 /* burst type */
28 #define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
29 #define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
30 
31 /* CAS latency */
32 #define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020)
33 #define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030)
34 
35 /* write mode */
36 #define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
37 #define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
38 
39 #define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
40 
41 #define SDRAM_TIMEOUT ((uint32_t)0x0000FFFF)
42 #define ADDR_STEP ((uint16_t)2)
clean_bss(void)43 void clean_bss(void)
44 {
45     volatile unsigned int *start = (volatile unsigned int *)&__bss_start__;
46     volatile unsigned int *end = (volatile unsigned int *)&__bss_end__;
47 
48     printf("bss start is 0x%x %p\n", __bss_start__, &__bss_start__);
49     printf("bss end is 0x%x %p\n", __bss_end__, &__bss_end__);
50     while (start <= end) {
51         *start++ = 0;
52     }
53 }
54 
55 /*!
56     \brief      initialize sdram peripheral
57     \param[in]  sdram_device: specify the SDRAM device
58     \param[out] none
59     \retval     none
60 */
sdram_rcu_periph_clock_enable(void)61 void sdram_rcu_periph_clock_enable(void)
62 {
63     /* enable EXMC clock */
64     rcu_periph_clock_enable(RCU_EXMC);
65     rcu_periph_clock_enable(RCU_GPIOB);
66     rcu_periph_clock_enable(RCU_GPIOC);
67     rcu_periph_clock_enable(RCU_GPIOD);
68     rcu_periph_clock_enable(RCU_GPIOE);
69     rcu_periph_clock_enable(RCU_GPIOF);
70     rcu_periph_clock_enable(RCU_GPIOG);
71     rcu_periph_clock_enable(RCU_GPIOH);
72 }
sdram_gpio_init(void)73 void sdram_gpio_init(void)
74 {
75     /* common GPIO configuration */
76     /* SDNWE(PC0),SDNE0(PC2),SDCKE0(PC3) pin configuration */
77     gpio_af_set(GPIOC, GPIO_AF_12, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3);
78     gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3);
79     gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3);
80 
81     /* D2(PD0),D3(PD1),D13(PD8),D14(PD9),D15(PD10),D0(PD14),D1(PD15) pin configuration */
82     gpio_af_set(GPIOD, GPIO_AF_12,
83                 GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15);
84     gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_PULLUP,
85                   GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15);
86     gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,
87                             GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_14 |
88                                 GPIO_PIN_15);
89 
90     /* NBL0(PE0),NBL1(PE1),D4(PE7),D5(PE8),D6(PE9),D7(PE10),D8(PE11),
91     D9(PE12),D10(PE13),D11(PE14),D12(PE15) pin configuration */
92     gpio_af_set(GPIOE, GPIO_AF_12,
93                 GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 |
94                     GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
95     gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_PULLUP,
96                   GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 |
97                       GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
98     gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,
99                             GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 |
100                                 GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
101 
102     /* A0(PF0),A1(PF1),A2(PF2),A3(PF3),A4(PF4),A5(PF5),NRAS(PF11),
103     A6(PF12),A7(PF13),A8(PF14),A9(PF15) pin configuration */
104     gpio_af_set(GPIOF, GPIO_AF_12,
105                 GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_11 |
106                     GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
107     gpio_mode_set(GPIOF, GPIO_MODE_AF, GPIO_PUPD_PULLUP,
108                   GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_11 |
109                       GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
110     gpio_output_options_set(GPIOF, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,
111                             GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_11 |
112                                 GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
113 
114     /* A10(PG0),A11(PG1),A12(PG2),A14(PG4),A15(PG5),SDCLK(PG8),NCAS(PG15) pin configuration */
115     gpio_af_set(GPIOG, GPIO_AF_12,
116                 GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_15);
117     gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_PULLUP,
118                   GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_15);
119     gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,
120                             GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_15);
121 }
122 
sdram_timing_init_struct_configure(exmc_sdram_timing_parameter_struct * sdram_timing_init_struct)123 void sdram_timing_init_struct_configure(exmc_sdram_timing_parameter_struct *sdram_timing_init_struct)
124 {
125      /* LMRD: 2 clock cycles */
126     int16_t delay_t1 = 2;
127     sdram_timing_init_struct->load_mode_register_delay = delay_t1;
128     /* XSRD: min = 75ns */
129     int16_t delay_t2 = 8;
130     sdram_timing_init_struct->exit_selfrefresh_delay = delay_t2;
131     /* RASD: min=44ns , max=120k (ns) */
132     int16_t delay_t3 = 5;
133     sdram_timing_init_struct->row_address_select_delay = delay_t3;
134     /* ARFD: min=66ns */
135     int16_t delay_t4 = 7;
136     sdram_timing_init_struct->auto_refresh_delay = delay_t4;
137     /* WRD:  min=1 Clock cycles +7.5ns */
138     int16_t delay_t5 = 2;
139     sdram_timing_init_struct->write_recovery_delay = delay_t5;
140     /* RPD:  min=20ns */
141     int16_t delay_t6 = 3;
142     sdram_timing_init_struct->row_precharge_delay = delay_t6;
143     /* RCD:  min=20ns */
144     int16_t delay_t7 = 3;
145     sdram_timing_init_struct->row_to_column_delay = delay_t7;
146 }
sdram_init_struct_config(uint32_t sdram_device,exmc_sdram_parameter_struct * sdram_init_struct,exmc_sdram_timing_parameter_struct * sdram_timing_init_struct)147 void sdram_init_struct_config(uint32_t sdram_device, exmc_sdram_parameter_struct *sdram_init_struct,
148                               exmc_sdram_timing_parameter_struct *sdram_timing_init_struct)
149 {
150     sdram_init_struct->sdram_device = sdram_device;
151     sdram_init_struct->column_address_width = EXMC_SDRAM_COW_ADDRESS_9;
152     sdram_init_struct->row_address_width = EXMC_SDRAM_ROW_ADDRESS_13;
153     sdram_init_struct->data_width = EXMC_SDRAM_DATABUS_WIDTH_16B;
154     sdram_init_struct->internal_bank_number = EXMC_SDRAM_4_INTER_BANK;
155     sdram_init_struct->cas_latency = EXMC_CAS_LATENCY_3_SDCLK;
156     sdram_init_struct->write_protection = DISABLE;
157     sdram_init_struct->sdclock_config = EXMC_SDCLK_PERIODS_2_HCLK;
158     sdram_init_struct->burst_read_switch = ENABLE;
159     sdram_init_struct->pipeline_read_delay = EXMC_PIPELINE_DELAY_1_HCLK;
160     sdram_init_struct->timing = sdram_timing_init_struct;
161 }
sdram_command_init_struct_config(int step,uint32_t bank_select,uint32_t command_content,exmc_sdram_command_parameter_struct * sdram_command_init_struct)162 void sdram_command_init_struct_config(int step, uint32_t bank_select, uint32_t command_content,
163                                       exmc_sdram_command_parameter_struct *sdram_command_init_struct)
164 {
165     switch (step) {
166         case 0x3:
167             sdram_command_init_struct->command = EXMC_SDRAM_CLOCK_ENABLE;
168             sdram_command_init_struct->bank_select = bank_select;
169             sdram_command_init_struct->auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_1_SDCLK;
170             sdram_command_init_struct->mode_register_content = 0;
171             break;
172         case 0x5:
173             sdram_command_init_struct->command = EXMC_SDRAM_PRECHARGE_ALL;
174             sdram_command_init_struct->bank_select = bank_select;
175             sdram_command_init_struct->auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_1_SDCLK;
176             sdram_command_init_struct->mode_register_content = 0;
177             break;
178         case 0x6:
179             sdram_command_init_struct->command = EXMC_SDRAM_AUTO_REFRESH;
180             sdram_command_init_struct->bank_select = bank_select;
181             sdram_command_init_struct->auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_8_SDCLK;
182             sdram_command_init_struct->mode_register_content = 0;
183             break;
184         case 0x7:
185             sdram_command_init_struct->command = EXMC_SDRAM_LOAD_MODE_REGISTER;
186             sdram_command_init_struct->bank_select = bank_select;
187             sdram_command_init_struct->auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_1_SDCLK;
188             sdram_command_init_struct->mode_register_content = command_content;
189             break;
190         default :
191             break;
192     }
193 }
time_out_check(uint32_t sdram_device)194 ErrStatus time_out_check(uint32_t sdram_device)
195 {
196     uint32_t timeout = SDRAM_TIMEOUT;
197     while ((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)) {
198         timeout--;
199     }
200     if (timeout == 0) {
201         printf("in %s %s:%d timeout\n", __FILE__, __FUNCTION__, __LINE__);
202         return ERROR;
203     }
204     return SUCCESS;
205 }
exmc_synchronous_dynamic_ram_init(uint32_t sdram_device)206 ErrStatus exmc_synchronous_dynamic_ram_init(uint32_t sdram_device)
207 {
208     exmc_sdram_parameter_struct sdram_init_struct;
209     exmc_sdram_timing_parameter_struct sdram_timing_init_struct;
210     exmc_sdram_command_parameter_struct sdram_command_init_struct;
211     uint32_t command_content = 0, bank_select;
212 
213     sdram_rcu_periph_clock_enable();
214 
215     sdram_gpio_init();
216     /* specify which SDRAM to read and write */
217     if (EXMC_SDRAM_DEVICE0 == sdram_device) {
218         bank_select = EXMC_SDRAM_DEVICE0_SELECT;
219     } else {
220         bank_select = EXMC_SDRAM_DEVICE1_SELECT;
221     }
222 
223     /* EXMC SDRAM device initialization sequence --------------------------------*/
224     /* Step 1 : configure SDRAM timing registers --------------------------------*/
225     sdram_timing_init_struct_configure(&sdram_timing_init_struct);
226 
227     /* step 2 : configure SDRAM control registers ---------------------------------*/
228     sdram_init_struct_config(sdram_device, &sdram_init_struct, &sdram_timing_init_struct);
229     /* EXMC SDRAM bank initialization */
230     exmc_sdram_init(&sdram_init_struct);
231 
232     /* step 3 : configure CKE high command---------------------------------------*/
233     sdram_command_init_struct_config(0x3, bank_select, command_content, &sdram_command_init_struct);
234     /* wait until the SDRAM controller is ready */
235     if (time_out_check(sdram_device) != SUCCESS) {
236         return ERROR;
237     }
238     /* send the command */
239     exmc_sdram_command_config(&sdram_command_init_struct);
240 
241     /* step 4 : insert 10ms delay----------------------------------------------*/
242     int16_t delay_t8 = 10;
243     Gd32f4xxDelay1ms(delay_t8);
244 
245     /* step 5 : configure precharge all command----------------------------------*/
246     sdram_command_init_struct_config(0x5, bank_select, command_content, &sdram_command_init_struct);
247     /* wait until the SDRAM controller is ready */
248     if (time_out_check(sdram_device) != SUCCESS) {
249         return ERROR;
250     }
251     /* send the command */
252     exmc_sdram_command_config(&sdram_command_init_struct);
253 
254     /* step 6 : configure Auto-Refresh command-----------------------------------*/
255     sdram_command_init_struct_config(0x6, bank_select, command_content, &sdram_command_init_struct);
256     /* wait until the SDRAM controller is ready */
257     if (time_out_check(sdram_device) != SUCCESS) {
258         return ERROR;
259     }
260     /* send the command */
261     exmc_sdram_command_config(&sdram_command_init_struct);
262 
263     /* step 7 : configure load mode register command-----------------------------*/
264     /* program mode register */
265     command_content = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 | SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
266                       SDRAM_MODEREG_CAS_LATENCY_3 | SDRAM_MODEREG_OPERATING_MODE_STANDARD |
267                       SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
268 
269     sdram_command_init_struct_config(0x7, bank_select, command_content, &sdram_command_init_struct);
270 
271     /* wait until the SDRAM controller is ready */
272     if (time_out_check(sdram_device) != SUCCESS) {
273         return ERROR;
274     }
275     /* send the command */
276     exmc_sdram_command_config(&sdram_command_init_struct);
277 
278     /* step 8 : set the auto-refresh rate counter--------------------------------*/
279     /* 64ms, 8192-cycle refresh, 64ms/8192=7.81us */
280     /* SDCLK_Freq = SYS_Freq/2 */
281     /* (7.81 us * SDCLK_Freq) - 20 */
282     int16_t auto_refresh_iterval = 761;
283     exmc_sdram_refresh_count_set(auto_refresh_iterval);
284 
285     /* wait until the SDRAM controller is ready */
286     if (time_out_check(sdram_device) != SUCCESS) {
287         return ERROR;
288     }
289     int16_t delay_t9 = 500;
290     Gd32f4xxDelay1ms(delay_t9);
291 
292     printf("*********************clean_bss\n");
293     clean_bss();
294     return SUCCESS;
295 }
296 
297 /*!
298     \brief      fill the buffer with specified value
299     \param[in]  pbuffer: pointer on the buffer to fill
300     \param[in]  buffer_lengh: size of the buffer to fill
301     \param[in]  offset: the initial value to fill in the buffer
302     \param[out] none
303     \retval     none
304 */
fill_buffer(uint8_t * pbuffer,uint16_t buffer_lengh,uint16_t offset)305 void fill_buffer(uint8_t *pbuffer, uint16_t buffer_lengh, uint16_t offset)
306 {
307     uint16_t index = 0;
308 
309     /* fill the buffer with specified values */
310     for (index = 0; index < buffer_lengh; index++) {
311         pbuffer[index] = 0x10 + index + offset;
312     }
313 }
314 
315 /*!
316     \brief      write a byte buffer(data is 8 bits) to the EXMC SDRAM memory
317     \param[in]  sdram_device: specify which a SDRAM memory block is written
318     \param[in]  pbuffer: pointer to buffer
319     \param[in]  writeaddr: SDRAM memory internal address from which the data will be written
320     \param[in]  numbytetowrite: number of bytes to write
321     \param[out] none
322     \retval     none
323 */
sdram_writebuffer_8(uint32_t sdram_device,uint8_t * pbuffer,uint32_t writeaddr,uint32_t numbytetowrite)324 void sdram_writebuffer_8(uint32_t sdram_device, uint8_t *pbuffer, uint32_t writeaddr, uint32_t numbytetowrite)
325 {
326     uint32_t temp_addr;
327 
328     /* Select the base address according to EXMC_Bank */
329     if (sdram_device == EXMC_SDRAM_DEVICE0) {
330         temp_addr = SDRAM_DEVICE0_ADDR;
331     } else {
332         temp_addr = SDRAM_DEVICE1_ADDR;
333     }
334 
335     /* While there is data to write */
336     for (; numbytetowrite != 0; numbytetowrite--) {
337         /* Transfer data to the memory */
338         *(uint8_t *)(temp_addr + writeaddr) = *pbuffer++;
339 
340         /* Increment the address */
341         writeaddr += 1;
342     }
343 }
344 
345 /*!
346     \brief      read a block of 8-bit data from the EXMC SDRAM memory
347     \param[in]  sdram_device: specify which a SDRAM memory block is written
348     \param[in]  pbuffer: pointer to buffer
349     \param[in]  readaddr: SDRAM memory internal address to read from
350     \param[in]  numbytetoread: number of bytes to read
351     \param[out] none
352     \retval     none
353 */
sdram_readbuffer_8(uint32_t sdram_device,uint8_t * pbuffer,uint32_t readaddr,uint32_t numbytetoread)354 void sdram_readbuffer_8(uint32_t sdram_device, uint8_t *pbuffer, uint32_t readaddr, uint32_t numbytetoread)
355 {
356     uint32_t temp_addr;
357 
358     /* select the base address according to EXMC_Bank */
359     if (sdram_device == EXMC_SDRAM_DEVICE0) {
360         temp_addr = SDRAM_DEVICE0_ADDR;
361     } else {
362         temp_addr = SDRAM_DEVICE1_ADDR;
363     }
364 
365     /* while there is data to read */
366     for (; numbytetoread != 0; numbytetoread--) {
367         /* read a byte from the memory */
368         *pbuffer++ = *(uint8_t *)(temp_addr + readaddr);
369 
370         /* increment the address */
371         readaddr += 1;
372     }
373 }
374 
375 /*!
376     \brief      write a half-word buffer(data is 16 bits) to the EXMC SDRAM memory
377     \param[in]  sdram_device: specify which a SDRAM memory block is written
378     \param[in]  pbuffer: pointer to buffer
379     \param[in]  writeaddr: SDRAM memory internal address from which the data will be written
380     \param[in]  numbytetowrite: number of half-word to write
381     \param[out] none
382     \retval     none
383 */
sdram_writebuffer_16(uint32_t sdram_device,uint16_t * pbuffer,uint32_t writeaddr,uint32_t numtowrite)384 void sdram_writebuffer_16(uint32_t sdram_device, uint16_t *pbuffer, uint32_t writeaddr, uint32_t numtowrite)
385 {
386     uint32_t temp_addr;
387     __IO uint32_t write_addr_prt = writeaddr;
388 
389     /* Select the base address according to EXMC_Bank */
390     if (sdram_device == EXMC_SDRAM_DEVICE0) {
391         temp_addr = SDRAM_DEVICE0_ADDR;
392     } else {
393         temp_addr = SDRAM_DEVICE1_ADDR;
394     }
395 
396     /* While there is data to write */
397     for (; numtowrite != 0; numtowrite--) {
398         /* Transfer data to the memory */
399         *(uint16_t *)(temp_addr + write_addr_prt) = *pbuffer++;
400 
401         /* Increment the address */
402         write_addr_prt += ADDR_STEP;
403     }
404 }
405 
406 /*!
407     \brief      read a block of 16-bit data from the EXMC SDRAM memory
408     \param[in]  sdram_device: specify which a SDRAM memory block is written
409     \param[in]  pbuffer: pointer to buffer
410     \param[in]  readaddr: SDRAM memory internal address to read from
411     \param[in]  numtowrite: number of half-word to read
412     \param[out] none
413     \retval     none
414 */
sdram_readbuffer_16(uint32_t sdram_device,uint16_t * pbuffer,uint32_t readaddr,uint32_t numtowrite)415 void sdram_readbuffer_16(uint32_t sdram_device, uint16_t *pbuffer, uint32_t readaddr, uint32_t numtowrite)
416 {
417     uint32_t temp_addr;
418     __IO uint32_t write_addr_prt = readaddr;
419 
420     /* select the base address according to EXMC_Bank */
421     if (sdram_device == EXMC_SDRAM_DEVICE0) {
422         temp_addr = SDRAM_DEVICE0_ADDR;
423     } else {
424         temp_addr = SDRAM_DEVICE1_ADDR;
425     }
426 
427     /* while there is data to read */
428     for (; numtowrite != 0; numtowrite--) {
429         /* read a byte from the memory */
430         *pbuffer++ = *(uint16_t *)(temp_addr + write_addr_prt);
431 
432         /* increment the address */
433         write_addr_prt += ADDR_STEP;
434     }
435 }
436