if (EPD_Init(&epd, lut_full_update) != 0) {
//printf("e-Paper init failed\n");
HAL_UART_Transmit(&hlpuart1, "e-Paper init failed\r\n", strlen("e-Paper init failed\r\n"), 100);
}
uint8_t spi_estado = HAL_SPI_GetState(&hspi1);
memset(uartBuf, '\0', sizeof(uartBuf));
sprintf(uartBuf, "SPI estado: 0x%08X | %d\r\n", spi_estado, spi_estado);
HAL_UART_Transmit(&hlpuart1, uartBuf, strlen(uartBuf), 100);while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
and the spi send function looks like:void EpdSpiTransferCallback(unsigned char data) {
HAL_GPIO_WritePin((GPIO_TypeDef*)pins[CS_PIN].port, pins[CS_PIN].pin, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1, &data, 1, 1000);
while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
HAL_GPIO_WritePin((GPIO_TypeDef*)pins[CS_PIN].port, pins[CS_PIN].pin, GPIO_PIN_SET);
}Are you using a debugger (stlink) to see if you code is getting stuck somewhere or doing anything unexpected?
Performing an SPI transfer *in* the SPI transfer complete callback doesn't seem right to me (I think thats what it is). Try updating every 500ms or something instead.
This is probably just a bad driver, or improper use of the driver. The driver expects the display to be in a certain state, which it isn't due to a previous command not being performed or being sent while busy.
You can check with a logic analyzer if the SPI still sends stuff, which I'm sure it does.
Verify if the display also has a busy bit, check this when waiting for it to do it's thing.
Also verify that you're not going to a sleep mode that loses register and ram contents that you do not expect to lose.
I need buy one.I haven't played with STM32 SPI so feel free to ignore all of this:
SPI packets are framed by CS' First, CS goes low, some data is transferred (the length in bytes is determined by the slave) and, AFTER the last byte is actually transferred and the SPI gadget changes state to Ready (or sends a completion interrupt), then CS is changed to high.
The problem with most code is that it doesn't wait for the last byte to transfer before raising CS' and from then on, things go sideways. Perhaps the last byte of the previous transaction is now the first byte of the current transaction.
I'm not going to go through the HAL code, that stuff is too grim to contemplate. I swear these libraries are created by doctors specializing in Carpel Tunnel surgery caused by the excessive typing. Never use 5 characters when an entire sentence will suffice!
It appears that the code above actually waits for Ready but unless I read the datasheet and reviewed the library code, I would be wondering. Of course a logic analyzer is a great help and I actually bought the 4 channel Rigol DS1054Z scope for the specific purpose of decoding SPI transactions. Yes, it also does a lot of other really neat things!
The e-paper only have a 3 SPI pins (MOSI, CLK, CS) and other pins as reset, busy, vcc, gnd... Between loops i turn off the VCC e-paper, so the hardware should be how the first cycle.
If you turn off Vcc from the display then you must also tell the library is should initialize the display again.
Anyway, resetting SPI is easy. See RCC->APB2RSTR bit SPI1RST (bit 12), chapter 7.3.10 of the reference manual.
The DS1054Z does have SPI protocol decoding as an option. This forum has topics about how to enable those protocol decoding options if it isn't enabled already.The e-paper only have a 3 SPI pins (MOSI, CLK, CS) and other pins as reset, busy, vcc, gnd... Between loops i turn off the VCC e-paper, so the hardware should be how the first cycle.Does the library know about this busy signal? Did you implement this correctly?
I test the SPI reset but dont works. I have added this lines (MX_SPI1_Init() is used in each loop before i use the e-paper):
I am using too an ADC, TIM2, UART2, LPUART1 and RTC. Could be any interference between interfaces?
RCC->APB2RSTR |= RCC_APB2RSTR_SPI1RST; //reset SPI1
RCC->APB2RSTR &= ~RCC_APB2RSTR_SPI1RST; //reset SPI1
MX_SPI1_Init();
HAL_Delay(1000);
if (EPD_Init(&epd, lut_full_update) != 0) {
HAL_UART_Transmit(&hlpuart1, "e-Paper init failed\r\n", strlen("e-Paper init failed\r\n"), 100);
}EPD epd;if (EPD_Init(&epd, lut_full_update) != 0) {
HAL_UART_Transmit(&hlpuart1, "e-Paper init failed\r\n", strlen("e-Paper init failed\r\n"), 100);
}unsigned char* frame_buffer = (unsigned char*)malloc(EPD_WIDTH * EPD_HEIGHT / 8);Ouch.
* Does the MCU even have enough RAM for this malloc?
* Is malloc called only once or repeatedly without ever freeing memory?
Malloc uses heap, do you have heap enabled and assigned?
Does Malloc return a usable pointer and not NULL?
Do you even need to use malloc, could you point to a static allocated aligned array of size (EPD_WIDTH * EPD_HEIGHT / 8 ).
My program use 65% of the RAM. When i compile the code, i don´t get any warning about space.
If i don´t write in main(), the malloc is called one in each loop.
My program use 65% of the RAM. When i compile the code, i don´t get any warning about space.
If i don´t write in main(), the malloc is called one in each loop.
It is my first time that i use malloc. I have not enogh knowledge about this. I need learn more about it.
Thanks,
Regards.
unsigned char frame_buffer[(EPD_WIDTH * EPD_HEIGHT / 8)];
Malloc is also unable to allocate enough memory. The last bit of screen will be outside the SRAM. This may or may not create a fault.
And then it makes sense it only works once, because the chip will be in the hardfault handler when it writes to the non-existing memory.
Or worse, malloc does allocate memory, completely overwriting the other parts of your application.