board707 / w80x_arduino

w806 package for Arduino IDE
GNU Lesser General Public License v2.1
68 stars 12 forks source link

Can Not get (2) PSRAM chips to work together #33

Open jcoleman-oneaihealth opened 9 months ago

jcoleman-oneaihealth commented 9 months ago

Hey AnatolSher , thanks for the help with getting the 1st PSRAM chip to work !

--

But now I am using Multiple PSRAM chips.

I stacked (2) chips.

PSRAM Wiring :

PB6 + PB1   CS     \/   +Vdd
      PB3   IO1/SO  IO3/Hold    PB5 
      PB4   IO2/WP      SCLK    PB0  
            Gnd-      SI/IO0    PB2 

1st Chip has CS connected to BP1 - with 100K resistor tied to V++. 2nd Chip has CS connected to BP6 - with 100K resistor tied to V++ also.

It works fine, if I ONLY Initialize PSRAM with CS PB1.

--

But if I disable PB1 cs as :

  /// DeSelect cs=PB1 : ///
  pinMode(      PB1 , OUTPUT );
  digitalWrite( PB1 , HIGH   );

Then ReInit PSRAM :

PSRAM_ReInit_CS( GPIOB , GPIO_PIN_6 );

static void  PSRAM_ReInit_CS( GPIO_TypeDef* gpio_N , int cs_N )
{
 //  __HAL_RCC_PSRAM_CLK_ENABLE();
 //  __HAL_RCC_GPIO_CLK_ENABLE();

/*  
  BRD PSRAM :
PB1   CS    \/   +Vdd
PB3   IO1/SO IO3/Hold    PB5 
PB4   IO2/WP     SCLK    PB0  
      Gnd-     SI/IO0    PB2 
*/

 //  __HAL_AFIO_REMAP_PSRAM_CS(GPIOB, GPIO_PIN_1);   // PB1 / CS   // CS 
  __HAL_AFIO_REMAP_PSRAM_CS( gpio_N , cs_N );   //  ..  CS   // CS 

  __HAL_AFIO_REMAP_PSRAM_CLK(GPIOB, GPIO_PIN_0);  // PB0 / SCLK // SCK 
  __HAL_AFIO_REMAP_PSRAM_D0(GPIOB, GPIO_PIN_2);   // PB2 / MOSI // SI/IO0 
  __HAL_AFIO_REMAP_PSRAM_D1(GPIOB, GPIO_PIN_3);   // PB3 / MISO // SO/IO1 
  __HAL_AFIO_REMAP_PSRAM_D2(GPIOB, GPIO_PIN_4);   // PB4        // WP/IO2 
  __HAL_AFIO_REMAP_PSRAM_D3(GPIOB, GPIO_PIN_5);   // PB5        // Hold/IO3 

  hpsram.Instance  = PSRAM;
 //   hpsram.Init.Div  = 2;    // - (160MHz) BAD DATA on Ips6404 - 
   hpsram.Init.Div  = 3;    // - (80MHz) WORKS on Ips6404 -
//  hpsram.Init.Div  = 0 ;  // => 0xFF ...
////   hpsram.Init.Div  = 4 ; // = 5 , = 8 ;
 ////  hpsram.Init.Div  = 15;  // = 2-15
////  hpsram.Init.Div  = 20;
////  hpsram.Init.Div  = 32;
  hpsram.Init.Mode = PSRAM_MODE_QSPI;

  if (HAL_PSRAM_Init(&hpsram) != HAL_OK)
  {
    Serial.printf("Init error...\r\n");
  }
}

=> *** It Just Reads FFs from either PSRAM ... !!!

-- Maybe I need to DeInit PSRAM before Init_PSRAM() again ???

AnatolSher commented 9 months ago

Hello! It doesn't work that way. You need to use an analog bidirectional switch or digital equivalent. The signal on pin PB6 should switch banks. Double initialization of the PSRAM controller is also required. Separately for each bank The scheme is something like this, without going into details image

jcoleman-oneaihealth commented 9 months ago

I tried that using a 74hc4051. But it did not work. I was thinking maybe it was too slow.

Whats wrong with just (2) gpio to (2) CS pins - instead of MUX ?

-

So, I tried with just : PB1-> Ram1chip:CS PB6-> Ram2chip:CS

That was the code above. But it just spits out 0xFFs with PB6 as CS in ReInit()

AnatolSher commented 9 months ago

Whats wrong with just (2) gpio to (2) CS pins - instead of MUX ?

Because it doesn't make sense. The CS line is controlled by the PSRAM controller in hardware. We can only change the time that this line is held low level. The multiplexer must be selected high-frequency. SN74LVC (TI) or ADG (AD) Such multiplexers work well: image

I don't understand why you need 2 banks, but you should simulate the standard connection of one bank

jcoleman-oneaihealth commented 9 months ago

How about : SN74LVC138APW ?

AnatolSher commented 9 months ago

No. This is not the right chip for your purposes. 2 X SN74LV4053 is good Might look like this: image

You need to take care of the correct PCB wiring and draw the missing pull-up resistors and blocking capacitors And there is no guarantee that such a solution will work in hardware :) At your own peril and risk

PS. If you don't have enough RAM and you are a fan of C-SKY architecture, it's better to use this... maybe image $6 C-SKY Linux Development Board Features GX6605S Media SoC with C-SKY ISA

jcoleman-oneaihealth commented 9 months ago

Why MUX every SpiRam chip pin to the GPIOs ? If the SpiRam is Not Enabled via its CS - then all of that Chip IOs are disabled.

W806:            SpiRam #1 : 
               +-----------+
GB1  --------> | CS
       *-----> |   MISO
       |  *--> |  MOSI
       |  |    | ... etc
       |  |    +-----------+
MISO   |  |
GPIO --*  |       SpiRam #2 :   
GPIO --|--*    +-----------+
MOSI   *--|--> |  MISO
          *--> | MOSI
               | ... etc
GB6 ---------> | CS
               +-----------+

I dual connected each SpiRam Pin to the same W806 GPIO pins , except the CS pins were on separate GPIO pins (PB1 and PB6).

I could then Intitialize PSRAM / SpiRam # 1 , using SpiRam as CS->PB1 , -- then talked with SpiRam chip # 1 worked with good data.

But when I changed GPIO PB1 to Input , then Initialized PSRAM / SpiRam # 2 with CS=GB6 , -- the PSRAM just went to returning only FFs.

AnatolSher commented 9 months ago

Why MUX every SpiRam chip pin to the GPIOs ? If the SpiRam is Not Enabled via its CS - then all of that Chip IOs are disabled.

First: Because I'm not sure that the PSRAM pins of the chip (d0-d3) will go to Z state when the CS signal is high. Second: You cannot influence the CS line of the PSRAM memory controller. There is no HardSS or SoftSS mode as in the SPI interface image Eng:tCPH, CS high level minimum time setting, the unit is the number of AHB clock cycles, must be greater than 1, the specific time depends on Set according to the instructions in the same psram manual. If you are not sure, you don’t need to modify the default value.

Your approach to increasing capacity is good for software emulation of the PSRAM communication protocol. Take a good logic analyzer and look in real time at what is happening at the pins of your dual assembly. Especially watch the CS line If the PSRAM pins can go into the Z state, you can get by with one MUX (sn74lvc1g3157) and switch only the CS lines Don't forget to connect CS and CS' to power via pull-up resistors

jcoleman-oneaihealth commented 9 months ago

Yeah, got that. Both CS lines are tied High via 100K resistors.

PSRAM # 1 Initializes and runs SUCCESSFULLY - even though both PSRAM chips are stacked - as the diagram above.

-- But I can not figure out how to switch to PSRAM # 2 successfully, (and back to PSRAM # 1 ... etc).

I think it needs something to De-Initialize current PSRAM # 1 with CS=PB1 in the code. -- Then I can Initialize 2nd PSRAM (with CS=PB6).

And vice-a-versa, to switch back to PSRAM # 1 again : De-Initialize current PSRAM # 2 (with CS=PB6), then i can Initialize PSRAM # 1 (with CS=PB1) again.

It may be slower, but I can switch back and forth between PSRAMs. Just need to keep Initializing next PSRAM # .

--

Btw: Where are these located in the Libraries / Include Files (I can not find them) : HAL_PSRAM_Init PSRAM PSRAM_MODE_QSPI PSRAM_HandleTypeDef

AnatolSher commented 9 months ago

wm_psram.* C:\Users\User\AppData\Local\Arduino15\packages\w80x_duino\hardware\XT804\0.0.5\cores\w806\include\driver C:\Users\User\AppData\Local\Arduino15\packages\w80x_duino\hardware\XT804\0.0.5\cores\w806\lib\drivers Instead of PB6, PB27 is used. This makes it more convenient to switch CS via HAL PB6 does not map to PSRAM controller image image

HAL_AFIO_REMAP_PSRAM_CS(GPIOB, GPIO_PIN_27); or HAL_AFIO_REMAP_PSRAM_CS(GPIOB, GPIO_PIN_1); In this case, set the opposite CS to HIGH

But the question arises... What happens inside the PSRAM chip during reinitialization? If the regeneration system turns off at this moment, all data will be lost. It seems to me that it is enough to do the initialization once for each bank. And then just remap only CS to the required bank

jcoleman-oneaihealth commented 9 months ago

Ok Thx , yeah only PB1 + PB27 as PSRAM_CS. Let me try.

I also ordered : SN74LVC138AD SN74LVC1G3157DCKR

I found the code. Its the arduino code hidden in the users dir ... There is a DeInit() function :

/**
  * @brief  Initializes the PSRAM according to the specified parameters
  *         in the PSRAM_InitTypeDef and create the associated handle.
  * @param  hpsram pointer to a PSRAM_HandleTypeDef structure that contains
  *         the configuration information for PSRAM module
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_PSRAM_Init(PSRAM_HandleTypeDef *hpsram)
{
    uint32_t value = 0x605;

    if(hpsram == NULL)
    {
        return HAL_ERROR;
    }
    assert_param(IS_PSRAM_INSTANCE(hpsram->Instance));
    assert_param(IS_PSRAM_DIV(hpsram->Init.Div));
    assert_param(IS_PSRAM_MODE(hpsram->Init.Mode));

    HAL_PSRAM_MspInit(hpsram);

    value |= ((hpsram->Init.Div << PSRAM_CR_DIV_Pos) | hpsram->Init.Mode);
    WRITE_REG(hpsram->Instance->CR, value);
    do{
        value = READ_REG(hpsram->Instance->CR);
    } while(value & 0x01);

    return HAL_OK;
}

/**
  * @brief  DeInitializes the PSRAM peripheral
  * @param  hpsram pointer to a PSRAM_HandleTypeDef structure that contains
  *         the configuration information for PSRAM module
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_PSRAM_DeInit(PSRAM_HandleTypeDef *hpsram)
{
    if (hpsram == NULL)
    {
        return HAL_ERROR;
    }

    assert_param(IS_PSRAM_INSTANCE(hpsram->Instance));
    HAL_PSRAM_MspDeInit(hpsram);

    return HAL_OK;
}
AnatolSher commented 9 months ago

jcoleman-oneaihealth Hello! What progress has been made? You intrigued me with your idea with two psram chips. If I have free time next week, I'll try to do this in practice too. I don't know why I need this :)

jcoleman-oneaihealth commented 9 months ago

It is useful. I am working on Robotics AI, and Vision Recognition.

One of the projects is using the Ov7670 camera (from the Arduino Library) on the W806. -- Multiple 8Mx8 PSRAMs would be very useful for this.