Forum Discussion

Zahkriin's avatar
Zahkriin
Icon for New Contributor rankNew Contributor
4 years ago

Max1000 Remote System Upgrade via SPI

Hello,

I have a Max1000 development board and would like to perform a remote system upgrade with it.
I have programmed an SPI interface to send the required data. (Here not necessarily SPI must be used, but I think another interface does not change my problem). Now I want to program the RSU without the Nios.
I have gotten to the point where I need the dual boot ip core to configure the "dual compressed image". An onchip-Ram to store the necessary data and an onchip-Flash to write to the CFM. But here my flash has only an address size of 17 bits, but to rewrite the CFM the address must be at least 18 bits.

Am I missing something here? Is it possible to rewrite the CFM with SPI like this?

58 Replies

    • Zahkriin's avatar
      Zahkriin
      Icon for New Contributor rankNew Contributor

      Thanks for the example project. I found an answer to my question, however I don't quite understand why? You write in line 854 that the maximum address is 13ffh (79871). In the Platform Designer it says under Flash Memory that the largest address is 0x4dfff (319487 or 8*79871 - 1). Why do you divide the addresses by 8?
      Furthermore I don't understand your page_erase_addr in line 740. Of course you take 19 bits, because there is so much space in the register. But why do you start counting up in the middle?

      • jozephka99's avatar
        jozephka99
        Icon for Contributor rankContributor

        1. As in the UFM user guide at (https://www.intel.com/content/www/us/en/docs/programmable/683180/18-0/sector-address.html), you have to convert the sector addresses to the avalon mm addresses. This process done by dividing 4 not 8 (2 bit shifting).

        2. Page erase operation at below the line ~740 is just UFM erase. Actually you can add here CFM sectors as well but I done CFM sectors erasing in sector erase mode. As you can see in UFM user guide (https://www.intel.com/content/www/us/en/docs/programmable/683180/18-0/ufm-and-cfm-array-size.html) 10M08 devices has 8+8= 16 pages in UFM sections. If you look at the flash ip, you can see that UFM sectors are between 0 and 0x07fff. It is normal sector addressing. It means approximately 0 - 0x2000 in avalon addressing and that is equal to 0-8192 bits. So we have 16 pages total, then one page's address is 8192/16=512 in avalon addressing. For this reason I increase the UFM page erase addresses by 512 for each page of UFM. I hope it doesn't confusing. In fact it is hard to understand that addressing and documentations about it is very poor.

    • JensVkb's avatar
      JensVkb
      Icon for Occasional Contributor rankOccasional Contributor

      @jozephka99 Why is it ok to start programming the flash data from either address 0xAC00 or 0x2000, based on the addresses shown in the Flash IP configuration, while the addresses shown in the .map file are a bit higher? In the map it shows 0x8800 as start of CFM1, so 0x2200, and 2B800 as start of CFM0, so 0xAE00.

      This is based on your lines 373 - 378 from the file manual_rsu.vhd. I'm guessing your code works, so it is correct to use the addresses of the Flash IP block and not to use the .map information.

      • jozephka99's avatar
        jozephka99
        Icon for Contributor rankContributor

        It is because the actual data -that differs from 1's- in that .rpd file begins from 0x8800 (0x2200) (CFM1) and 0x2B800 (0xAE00) (CFM0). Data before this addresses is full of "FF"s that is default value of OC RAM. (You can see that if you open the .rpd file with a HEX editor.) .map tells us that you don't have to change these addresses because you already erase the OC RAM before writing it and they are already in the default values. So you can either begin from addresses that shown in IP core like me, or you can use .map addressings. But I think .map addressings can change and it is not that easy to do it in dynamic way.

    • sadann22's avatar
      sadann22
      Icon for New Contributor rankNew Contributor

      I'm very interested to learn from your example but there is a problem during download because i received this:

      Anti-virus warning

      – 1 attachment contains a virus or blocked file. Downloading this attachment is disabled.

      Is there another way I can get your exaple.

      • jozephka99's avatar
        jozephka99
        Icon for Contributor rankContributor

        Which file did you try to download. I downloaded the project zip file in opera without any error. May be you can try it with different browser.

  • sstrell's avatar
    sstrell
    Icon for Super Contributor rankSuper Contributor

    What are your settings under "Configuration Mode" (that section is minimized in your screenshot)?

    Also, which exact MAX 10 device is on that board (10Mxx)? The size of the CFM is different for different members of the family.

  • Zahkriin's avatar
    Zahkriin
    Icon for New Contributor rankNew Contributor

    Under the settings stand:

    Configuration Scheme: Internal Configuration

    Configuration Mode: Dual Compressed Images

    This is how I have seen it in various videos on the subject. And I have an 10M08SAU169C8G on the board.

  • sstrell's avatar
    sstrell
    Icon for Super Contributor rankSuper Contributor

    That's weird. Are you using Platform Designer? I'm guessing yes. Are you just exporting the Avalon interface out of the system and then connecting your control mechanism to it externally? What are you using for control if not Nios?

  • Zahkriin's avatar
    Zahkriin
    Icon for New Contributor rankNew Contributor

    Yes, I am using the Platform Designer. I put the onchip-flash, onchip-memory and dual_boot in a Qsys file and added it to the project. I link the signals externally. I'll add a scrrenshot of it.

    I would like to implement the RSU not with the Nios, but with an own logic circuit. So that I write the VHDL code myself to read and write the register and read from the flash or write on the flash. I could already read the register and got the expected data. It should not really change my problem if the Nios or something else is connected, because it does not increase the size of the addresbus from the onchip flash.

    This is how a part of my interface to the onchip flash should look like then. I read the register, then I write in the register the command to clear a page and wait until the bit in the register is set that the clear was successful. But no matter how that looks, it shouldn't change my problem.

       -- -------------------------------------------------------------------------------------
        --  erase Page or sector
        -- -------------------------------------------------------------------------------------	 
    	 procedure register_erase (
        i_data_register       : in  std_logic_vector(31 downto 0)) is
        begin
    	     CASE operation_register IS
    		  
    	     -- 1. read in which mode flash is
            -- 2. write erase command in register 0x01
    	     -- 3. Check register 0x00 wheather erase was sucessful
    		  -- 4. reset register 0x01 
    		  WHEN mode_start =>
    		      onchip_flash_register_addr <= '0';
    		      onchip_flash_register_read <= '1';
    				IF count_flash <= 5 THEN
    				    count_flash <= count_flash + 1;
    				ELSE
    				    IF onchip_flash_register_readdata (1 DOWNTO 0) = "00" THEN
    				        -- Flash is in IDLE mode
    						  operation_register <= mode_write;
    						  count_flash <= 0;
    				    ELSE
    					     -- Flash is busy
    						  count_flash <= 0;
    						  count_error_flash <= count_error_flash + 1;
    					 END IF;
    				END IF;
    				
    		  WHEN mode_write =>
    		      onchip_flash_register_read <= '0';
    				onchip_flash_register_addr <= '1';
    		      onchip_flash_register_write <= '1';
    				onchip_flash_register_writedata <= i_data_register;
    				-- wait a few ns to write in register
    				IF count_flash <= 10 THEN
    				    count_flash <= count_flash + 1;
    				ELSE
    				    count_flash <= 0;
    				    operation_register <= mode_check;
    				END IF;
    				
    		  WHEN mode_check =>
    		      onchip_flash_register_read <= '1';
    				onchip_flash_register_addr <= '0';
    		      onchip_flash_register_write <= '0';
    				-- wait a few ns to read from register
    				IF count_flash <= 10 THEN
    				    count_flash <= count_flash + 1;
    				ELSE
    				    IF onchip_flash_register_readdata (4 DOWNTO 4) = "1" THEN
    				        -- erase was sucessful
    						  count_flash <= 0;
    						  count_error_flash <= 0;
    				        operation_register <= mode_reset;
    					 ELSE
    					     -- erase wasnt sucessful
    						  count_flash <= 0;
    						  count_error_flash <= count_error_flash + 1;
    						  operation_register <= mode_write;
    					 END IF;
    				END IF;
    		  
    		  WHEN mode_reset =>
    		      onchip_flash_register_read <= '0';
    				onchip_flash_register_addr <= '1';
    		      onchip_flash_register_write <= '1';
    				onchip_flash_register_writedata <= x"FF800000";
    				-- wait a few ns to write in register
    				IF count_flash <= 5 THEN
    				    count_flash <= count_flash + 1;
    				ELSE
    				    count_flash <= 0;
    				    operation_register <= mode_start;
    					 operation_flash <= mode_wait;
    					 onchip_flash_register_addr <= '0';
    		          onchip_flash_register_write <= '0';
    				END IF;
    		  
    		  WHEN OTHERS =>
    		      operation_register <= mode_start;
    		  
    		  END CASE;
    	 
        end register_erase;
  • sstrell's avatar
    sstrell
    Icon for Super Contributor rankSuper Contributor

    You're exporting everything out of the system, so you're not really building a system. If you make connections in the system without exporting and set proper addressing, the tool checks and makes sure everything in the interconnect is set up correctly and this might fix your issue.

    • Zahkriin's avatar
      Zahkriin
      Icon for New Contributor rankNew Contributor

      I want to lead the signals out of the system to be able to set them manually. Just like jozephka99 did in his example. You can use only one nios in the system itself to set them? Or is there another alternative?

  • Chudik's avatar
    Chudik
    Icon for New Contributor rankNew Contributor

    How interesting. The topic is Remote System Upgrade via SPI

    However everybody switched to UART... May I make offtopic question and ask about discrete RSU via SPI (or I2C)?

    From the very starting point - which IP block should I use for it?

    The part I'm using is 10M08 with Verilog. I can translate from VHDL to Verilog, but original Verilog code is preferable.

    There is a page with example for RSU via I2C but it does not help. Opening .par file shows only top file for 10M50 used as a I2C host. Structure of the project and used IP blocks are invisible

    Besides the description of the project and how to run written for Quartus 16 and for a template it suggests to use an evaluation board that does not exist anymore.