Yes, it's quite possible and it has saved my life for a project I was working on where I had everything built around HAL.
Believe it or not, I kept resisting the transition to that HAL thing for so long, until I found myself forced to use it for my project due to many advantages it provides on certain aspect.
However, part of my project is to control a slave device over SPI and I had the library for the SPL from ST. After spending a tremendous time trying to solve an issue I had with the receive part of the SPI over HAL, and after giving up trying hundreds of examples and code snippets for the SPI, I have finally managed to figure it out by mixing the SPI driver from the SPL with the rest of my project, which was built with HAL.
Here's what I did in Keil uVision to get it to work for me without any problem. I have created pre-compiled objects for the SPI and any dependencies used by SPI and had those imported/linked into my HAL project. Of course, I have removed everything about HAL_SPI in the project and now the project compiles and runs quickly and smoothly. I can now drive my device with the SPL based SPI functions, and still enjoy what HAL has to offer for the remaining modules of the project.
ST has released an errata sheet called:
STM32F100xC, STM32F10 0xD and STM32F100xE high-density value line device limitations.
The interesting point here is:
2.9.7 I2C analog filter may provide wrong value, locking BUSY flag and preventing master mode entry
There is a detailed 15 step workaround that worked for me, surprisingly for an STM32F446, so I2C peripherals of every STM32 CORTEX-M series might be affected.
During this operation, the lines must not be actively pulled up or down by a bus member. So if you connect two I2C interfaces of the same MCU to the bus, first set up the pins of both to Alternate Function/Open Drain, then call the routine, as a transition of logical levels is required.
Here is an example with HAL libraries I use after the first initialization and during runtime, if an error occurs. As said above, this is for STM32F4, libraries for SMT32F1 might differ a bit.
struct I2C_Module
{
I2C_HandleTypeDef instance;
uint16_t sdaPin;
GPIO_TypeDef* sdaPort;
uint16_t sclPin;
GPIO_TypeDef* sclPort;
};
void I2C_ClearBusyFlagErratum(struct I2C_Module* i2c)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 1. Clear PE bit.
i2c->instance.Instance->CR1 &= ~(0x0001);
// 2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR).
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStructure.Alternate = I2C_PIN_MAP;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStructure.Pin = i2c->sclPin;
HAL_GPIO_Init(i2c->sclPort, &GPIO_InitStructure);
HAL_GPIO_WritePin(i2c->sclPort, i2c->sclPin, GPIO_PIN_SET);
GPIO_InitStructure.Pin = i2c->sdaPin;
HAL_GPIO_Init(i2c->sdaPort, &GPIO_InitStructure);
HAL_GPIO_WritePin(i2c->sdaPort, i2c->sdaPin, GPIO_PIN_SET);
// 3. Check SCL and SDA High level in GPIOx_IDR.
while (GPIO_PIN_SET != HAL_GPIO_ReadPin(i2c->sclPort, i2c->sclPin))
{
asm("nop");
}
while (GPIO_PIN_SET != HAL_GPIO_ReadPin(i2c->sdaPort, i2c->sdaPin))
{
asm("nop");
}
// 4. Configure the SDA I/O as General Purpose Output Open-Drain, Low level (Write 0 to GPIOx_ODR).
HAL_GPIO_WritePin(i2c->sdaPort, i2c->sdaPin, GPIO_PIN_RESET);
// 5. Check SDA Low level in GPIOx_IDR.
while (GPIO_PIN_RESET != HAL_GPIO_ReadPin(i2c->sdaPort, i2c->sdaPin))
{
asm("nop");
}
// 6. Configure the SCL I/O as General Purpose Output Open-Drain, Low level (Write 0 to GPIOx_ODR).
HAL_GPIO_WritePin(i2c->sclPort, i2c->sclPin, GPIO_PIN_RESET);
// 7. Check SCL Low level in GPIOx_IDR.
while (GPIO_PIN_RESET != HAL_GPIO_ReadPin(i2c->sclPort, i2c->sclPin))
{
asm("nop");
}
// 8. Configure the SCL I/O as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR).
HAL_GPIO_WritePin(i2c->sclPort, i2c->sclPin, GPIO_PIN_SET);
// 9. Check SCL High level in GPIOx_IDR.
while (GPIO_PIN_SET != HAL_GPIO_ReadPin(i2c->sclPort, i2c->sclPin))
{
asm("nop");
}
// 10. Configure the SDA I/O as General Purpose Output Open-Drain , High level (Write 1 to GPIOx_ODR).
HAL_GPIO_WritePin(i2c->sdaPort, i2c->sdaPin, GPIO_PIN_SET);
// 11. Check SDA High level in GPIOx_IDR.
while (GPIO_PIN_SET != HAL_GPIO_ReadPin(i2c->sdaPort, i2c->sdaPin))
{
asm("nop");
}
// 12. Configure the SCL and SDA I/Os as Alternate function Open-Drain.
GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
GPIO_InitStructure.Alternate = I2C_PIN_MAP;
GPIO_InitStructure.Pin = i2c->sclPin;
HAL_GPIO_Init(i2c->sclPort, &GPIO_InitStructure);
GPIO_InitStructure.Pin = i2c->sdaPin;
HAL_GPIO_Init(i2c->sdaPort, &GPIO_InitStructure);
// 13. Set SWRST bit in I2Cx_CR1 register.
i2c->instance.Instance->CR1 |= 0x8000;
asm("nop");
// 14. Clear SWRST bit in I2Cx_CR1 register.
i2c->instance.Instance->CR1 &= ~0x8000;
asm("nop");
// 15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register
i2c->instance.Instance->CR1 |= 0x0001;
// Call initialization function.
HAL_I2C_Init(&(i2c->instance));
}
Best Answer
If you do not want to use the STM32CubeMX code generator tool but still need simple example projects then you should use the STM32Cubexx firmware examples that are available for all STM32 series.
STM32CubeF4
STM32CubeF3
STM32CubeF2
STM32CubeF1
STM32CubeF0
STM32CubeL4
STM32CubeL1
STM32CubeL0
Each link has an application note called "STM32Cube firmware examples for STM32xx Series" (example for F4) which is actually a huge table listing all the available examples for all the development boards.
Also there are the user manual for each series called " Description of STM32xxxx HAL drivers" (example for F4). Yes, this is the 900 - 1300 pages long document but you do not have to read through all of it, just open up the relevant part. There are a short step by step guide at the beginning of every chapter. In case of the GPIO Generic Driver:
Based on this you can look up the function descriptions as well in this document and if you really need an example then there are the already mentioned STM32Cubexx example packages and you did not have to use the STM32CubeMX tool at all.