| /**************************************************************************** |
| * boards/arm/sama5/sama5d4-ek/src/at25_main.c |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. The |
| * ASF licenses this file to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance with the |
| * License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations |
| * under the License. |
| * |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Included Files |
| ****************************************************************************/ |
| |
| #include <nuttx/config.h> |
| |
| #include <stdint.h> |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <fcntl.h> |
| #include <errno.h> |
| #include <debug.h> |
| #include <hex2bin.h> |
| |
| #include <nuttx/streams.h> |
| #include <arch/irq.h> |
| |
| #include "sama5d4-ek.h" |
| |
| /**************************************************************************** |
| * Pre-processor Definitions |
| ****************************************************************************/ |
| |
| /* Configuration ************************************************************/ |
| |
| #ifndef HAVE_AT25 |
| # error The AT25 Serial FLASH is not available |
| #endif |
| |
| #ifndef CONFIG_SAMA5D4EK_AT25_BLOCKMOUNT |
| # error CONFIG_SAMA5D4EK_AT25_BLOCKMOUNT must be selected |
| #endif |
| |
| #ifndef CONFIG_SAMA5D4EK_AT25_CHARDEV |
| # error CONFIG_SAMA5D4EK_AT25_CHARDEV must be selected |
| #endif |
| |
| #ifdef CONFIG_BOOT_SDRAM_DATA |
| # error CONFIG_BOOT_SDRAM_DATA must NOT be selected |
| #endif |
| |
| #if !defined(CONFIG_SAMA5D4EK_AT25_PROGSIZE) || CONFIG_SAMA5D4EK_AT25_PROGSIZE < 128 |
| # error Large CONFIG_SAMA5D4EK_AT25_PROGSIZE must be selected |
| #endif |
| |
| #define DEVNAME_MAXSIZE 12 |
| #define IOBUFFER_SIZE 512 |
| |
| /**************************************************************************** |
| * Private Types |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Private Data |
| ****************************************************************************/ |
| |
| static uint8_t g_iobuffer[IOBUFFER_SIZE]; |
| static char g_at25dev[DEVNAME_MAXSIZE]; |
| |
| /**************************************************************************** |
| * Private Functions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Public Functions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Name: at25_main |
| * |
| * Description: |
| * at25_main is a tiny program that runs in ISRAM. at25_main will |
| * configure DRAM and the AT25 serial FLASH, present a prompt, and load |
| * an Intel HEX file into the AT25 serial FLASH (after first buffering |
| * the binary data into memory). On re-boot, the program loaded into |
| * the AT25 FLASH should then execute. |
| * |
| * On entry: |
| * - SDRAM has already been initialized (we are using it for .bss!) |
| * - SPI0 chip select has already been configured. |
| * |
| ****************************************************************************/ |
| |
| int at25_main(int argc, char *argv[]) |
| { |
| struct lib_rawinstream_s rawinstream; |
| struct lib_memsostream_s memoutstream; |
| const uint8_t *src; |
| ssize_t nwritten; |
| ssize_t nread; |
| ssize_t remaining; |
| size_t rdsize; |
| int fd; |
| int ret; |
| |
| /* Configure the AT25 as the a character device. */ |
| |
| ret = sam_at25_automount(AT25_MINOR); |
| if (ret < 0) |
| { |
| fprintf(stderr, "ERROR: Failed to mount AT25 FLASH: %d\n", ret); |
| return EXIT_FAILURE; |
| } |
| |
| /* Open the AT25 device for writing */ |
| |
| snprintf(g_at25dev, DEVNAME_MAXSIZE, "/dev/mtd%d", AT25_MINOR); |
| fd = open(g_at25dev, O_WRONLY); |
| if (fd < 0) |
| { |
| int errcode = errno; |
| fprintf(stderr, "ERROR: Failed to open %s: %d\n", g_at25dev, errcode); |
| return EXIT_FAILURE; |
| } |
| |
| /* Wrap stdin as an IN stream that can the HEX data over the serial port */ |
| |
| lib_rawinstream(&rawinstream, 0); |
| |
| /* Define a memory buffer of size CONFIG_SAMA5D4EK_AT25_PROGSIZE at the |
| * beginning of SDRAM. Wrap the memory buffer as a seek-able OUT stream in |
| * which we can buffer the binary data. |
| */ |
| |
| lib_memsostream(&memoutstream, (char *)SAM_DDRCS_VSECTION, |
| CONFIG_SAMA5D4EK_AT25_PROGSIZE); |
| |
| /* We are ready to load the Intel HEX stream into DRAM. |
| * |
| * Hmm.. With no hardware handshake, there is a possibility of data loss |
| * to overrunning incoming data buffer. So far I have not seen this at |
| * 115200 8N1, but still it is a possibility. |
| */ |
| |
| printf("Send Intel HEX file now\n"); |
| fflush(stdout); |
| |
| ret = hex2bin(&rawinstream.common, &memoutstream.common, |
| SAM_ISRAM_VSECTION, |
| SAM_ISRAM_VSECTION + CONFIG_SAMA5D4EK_AT25_PROGSIZE, |
| 0); |
| if (ret < 0) |
| { |
| /* We failed the load */ |
| |
| fprintf(stderr, "ERROR: Intel HEX file load failed: %d\n", ret); |
| close(fd); |
| return EXIT_FAILURE; |
| } |
| |
| /* Replace the vector at offset 0x14 with the size of the image to load |
| * into SRAM. The RomBOOT loader expects to find this size at that |
| * location. |
| */ |
| |
| *(uint32_t *)(SAM_DDRCS_VSECTION + 0x14) = memoutstream.common.nput; |
| |
| /* The HEX file load was successful, write the data to FLASH */ |
| |
| printf("Successfully loaded the Intel HEX file into memory...\n"); |
| printf(" Writing %d bytes to the AT25 Serial FLASH\n", |
| memoutstream.common.nput); |
| |
| remaining = memoutstream.common.nput; |
| src = (uint8_t *)SAM_DDRCS_VSECTION; |
| |
| do |
| { |
| nwritten = write(fd, src, memoutstream.common.nput); |
| if (nwritten <= 0) |
| { |
| int errcode = errno; |
| if (errno != EINTR) |
| { |
| fprintf(stderr, "ERROR: Write failed: %d\n", errcode); |
| close(fd); |
| return EXIT_FAILURE; |
| } |
| } |
| else |
| { |
| remaining -= nwritten; |
| src += nwritten; |
| } |
| } |
| while (remaining > 0); |
| |
| close(fd); |
| |
| /* Now verify that the image in memory and the image in FLASH are truly |
| * the same. |
| */ |
| |
| printf(" Verifying %d bytes in the AT25 Serial FLASH\n", |
| memoutstream.common.nput); |
| |
| /* Open the AT25 device for writing */ |
| |
| fd = open(g_at25dev, O_RDONLY); |
| if (fd < 0) |
| { |
| int errcode = errno; |
| fprintf(stderr, "ERROR: Failed to open %s: %d\n", g_at25dev, errcode); |
| return EXIT_FAILURE; |
| } |
| |
| remaining = memoutstream.common.nput; |
| src = (const uint8_t *)SAM_DDRCS_VSECTION; |
| |
| do |
| { |
| rdsize = remaining; |
| if (rdsize > IOBUFFER_SIZE) |
| { |
| rdsize = IOBUFFER_SIZE; |
| } |
| |
| nread = read(fd, g_iobuffer, rdsize); |
| if (nread <= 0) |
| { |
| int errcode = errno; |
| if (errno != EINTR) |
| { |
| fprintf(stderr, "ERROR: Read failed: %d\n", errcode); |
| close(fd); |
| return EXIT_FAILURE; |
| } |
| } |
| else |
| { |
| if (memcmp(g_iobuffer, src, nread) != 0) |
| { |
| fprintf(stderr, "ERROR: Verify failed at offset %d\n", |
| memoutstream.common.nput - remaining); |
| close(fd); |
| return EXIT_FAILURE; |
| } |
| |
| remaining -= nwritten; |
| src += nwritten; |
| } |
| } |
| while (remaining > 0); |
| |
| printf(" Successfully verified %d bytes in the AT25 Serial FLASH\n", |
| memoutstream.common.nput); |
| |
| close(fd); |
| return EXIT_SUCCESS; |
| } |