Skip to content

Dev spi asynch l0l1 #3288

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Nov 29, 2016
Merged

Dev spi asynch l0l1 #3288

merged 6 commits into from
Nov 29, 2016

Conversation

LMESTM
Copy link
Contributor

@LMESTM LMESTM commented Nov 18, 2016

Up to now Aysnch API was not activated on L0 and L1 devices.
This is now done with this PR.

Activation required a few modifications to improve the IRQ handling performances as asynch API provides enhanced SPI throughput but also require high IRQ handling rate, and L0 / L1 are relatively slow MCUs.

Status

READY

The Asynch SPI trasnfers have been tested ok @ 100kHz, 450kHz and 1MHz, for all L0 and L1 boards.
Also non regression was run on NUCLEO_F411RE board.

This is a temporary update waiting for the next official release
This is a temporary update waiting for the next official release
Disable IRQ when transfer is finished.
Also clear pending IRQ after they have been disabled.
This commit contains a few optimizations to get a better performance
in SPI Asynch mode
@bridadan
Copy link
Contributor

/morph test

@mbed-bot
Copy link

Result: SUCCESS

Your command has finished executing! Here's what you wrote!

/morph test

Output

mbed Build Number: 1127

All builds and test passed!

@adbridge
Copy link
Contributor

@marhil01 Is Oulu ci still broken? If not can we kick this off again ?

@LMESTM
Copy link
Contributor Author

LMESTM commented Nov 29, 2016

@adbridge who is in action to review this PR ?

@adbridge
Copy link
Contributor

@LMESTM I'll take a look this morning

#if (USE_SPI_CRC != 0U)
if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
{
hspi->RxISR = SPI_RxISR_8BITCRC;
Copy link
Contributor

@adbridge adbridge Nov 29, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra space here after =

static void SPI_RxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi)
{
__IO uint16_t tmpreg = 0U;

Copy link
Contributor

@adbridge adbridge Nov 29, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't tmpreg just be set to hspi->Instance->DR immediately here? Or do you need to write 0 first ? If so, a comment saying why would be good here.


#if (USE_SPI_CRC != 0U)
/* Enable CRC Transmission */
if((hspi->RxXferCount == 1U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you checking a XferCount of 1 ? Can we comment it ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RxXferCount == 1 means that the last byte to receive will come next so this is the time to activate HW SPI_CR1_CRCNEXT. Reference Manual says
Communication starts and continues normally until the last data frame has to be sent or
received in the SPIx_DR register. Then CRCNEXT bit has to be set in the SPIx_CR1
register to indicate that the CRC frame transaction will follow after the transaction of the
currently processed data frame. The CRCNEXT bit must be set before the end of the last
data frame transaction.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

if(hspi->RxXferCount==0)
#if (USE_SPI_CRC != 0U)
/* Enable CRC Transmission */
if((hspi->RxXferCount == 1U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you checking a XferCount of 1 ? Can we comment it ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as previous comment, in a 16 bits this case.


if(hspi->RxXferCount == 0U)
{
#if (USE_SPI_CRC != 0U)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any particular reason for using a value for USE_SPI_CRC instead of just:
#ifdef USE_SPI_CRC ?

Copy link
Contributor Author

@LMESTM LMESTM Nov 29, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, no particular reason that I know of.
This is how this is defined in STM32 hal.

SPI_RxCloseIRQHandler(hspi);
if(Timeout != HAL_MAX_DELAY)
{
if((Timeout == 0U) || ((HAL_GetTick()-Tickstart) >= Timeout))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is HAL_GetTick() guaranteed to always be > Tickstart ? Can wrapping occur? What would be the impact ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll have to check with code author - is worth a check

/* Disable TXE, RXNE and ERR interrupts for the interrupt process */
__HAL_SPI_DISABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));

if((hspi->Init.Mode == SPI_MODE_MASTER)&&((hspi->Init.Direction == SPI_DIRECTION_1LINE)||(hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be easier to read if it were split across 2 lines?

return HAL_TIMEOUT;
}
return HAL_OK;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this function really necessary? could the functionality of SPI_CheckFlag_BSY() and SPI_WaitFlagStateUntilTimeout() not be combined as the only difference is the SET_BIT ?

static void SPI_CloseRxTx_ISR(SPI_HandleTypeDef *hspi)
{
uint32_t tickstart = 0U;
__IO uint32_t count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24 / 1000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you document what these values mean ? 24 and 1000 ?

if(hspi->State == HAL_SPI_STATE_BUSY_RX)
{
hspi->State = HAL_SPI_STATE_READY;
HAL_SPI_RxCpltCallback(hspi);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some indentation issues here?

else
{
hspi->State = HAL_SPI_STATE_READY;
HAL_SPI_TxRxCpltCallback(hspi);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some indentation issues here?

static void SPI_CloseTx_ISR(SPI_HandleTypeDef *hspi)
{
uint32_t tickstart = 0U;
__IO uint32_t count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24 / 1000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please comment on what the values 24 and 1000 mean

__IO uint32_t count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24 / 1000);

/* Init tickstart for timeout management*/
tickstart = HAL_GetTick();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar comment to previous one about whether tickstart could just be initialised with HAL_GetTick() ?

do
{
if(count-- == 0)
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any chance that count could enter this loop set to 0 ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might happen in rare cases if communication is broken, or HW clock is unintentionally stopped ... so the loop avoids getting stuck infinitely.

/**
* @}
*/

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this comment block here ?

/* Set the function for IT treatment */
if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )
{
hspi->TxISR = SPI_TxISR_16BIT;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation here is inconsistent with the rest of the function which uses 2 spaces

}
else
{
hspi->TxISR = SPI_TxISR_8BIT;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation here is inconsistent with the rest of the function which uses 2 spaces

/* Set the function for IT treatment */
if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )
{
hspi->RxISR = SPI_RxISR_16BIT;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation here is inconsistent with the rest of the function which uses 2 spaces

}
else
{
hspi->RxISR = SPI_RxISR_8BIT;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation here is inconsistent with the rest of the function which uses 2 spaces

/* Set the function for IT treatment */
if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )
{
hspi->RxISR = SPI_2linesRxISR_16BIT;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation here is inconsistent with the rest of the function/file which uses 2 spaces

static void SPI_2linesRxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi)
{
__IO uint8_t tmpreg = 0U;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can tmpreg not be initialised directly ?

__IO uint16_t tmpreg = 0U;

/* Read data register to flush CRC */
tmpreg = hspi->Instance->DR;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can tmpreg not be initialised directly ?

__IO uint8_t tmpreg = 0U;

/* Read data register to flush CRC */
tmpreg = *((__IO uint8_t*)&hspi->Instance->DR);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can tmpreg not be initialised directly ?

__IO uint16_t tmpreg = 0U;

/* Read data register to flush CRC */
tmpreg = hspi->Instance->DR;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can tmpreg not be initialised directly ?


#if (USE_SPI_CRC != 0U)
/* Enable CRC Transmission */
if((hspi->RxXferCount == 1U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you checking the Xfer count = 1 ? Could that be commented ?

if(Timeout != HAL_MAX_DELAY)
{
if((Timeout == 0U) || ((HAL_GetTick()-Tickstart) >= Timeout))
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is HAL_GetTick() guaranteed to be >= Timeout? What is the impact if it isn't ?

* @param Tickstart: tick start value
* @retval HAL status
*/
static HAL_StatusTypeDef SPI_CheckFlag_BSY(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to previous target comment about combining these functions ?

uint32_t tickstart = 0U;
__IO uint32_t count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24 / 1000);
/* Init tickstart for timeout managment*/
tickstart = HAL_GetTick();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can tickstart not be initialised directly ?

/* Wait until TXE flag is set */
do
{
if(count-- == 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is count guaranteed not to be able to be 0 on entry to this loop ?

@LMESTM
Copy link
Contributor Author

LMESTM commented Nov 29, 2016

@adbridge Hi Anna. thanks for reviewing. Nevertheless I'm a bit annoyed because the stm32l0xx_hal_spi.c and stm32l1xx_hal_spi.c are files from the STM32 SDK2 named Cube or hal. This is the standard SDK as delivered on st.com and we include it as it is and base our MBED development on it. Most of those files don't follow the MBED coding rules. I can try to answer some your comments, but I am not the author of those lines and would like to avoid modifying them as it would diverge from official files ... let me know your thoughts

{
if(hspi->State == HAL_SPI_STATE_BUSY_RX)
{
hspi->State = HAL_SPI_STATE_READY;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation mismatch

}
else
{
hspi->State = HAL_SPI_STATE_READY;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation mismatch

__IO uint32_t count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24 / 1000);

/* Init tickstart for timeout management*/
tickstart = HAL_GetTick();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can tickstart not be initialised directly?

/* Wait until TXE flag is set */
do
{
if(count-- == 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is count guaranteed not to be 0 on loop entry ?

@adbridge
Copy link
Contributor

@LMESTM I have made some review comments, if you could take a look please. Also could you post some test results that verify your changes ? Thanks

@LMESTM
Copy link
Contributor Author

LMESTM commented Nov 29, 2016

@adbridge
See my previous comments about the questions and comments. I 'm answering what I can though.

About tests results, it's not in a table format but here is the result as mentioned in the description :
The Asynch SPI trasnfers have been tested ok @ 100kHz, 450kHz and 1MHz, for all L0 and L1 boards.
Also non regression was run on NUCLEO_F411RE board.

@adbridge
Copy link
Contributor

Hi @LMESTM don't worry I wasn't reviewing against MBED guidelines, merely looking at consistencies within the changes to what was already there and areas where potential issues could lie. They are just comments and feedback, I didn't see anything that would necessarily block us from accepting.

@LMESTM
Copy link
Contributor Author

LMESTM commented Nov 29, 2016

@adbridge ok thanks for the feedback. I will share your comments with the team in charge of the driver so that they can take them into account - next STM32 HAL update should then include updates in line with your feedback. I have provided some answers where I could in the meantime (I have not answered styling issue).

@adbridge
Copy link
Contributor

Thanks @LMESTM looks good to go then

@0xc0170 0xc0170 merged commit a8ebfaa into ARMmbed:master Nov 29, 2016
aisair pushed a commit to aisair/mbed that referenced this pull request Apr 30, 2024
Ports for Upcoming Targets

3241: Add support for FRDM-KW41 ARMmbed/mbed-os#3241
3291: Adding mbed enabled Maker board with NINA-B1 and EVA-M8Q ARMmbed/mbed-os#3291

Fixes and Changes

3062: TARGET_STM :USB device FS  ARMmbed/mbed-os#3062
3213: STM32: Refactor us_ticker.c + hal_tick.c files ARMmbed/mbed-os#3213
3288: Dev spi asynch l0l1 ARMmbed/mbed-os#3288
3289: Bug fix of initial value of interrupt edge in "gpio_irq_init" function. ARMmbed/mbed-os#3289
3302: STM32F4 AnalogIn - Clear VBATE and TSVREFE bits before configuring ADC channels ARMmbed/mbed-os#3302
3320: STM32 - Add ADC_VREF label ARMmbed/mbed-os#3320
3321: no HSE available by default for NUCLEO_L432KC ARMmbed/mbed-os#3321
3352: ublox eva nina - fix line endings ARMmbed/mbed-os#3352
3322: DISCO_L053C8 doesn't support LSE ARMmbed/mbed-os#3322
3345: STM32 - Remove TIM_IT_UPDATE flag in HAL_Suspend/ResumeTick functions ARMmbed/mbed-os#3345
3309: [NUC472/M453] Fix CI failed tests ARMmbed/mbed-os#3309
3157: [Silicon Labs] Adding support for EFR32MG1 wireless SoC ARMmbed/mbed-os#3157
3301: I2C - correct return values for write functions (docs) - part 1 ARMmbed/mbed-os#3301
3303: Fix #2956 #2939 #2957 #2959 #2960: Add HAL_DeInit function in gpio_irq destructor ARMmbed/mbed-os#3303
3304: STM32L476: no HSE is present in NUCLEO and DISCO boards ARMmbed/mbed-os#3304
3318: Register map changes for RevG ARMmbed/mbed-os#3318
3317: NUCLEO_F429ZI has integrated LSE ARMmbed/mbed-os#3317
3312: K64F: SPI Asynch API implementation ARMmbed/mbed-os#3312
3324: Dev i2c common code ARMmbed/mbed-os#3324
3369: Add CAN2 missing pins for connector CN12 ARMmbed/mbed-os#3369
3377: STM32 NUCLEO-L152RE Update system core clock to 32MHz ARMmbed/mbed-os#3377
3378: K66F: Enable LWIP feature ARMmbed/mbed-os#3378
3382: [MAX32620] Fixing serial readable function. ARMmbed/mbed-os#3382
3399: NUCLEO_F103RB - Add SERIAL_FC feature ARMmbed/mbed-os#3399
3409: STM32L1 : map ST HAL assert into MBED assert ARMmbed/mbed-os#3409
3416: Renames i2c_api.c for STM32F1 targets to fix IAR exporter ARMmbed/mbed-os#3416
3348: Fix frequency function of CAN driver. ARMmbed/mbed-os#3348
3366: NUCLEO_F412ZG - Add new platform ARMmbed/mbed-os#3366
3379: STM32F0 : map ST HAL assert into MBED assert ARMmbed/mbed-os#3379
3393: ISR register never re-evaluated in HAL_DMA_PollForTransfer for STM32F4 ARMmbed/mbed-os#3393
3408: STM32F7 : map ST HAL assert into MBED assert ARMmbed/mbed-os#3408
3411: STM32L0 : map ST HAL assert into MBED assert ARMmbed/mbed-os#3411
3424: STM32F4 - FIX to add the update of hdma->State variable ARMmbed/mbed-os#3424
3427: Fix stm i2c slave ARMmbed/mbed-os#3427
3429: Fix stm i2c fix init ARMmbed/mbed-os#3429
3434: [NUC472/M453] Fix stuck in lp_ticker_init and other updates ARMmbed/mbed-os#3434
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants