#include "../../inc/main.h" #include "ad0x0_spi1.h" #include "ad0x0_spi_ext.h" #include "../admisc/ad0x0_timman.h" #include "stm32f1xx_hal_spi.h" #include /*не проебать SPE: SPI enable в ините врубаем это SPIX->CR2 |= (SPI_CR2_ERRIE); для экрана нужно включать DC не отдельной командой очереди, а чисто внутри передачи байта */ #define SPIX ((SPI_TypeDef *)SPI1_BASE) //#undef AD0X0_SPI1_DBG //#define AD0X0_SPI1_DBG #define AD0X0_USE_SPI1_PROCESS_THROUGH_XQUEUE //ADQS == AD0x0 Queue Spi #define ADQS_SPI_EV_DISABLE SPIX->CR2 &= ~(SPI_CR2_TXEIE|SPI_CR2_RXNEIE); /*Хотелось бы выключить нахер пилу, которая идет в прерывание SPI Для этого события нужно включать только для команд предачи и выключать при операциях с очередью*/ #define ADQS_SPI_EV_GETSTATE(LAST_STATE) LAST_STATE=SPIX->CR2 & (SPI_CR2_TXEIE|SPI_CR2_RXNEIE); #define ADQS_SPI_EV_SETSTATE(LAST_STATE) __disable_irq(); SPIX->CR2 &= ~(SPI_CR2_TXEIE|SPI_CR2_RXNEIE); SPIX->CR2 |= (LAST_STATE); __enable_irq(); #define ADQS_SPI_EV_ENABLE SPIX->CR2 |= (SPI_CR2_TXEIE|SPI_CR2_RXNEIE); #define ADQS_SPI_DISABLE SPIX->CR1&= ~SPI_CR1_SPE; #define ADQS_SPI_ENABLE SPIX->CR1|= SPI_CR1_SPE; SPI_HandleTypeDef *phspi1=NULL; __weak void ad0x0_spi1_err_cb(void); void ad0x0_spi1_process(uint8_t _from_isr); void ad0x0_spi1_err(void); void ad0x0_spi1_pop(void); uint8_t ad0x0_spi1_next(uint8_t _from_isr); void ad0x0_spi1_init_desc(void); volatile xQueueHandle xqspi1_01=NULL; struct ad0x0_spi_cmd_s ad0x0_spi1_fifo[AD0X0_SPI_FIFO_COUNT]; volatile struct ad0x0_spi_cmd_s *ad0x0_spi1_pcurhwi=0,*ad0x0_spi1_pcurswi=0; ad0x0_spi_desc_s ad0x0_spi1_desc; volatile uint32_t ad0x0_spi1_last_HAL_RES=0, ad0x0_spi1_DMAERR_count=0; volatile uint32_t ad0x0_spi1_wait_cycles=0,ad0x0_spi1_wait_cycles_push=0; GPIO_TypeDef *AD_SPI1_DC_GPIO_Port=NULL, *AD_SPI1_RES_GPIO_Port=NULL,*AD_SPI1_NSS_GPIO_Port=NULL; uint16_t AD_SPI1_DC_Pin=0, AD_SPI1_RES_Pin=0, AD_SPI1_NSS_Pin=0; #ifdef AD0X0_DAMN_DBG //volatile int16_t c_enter_process=0,c_enter_ext=0; #endif //вызывается из какого нить vTask..... void ad0x0_spi1_xqRecieveHandler(void){ struct ad0x0_spi_cmd_s *p=NULL; //Если в очереди нихера то выходим!!!!!!!!!!!!!!!!!!!!!!!!! xQueueReceive(xqspi1_01,&p,portMAX_DELAY); //if(xQueueReceive(xqspi1_01,&p,0)!=pdPASS)return; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! uint8_t ctype=p->ctype & 0x3f; switch(ctype){ case ADQS_DELAY_MS: osDelay(p->cbyte); ad0x0_spi1_next(false); break; #ifdef AD0X0_USE_SPI1_PROCESS_THROUGH_XQUEUE case ADQS_USE_EXT: ad0x0_spi1_next(false); break; case ADQS_TX_PBUF_DMA: case ADQS_TXRX_PBUF_DMA: case ADQS_TX_PBUF_DMA_EXT: case ADQS_TXRX_PBUF_DMA_EXT: ad0x0_spi1_next(false); break; #endif default: ad0x0_err(); } } static portFORCE_INLINE void xqSendProcess(uint8_t _from_isr){ char str[10]; static portBASE_TYPE xHigherPriorityTaskWoken; __enable_irq(); if(_from_isr){ xHigherPriorityTaskWoken=false; while(xQueueSendFromISR(xqspi1_01,(void*)&ad0x0_spi1_pcurhwi,&xHigherPriorityTaskWoken)!=pdTRUE){ __asm("nop"); } /*else if(res==errQUEUE_FULL){ sprintf(str,"%d",(int)res); ad0x0_spi1_err(); }*/ if( xHigherPriorityTaskWoken ) { /* Actual macro used here is port specific. */ portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); } }else{ BaseType_t res=xQueueSend(xqspi1_01,(void*)&ad0x0_spi1_pcurhwi,100); if(res==pdTRUE){ __asm("nop"); //taskYIELD(); }else if(res==errQUEUE_FULL){ sprintf(str,"%d",(int)res); ad0x0_spi1_err(); } } } void ad0x0_spi1_push(ADQS_t _ctype,uint8_t _cbyte){//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #ifdef AD0X0_SPI1_DBG ADDBG2_HIGH; #endif uint16_t ev_state; /* if(t>2){//ms if(ad0x0_spi1_pcurhwi->ctype==0x4B){ ad0x0_spi1_pop(); ad0x0_spi1_process(); } }*/ // while((I2CX->CR1 & I2C_CR1_STOP));//это единственный while, который НЕЗАМЕТНО срабатывает раз в час... while(!(ad0x0_spi1_pcurswi->ctype & ADQS_EMPTY)){ osDelay(1); } if(ad0x0_spi1_pcurswi->ctype & ADQS_EMPTY){ ADQS_SPI_EV_GETSTATE(ev_state); ADQS_SPI_EV_DISABLE; __disable_irq(); //taskENTER_CRITICAL(); ad0x0_spi1_pcurswi->ctype=_ctype; ad0x0_spi1_pcurswi->cbyte=_cbyte; ad0x0_spi1_pcurswi=ad0x0_spi1_pcurswi->pnext; //__enable_irq(); //taskEXIT_CRITICAL(); if((!(ad0x0_spi1_pcurhwi->ctype & ADQS_PROCESSED)) ){ ad0x0_spi1_process(false);// }else ADQS_SPI_EV_SETSTATE(ev_state); //ADQS_SPI_EV_ENABLE;//решить!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #ifdef AD0X0_SPI1_DBG ADDBG2_LOW; #endif return; } #ifdef AD0X0_SPI1_DBG ADDBG2_LOW; #endif } uint8_t ad0x0_spi1_next(uint8_t _from_isr){ ad0x0_spi1_pop(); if(!(ad0x0_spi1_pcurhwi->ctype & ADQS_EMPTY)){//(очередь не пустая) ad0x0_spi1_process(_from_isr); } return 1; } void ad0x0_spi1_pop(){//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! int was_masked=__disable_irq(); if(!(ad0x0_spi1_pcurhwi->ctype & ADQS_PROCESSED)){ //попытка выкинуть необработанный элемент if(!was_masked)__enable_irq(); ad0x0_spi1_err(); } switch(ad0x0_spi1_pcurhwi->ctype & 0x3f){ case ADQS_USE_EXT: //case ADQS_TX_PBUF_DMA: //case ADQS_TXRX_PBUF_DMA: case ADQS_TX_PBUF_DMA_EXT: case ADQS_TXRX_PBUF_DMA_EXT: if(!(ad0x0_spi1_pcurhwi->cbyte & 0x80)){ ad0x0_spi_ext_post_process(&ad0x0_spi1_desc,ad0x0_spi1_pcurhwi->cbyte); ad0x0_spi1_pcurhwi->cbyte|=0x80; } break; } __disable_irq(); ad0x0_spi1_pcurhwi->ctype|=0x80;//метим как выкинутую ad0x0_spi1_pcurhwi=ad0x0_spi1_pcurhwi->pnext; if(!was_masked)__enable_irq(); } //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! void ad0x0_spi1_process(uint8_t _from_isr){ int was_masked=__disable_irq(); //тут мы шото меняем какие то флаги, а затем ждем прерывания для текущей команды ADS2_HIGH; /*возможна ситуация, когда в push уже вызвали ad0x0_spi1_process для необработанной команды... очевидно, 2й раз этого делать не надо ПРОВЕРИТЬ*/ if(ad0x0_spi1_pcurhwi->ctype & (ADQS_EMPTY|ADQS_PROCESSED)){//(очередь не пустая) //ad0x0_err(); __enable_irq(); ADS2_LOW; return; } //если тип не впишится в свитч, то комнда либо отброшена, либо обработана ранее switch(ad0x0_spi1_pcurhwi->ctype){ case ADQS_TX: //I2CX->CR1 |= I2C_CR1_ACK; if(ad0x0_spi1_pcurhwi->cbyte==0x1b){ __asm("nop"); } ad0x0_spi1_pcurhwi->ctype|=ADQS_PROCESSED;//метим как обработанную SPIX->DR = ad0x0_spi1_pcurhwi->cbyte; __enable_irq(); ADQS_SPI_EV_ENABLE; break; case ADQS_TX_PBUF: if(AD_SPI1_NSS_GPIO_Port)HAL_GPIO_WritePin(AD_SPI1_NSS_GPIO_Port,AD_SPI1_NSS_Pin,GPIO_PIN_RESET); ad0x0_spi1_desc.pbuf_counter_cur=ad0x0_spi1_desc.pbuf_counter; ad0x0_spi1_desc.tx_pbuf_cur=ad0x0_spi1_desc.tx_pbuf; ad0x0_spi1_desc.rx_pbuf_cur=0; //ad0x0_spi1_desc.pbuf_counter=ad0x0_spi1_pcurhwi->cbyte; SPIX->DR = *ad0x0_spi1_desc.tx_pbuf_cur++; ad0x0_spi1_desc.pbuf_counter_cur--; ad0x0_spi1_pcurhwi->ctype|=ADQS_PROCESSED;//метим как обработанную __enable_irq(); ADQS_SPI_EV_ENABLE; break; case ADQS_TX_PBUF_EXT: ad0x0_spi1_pcurhwi->ctype|=ADQS_PROCESSED;//метим как обработанную __enable_irq(); if(AD_SPI1_NSS_GPIO_Port)HAL_GPIO_WritePin(AD_SPI1_NSS_GPIO_Port,AD_SPI1_NSS_Pin,GPIO_PIN_RESET); //ext - ф-я дма, в случае перезапуска не выполняется, т.к. буферы уже назначены if(!(ad0x0_spi1_pcurhwi->cbyte & 0x80)){ ad0x0_spi_ext_pre_process(&ad0x0_spi1_desc,ad0x0_spi1_pcurhwi->cbyte); } ad0x0_spi1_desc.pbuf_counter_cur=ad0x0_spi1_desc.pbuf_counter; ad0x0_spi1_desc.tx_pbuf_cur=ad0x0_spi1_desc.tx_pbuf; ad0x0_spi1_desc.rx_pbuf_cur=0; //ad0x0_spi1_desc.pbuf_counter=ad0x0_spi1_pcurhwi->cbyte; SPIX->DR = *ad0x0_spi1_desc.tx_pbuf_cur++; ad0x0_spi1_desc.pbuf_counter_cur--; ADQS_SPI_EV_ENABLE; break; case ADQS_TX_PBUF_DMA: //ad0x0_spi1_desc.pbuf_counter=ad0x0_spi1_pcurhwi->cbyte;//все через EXT ad0x0_spi1_pcurhwi->ctype|=ADQS_PROCESSED;//метим как обработанную ADQS_SPI_EV_DISABLE; if(AD_SPI1_NSS_GPIO_Port)HAL_GPIO_WritePin(AD_SPI1_NSS_GPIO_Port,AD_SPI1_NSS_Pin,GPIO_PIN_RESET); if((!ad0x0_spi1_desc.pbuf_counter) || (!ad0x0_spi1_desc.tx_pbuf) )ad0x0_spi1_err(); __enable_irq(); ad0x0_spi1_last_HAL_RES=HAL_SPI_Transmit_DMA(phspi1,(uint8_t*)ad0x0_spi1_desc.tx_pbuf,ad0x0_spi1_desc.pbuf_counter); //for (uint32_t i=0;i<1000000;i++) if(HAL_OK != ad0x0_spi1_last_HAL_RES){ ad0x0_spi1_pcurhwi->ctype&=~ADQS_PROCESSED;//финт ушами, ad0x0_spi1_DMAERR_count++; ADQS_SPI_EV_ENABLE; }else break; if(HAL_OK != ad0x0_spi1_last_HAL_RES)ad0x0_spi1_err(); break; case ADQS_TX_PBUF_DMA_EXT: //ad0x0_spi1_desc.pbuf_counter=ad0x0_spi1_pcurhwi->cbyte;//все через EXT ad0x0_spi1_pcurhwi->ctype|=ADQS_PROCESSED;//метим как обработанную __enable_irq(); if(!(ad0x0_spi1_pcurhwi->cbyte & 0x80)){ ad0x0_spi_ext_pre_process(&ad0x0_spi1_desc,ad0x0_spi1_pcurhwi->cbyte); } ADQS_SPI_EV_DISABLE; if(AD_SPI1_NSS_GPIO_Port)HAL_GPIO_WritePin(AD_SPI1_NSS_GPIO_Port,AD_SPI1_NSS_Pin,GPIO_PIN_RESET); if((!ad0x0_spi1_desc.pbuf_counter) || (!ad0x0_spi1_desc.tx_pbuf) )ad0x0_spi1_err(); ad0x0_spi1_last_HAL_RES=HAL_SPI_Transmit_DMA(phspi1,(uint8_t*)ad0x0_spi1_desc.tx_pbuf,ad0x0_spi1_desc.pbuf_counter); //for (uint32_t i=0;i<1000000;i++) if(HAL_OK != ad0x0_spi1_last_HAL_RES){ ad0x0_spi1_pcurhwi->ctype&=~ADQS_PROCESSED;//финт ушами, ad0x0_spi1_DMAERR_count++; ADQS_SPI_EV_ENABLE; }else break; if(HAL_OK != ad0x0_spi1_last_HAL_RES)ad0x0_spi1_err(); break; case ADQS_TXRX_PBUF_DMA: //тут дуализм сраный. сейчас байт данных не должен ни за что отвечать if(ad0x0_spi1_pcurhwi->cbyte)ad0x0_spi1_desc.pbuf_counter=ad0x0_spi1_pcurhwi->cbyte; ad0x0_spi1_pcurhwi->ctype|=ADQS_PROCESSED;//метим как обработанную __enable_irq(); ADQS_SPI_EV_DISABLE; if(AD_SPI1_NSS_GPIO_Port)HAL_GPIO_WritePin(AD_SPI1_NSS_GPIO_Port,AD_SPI1_NSS_Pin,GPIO_PIN_RESET); if((!ad0x0_spi1_desc.pbuf_counter) || (!ad0x0_spi1_desc.tx_pbuf) || (!ad0x0_spi1_desc.rx_pbuf) )ad0x0_spi1_err(); ad0x0_spi1_last_HAL_RES=HAL_SPI_TransmitReceive_DMA(phspi1,(uint8_t*)ad0x0_spi1_desc.tx_pbuf,(uint8_t*)ad0x0_spi1_desc.rx_pbuf,ad0x0_spi1_desc.pbuf_counter); //for (uint32_t i=0;i<1000000;i++) if(HAL_OK != ad0x0_spi1_last_HAL_RES){ ad0x0_spi1_pcurhwi->ctype&=~ADQS_PROCESSED;//финт ушами, ad0x0_spi1_DMAERR_count++; ADQS_SPI_EV_ENABLE; //NVIC_SetPendingIRQ(SPI1_IRQn);//ПЕРЕСМОТРЕТЬ } //if(ad0x0_spi1_DMAERR_count>100)ad0x0_spi1_err();//ПЕРЕСМОТРЕТЬ break; case ADQS_TXRX_PBUF_DMA_EXT: //тут дуализм сраный. сейчас байт данных не должен ни за что отвечать if(ad0x0_spi1_pcurhwi->cbyte)ad0x0_spi1_desc.pbuf_counter=ad0x0_spi1_pcurhwi->cbyte; ad0x0_spi1_pcurhwi->ctype|=ADQS_PROCESSED;//метим как обработанную __enable_irq(); //ext - ф-я дма, в случае перезапуска не выполняется, т.к. буферы уже назначены if(!(ad0x0_spi1_pcurhwi->cbyte & 0x80)){ ad0x0_spi_ext_pre_process(&ad0x0_spi1_desc,ad0x0_spi1_pcurhwi->cbyte); } ADQS_SPI_EV_DISABLE; if(AD_SPI1_NSS_GPIO_Port)HAL_GPIO_WritePin(AD_SPI1_NSS_GPIO_Port,AD_SPI1_NSS_Pin,GPIO_PIN_RESET); if((!ad0x0_spi1_desc.pbuf_counter) || (!ad0x0_spi1_desc.tx_pbuf) || (!ad0x0_spi1_desc.rx_pbuf) )ad0x0_spi1_err(); ad0x0_spi1_last_HAL_RES=HAL_SPI_TransmitReceive_DMA(phspi1,(uint8_t*)ad0x0_spi1_desc.tx_pbuf,(uint8_t*)ad0x0_spi1_desc.rx_pbuf,ad0x0_spi1_desc.pbuf_counter); //for (uint32_t i=0;i<1000000;i++) if(HAL_OK != ad0x0_spi1_last_HAL_RES){ ad0x0_spi1_pcurhwi->ctype&=~ADQS_PROCESSED;//финт ушами, ad0x0_spi1_DMAERR_count++; ADQS_SPI_EV_ENABLE; //NVIC_SetPendingIRQ(SPI1_IRQn);//ПЕРЕСМОТРЕТЬ } //if(ad0x0_spi1_DMAERR_count>100)ad0x0_spi1_err();//ПЕРЕСМОТРЕТЬ break; case ADQS_USE_EXT: if(ad0x0_spi1_pcurhwi->ctype & ADQS_PROCESSED){__enable_irq();ad0x0_spi1_err();} else{ ad0x0_spi1_pcurhwi->ctype|=ADQS_PROCESSED;//метим как обработанную ADQS_SPI_EV_ENABLE;//иначе очередь может остановиться и не просраться // ad0x0_spi1_pcurhwi->cbyte __enable_irq(); uint8_t cb=ad0x0_spi1_pcurhwi->cbyte; ad0x0_spi1_pcurhwi->cbyte|=0x80; ad0x0_spi_ext_pre_process(&ad0x0_spi1_desc,cb); ad0x0_spi_ext_post_process(&ad0x0_spi1_desc,cb); #ifdef AD0X0_USE_SPI1_PROCESS_THROUGH_XQUEUE xqSendProcess(_from_isr); #else ad0x0_spi1_next(_from_isr);//если здесь накидывается куча команд, то стэк это.. того... #endif //v2 /*ad0x0_spi1_pop(); ADQS_SPI_EV_ENABLE; NVIC_SetPendingIRQ(SPI1_IRQn);*/ //v3 /*ad0x0_spi1_pop(); if(!(ad0x0_spi1_pcurhwi->ctype & ADQS_EMPTY)){//(очередь не пустая) ad0x0_spi1_process(); }*/ } //__enable_irq(); break; case ADQS_DELAY_MS: ad0x0_spi1_pcurhwi->ctype|=ADQS_PROCESSED;//метим как обработанную __enable_irq(); #ifdef INC_FREERTOS_H //osDelay(ad0x0_i2c1_pcurhwi->cbyte); //задача, в которую это придет, затормозится на скока надо и вызовет поп и процесс xqSendProcess(_from_isr); #else ad0x0_timman_add(ad0x0_spi1_pcurhwi->cbyte,ad0x0_spi1_next); #endif break; case ADQS_ST7735_SET_DC: ad0x0_spi1_pcurhwi->ctype|=ADQS_PROCESSED;//метим как обработанную //если состояние пина не изменится, то выкидываем команду из очереди __enable_irq(); while(SPIX->SR & SPI_SR_BSY); if(ad0x0_spi1_pcurhwi->pnext->cbyte==0xC0){ __asm("nop"); } if(AD_SPI1_DC_GPIO_Port)HAL_GPIO_WritePin( AD_SPI1_DC_GPIO_Port,AD_SPI1_DC_Pin,ad0x0_spi1_pcurhwi->cbyte ? GPIO_PIN_SET : GPIO_PIN_RESET); ad0x0_spi1_next(_from_isr); break; case ADQS_ST7735_SET_CS: ad0x0_spi1_pcurhwi->ctype|=ADQS_PROCESSED;//метим как обработанную __enable_irq(); if(ad0x0_spi1_pcurhwi->cbyte){ SPIX->CR1|= SPI_CR1_SSI; SPIX->CR1&=~SPI_CR1_SSM;//0: Software slave management disabled }else{ SPIX->CR1&= ~SPI_CR1_SSI; SPIX->CR1|=SPI_CR1_SSM;//1: Software slave management enabled } ad0x0_spi1_next(_from_isr); break; case ADQS_ST7735_SET_RESET: if(AD_SPI1_RES_GPIO_Port)HAL_GPIO_WritePin( AD_SPI1_RES_GPIO_Port,AD_SPI1_RES_Pin,ad0x0_spi1_pcurhwi->cbyte ? GPIO_PIN_SET : GPIO_PIN_RESET); //HAL_GPIO_WritePin( AD_RES_GPIO_Port,AD_RES_Pin,ad0x0_spi1_pcurhwi->cbyte ? GPIO_PIN_SET : GPIO_PIN_RESET); ad0x0_spi1_pcurhwi->ctype|=ADQS_PROCESSED;//метим как обработанную __enable_irq(); ad0x0_spi1_next(_from_isr); break; default: ad0x0_spi1_err(); } //c_enter_process--; ADS2_LOW; } void ad0x0_spi1_irq_err(void){ //я бы это не обрабатывал, если бы не пидорский гироскоп, который не прислал нак при адресе... //метим команду как необработанную и пробуем по новой uint8_t ctypex=ad0x0_spi1_pcurhwi->ctype; uint32_t sr=0; sr=SPIX->SR;// ad0x0_spi1_err(); switch(ctypex & 0x3f){ case ADQS_TX_PBUF_DMA: if(sr & SPI_SR_OVR){ /*When the SPI is used only to transmit data, it is possible to enable only the SPI Tx DMA channel. In this case, the OVR flag is set because the data received are not read*/ __ASM("nop"); } break; default: ad0x0_spi1_err(); } } void ad0x0_spi1_dma_err(void){ //всякая херня случается, и... приводит как всегда к ad0x0_spi1_err(); uint8_t ctypex=ad0x0_spi1_pcurhwi->ctype; ad0x0_spi1_err(); } void ad0x0_spi1_dma(void){ ADS1_HIGH; #ifdef AD0X0_USE_SPI1_PROCESS_THROUGH_XQUEUE uint8_t ctype=ad0x0_spi1_pcurhwi->ctype & 0x3f; switch(ctype){ case ADQS_TX_PBUF_DMA: case ADQS_TXRX_PBUF_DMA: case ADQS_TX_PBUF_DMA_EXT: case ADQS_TXRX_PBUF_DMA_EXT: if(AD_SPI1_NSS_GPIO_Port)HAL_GPIO_WritePin(AD_SPI1_NSS_GPIO_Port,AD_SPI1_NSS_Pin,GPIO_PIN_SET); break; default: ad0x0_err(); } //if(ad0x0_spi1_pcurhwi->pnext->ctype == ADQS_USE_EXT ){ if(1){ xqSendProcess(true);//так правильно, но медленно }else{ ad0x0_spi1_pop(); NVIC_SetPendingIRQ(SPI1_IRQn); } #else uint8_t ctypex=ad0x0_spi1_pcurhwi->ctype; switch(ctypex & 0x3f){ case ADQS_TX_PBUF_DMA: if(AD_SPI1_NSS_GPIO_Port)HAL_GPIO_WritePin(AD_SPI1_NSS_GPIO_Port,AD_SPI1_NSS_Pin,GPIO_PIN_SET); ad0x0_spi1_next(true); break; case ADQS_TXRX_PBUF_DMA: if(AD_SPI1_NSS_GPIO_Port)HAL_GPIO_WritePin(AD_SPI1_NSS_GPIO_Port,AD_SPI1_NSS_Pin,GPIO_PIN_SET); //v2 почему так? потому что начинает сыпаться ф-я хал с дма-передачей ad0x0_spi1_pop(); NVIC_SetPendingIRQ(SPI1_IRQn); break; case ADQS_TX_PBUF_DMA_EXT: if(AD_SPI1_NSS_GPIO_Port)HAL_GPIO_WritePin(AD_SPI1_NSS_GPIO_Port,AD_SPI1_NSS_Pin,GPIO_PIN_SET); if(!(ad0x0_spi1_pcurhwi->cbyte & 0x80)){ ad0x0_spi_ext_post_process(&ad0x0_spi1_desc,ad0x0_spi1_pcurhwi->cbyte); ad0x0_spi1_pcurhwi->cbyte|=0x80; } //ad0x0_spi1_next(); //v2 почему так? потому что начинает сыпаться ф-я хал с дма-передачей ad0x0_spi1_pop(); NVIC_SetPendingIRQ(SPI1_IRQn); break; case ADQS_TXRX_PBUF_DMA_EXT: if(AD_SPI1_NSS_GPIO_Port)HAL_GPIO_WritePin(AD_SPI1_NSS_GPIO_Port,AD_SPI1_NSS_Pin,GPIO_PIN_SET); if(!(ad0x0_spi1_pcurhwi->cbyte & 0x80)){ ad0x0_spi_ext_post_process(&ad0x0_spi1_desc,ad0x0_spi1_pcurhwi->cbyte); ad0x0_spi1_pcurhwi->cbyte|=0x80; } ad0x0_spi1_pop(); NVIC_SetPendingIRQ(SPI1_IRQn); break; default: //}else{ ad0x0_spi1_err(); } #endif ADS1_LOW; } void ad0x0_spi1_irq(void) { /* In order to detect unexpected events during development, it is recommended to set a breakpoint on the following instruction. */ ad0x0_spi1_desc.insint=1; ADS1_HIGH; /* для и2ц было так: когда генерится стоп, игнорим прерывания, для spi так не делаем if(I2CX->CR1 & I2C_CR1_STOP){ #ifdef AD0X0_SPI1_DBG ADINT_LOW; #endif ad0x0_spi1_insint=0; return; }*/ /**/ uint32_t sr=SPIX->SR;// /*if(sr & SPI_SR_RXNE){ uint8_t data=SPIX->DR; sr=SPIX->SR; }*/ uint8_t ctypex=ad0x0_spi1_pcurhwi->ctype; if(!(ctypex & ADQS_PROCESSED)){//эл-т для которого не делался process if(!(ad0x0_spi1_pcurhwi->ctype & ADQS_EMPTY)){//(очередь не пустая) ad0x0_spi1_process(true); ADS1_LOW; ad0x0_spi1_desc.insint=0; return; }else ADQS_SPI_EV_DISABLE; } if(ctypex & ADQS_EMPTY){//уже обработанный эл-т...== пустая очередь ADS1_LOW; ADQS_SPI_EV_DISABLE; //ADQS_SPI_DISABLE; ad0x0_spi1_desc.insint=0; return; } switch(ctypex & 0x3f){ case ADQS_TX: if(sr & SPI_SR_TXE){ /* так не сработает, т.к. прерывание приходит пока байт передается, Зато работает с ДМА!!! #ifdef SPI1_NSS_GPIO_Port HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port,SPI1_NSS_Pin,GPIO_PIN_SET); #endif*/ ad0x0_spi1_next(true); } if(sr & SPI_SR_RXNE){//ad0x0 09102020 проверить uint8_t d=SPIX->DR; } ADQS_SPI_EV_DISABLE; break; case ADQS_TX_PBUF: if(sr & SPI_SR_TXE) { if(ad0x0_spi1_desc.pbuf_counter_cur){ __disable_irq(); SPIX->DR = *ad0x0_spi1_desc.tx_pbuf_cur++; ad0x0_spi1_desc.pbuf_counter_cur--; __enable_irq(); }else{ ADQS_SPI_EV_DISABLE; ad0x0_spi1_next(true); } } if(sr & SPI_SR_RXNE){//ad0x0 09102020 проверить uint8_t d=SPIX->DR; } //ADQS_SPI_EV_DISABLE; break; case ADQS_TX_PBUF_EXT: if(sr & SPI_SR_TXE) { if(ad0x0_spi1_desc.pbuf_counter_cur){ __disable_irq(); SPIX->DR = *ad0x0_spi1_desc.tx_pbuf_cur++; ad0x0_spi1_desc.pbuf_counter_cur--; __enable_irq(); }else{ ADQS_SPI_EV_DISABLE; if(!(ad0x0_spi1_pcurhwi->cbyte & 0x80)){ ad0x0_spi_ext_post_process(&ad0x0_spi1_desc,ad0x0_spi1_pcurhwi->cbyte); ad0x0_spi1_pcurhwi->cbyte|=0x80; } ad0x0_spi1_next(true); } } if(sr & SPI_SR_RXNE){//ad0x0 09102020 проверить uint8_t d=SPIX->DR; } //ADQS_SPI_EV_DISABLE; break; case ADQS_TXRX_PBUF_DMA: case ADQS_TX_PBUF_DMA: case ADQS_TX_PBUF_DMA_EXT: case ADQS_TXRX_PBUF_DMA_EXT: if(sr & SPI_SR_RXNE){//ad0x0 09102020 проверить uint8_t d=SPIX->DR; } ADQS_SPI_EV_DISABLE; break; case ADQS_DELAY_MS: ADQS_SPI_EV_DISABLE; break; case ADQS_ST7735_SET_DC: ADQS_SPI_EV_DISABLE; break; case ADQS_USE_EXT: ADQS_SPI_EV_DISABLE; break; default: //}else{ ad0x0_spi1_err(); } ad0x0_spi1_desc.insint=0; ADS1_LOW; } void ad0x0_spi1_initq(void){ ad0x0_spi1_pcurhwi=ad0x0_spi1_pcurswi=ad0x0_spi1_fifo; ad0x0_spi1_fifo[AD0X0_SPI_FIFO_COUNT-1].pnext=ad0x0_spi1_fifo; ad0x0_spi1_fifo[AD0X0_SPI_FIFO_COUNT-1].ctype=ADQS_EMPTY; for(uint16_t i=0;i<=AD0X0_SPI_FIFO_COUNT-2;i++){ ad0x0_spi1_fifo[i].pnext=ad0x0_spi1_fifo+i+1; ad0x0_spi1_fifo[i].ctype=ADQS_EMPTY; } // HAL_SPI_R } void ad0x0_spi1_err(void){ ad0x0_err(); } uint8_t ad0x0_spi1_is_queue_empty(void){ return ((ad0x0_spi1_pcurhwi->ctype & ADQS_EMPTY) && (ad0x0_spi1_pcurhwi->pnext->ctype & ADQS_EMPTY) && !(SPIX->SR & SPI_SR_BSY)); } void ad0x0_spi1_wait(void){ uint16_t ev_state; ADQS_SPI_EV_GETSTATE(ev_state); while(!ad0x0_spi1_is_queue_empty()){ osDelay(1); ADQS_SPI_EV_ENABLE; }//!!!!!!!!!!ubrat' etot pizdets ADQS_SPI_EV_SETSTATE(ev_state); } void ad0x0_spi1_init(SPI_HandleTypeDef *_phspi1,GPIO_TypeDef *_LCD_DC_GPIO_Port,uint16_t _LCD_DC_Pin, GPIO_TypeDef *_LCD_RES_GPIO_Port,uint16_t _LCD_RES_Pin, GPIO_TypeDef *_NSS_GPIO_Port,uint16_t _NSS_Pin) { phspi1=_phspi1; AD_SPI1_DC_GPIO_Port=_LCD_DC_GPIO_Port; AD_SPI1_DC_Pin=_LCD_DC_Pin; AD_SPI1_RES_GPIO_Port=_LCD_RES_GPIO_Port; AD_SPI1_RES_Pin=_LCD_RES_Pin; AD_SPI1_NSS_GPIO_Port=_NSS_GPIO_Port; AD_SPI1_NSS_Pin=_NSS_Pin; if(AD_SPI1_NSS_GPIO_Port){ SPIX->CR1|= SPI_CR1_SSM;//1: Software slave management enabled SPIX->CR1|= SPI_CR1_SSI;//The value of this bit is forced onto the NSS pin and the IO value of the NSS pin is ignored }else{ SPIX->CR1&= ~SPI_CR1_SSM;// SPIX->CR1&= ~SPI_CR1_SSI;// } SPIX->CR2 |= (SPI_CR2_ERRIE); SPIX->CR1|=SPI_CR1_SPE; xqspi1_01 = xQueueCreate(1,sizeof(struct ad0x0_spi_cmd_s *)); if(!xqspi1_01)ad0x0_err(); ad0x0_spi1_initq(); ad0x0_spi1_init_desc(); //pins configuing in cubemx...main.c } void ad0x0_spi1_init_desc(void){ memset(&ad0x0_spi1_desc,0,sizeof(ad0x0_spi1_desc)); ad0x0_spi1_desc.spix=SPIX; ad0x0_spi1_desc.perrfunc=ad0x0_spi1_err; } uint8_t ad0x0_spi1_get_ext_async(uint8_t *_p_out_handle,ad0x0_spi_ext_t **_p_out_desc){ while( !ad0x0_spi_ext_get(_p_out_handle, _p_out_desc) ){ __enable_irq(); ad0x0_spi1_wait_cycles++; ADQS_SPI_EV_ENABLE; osDelay(1); } return 1; } uint8_t ad0x0_spi1_get_ext_async2(uint8_t *_p_out_handle,void **_p_out_spi_ext_t){ return ad0x0_spi1_get_ext_async(_p_out_handle, (ad0x0_spi_ext_t**)_p_out_spi_ext_t); } uint8_t ad0x0_spi1_get_ext_setbuf(uint8_t *_tx_pbuf,uint8_t *_rx_pbuf, uint8_t _count){ //c_enter_ext++; uint8_t i; ad0x0_spi_ext_t *pf; ad0x0_spi1_get_ext_async(&i,&pf); // if(pf->pSetTXRXBuf ||pf->_p_cb_func|| pf->calls_count)ad0x0_spi1_err();//УБРАТЬ pf->pbuf_tx=_tx_pbuf; pf->pbuf_rx=_rx_pbuf; pf->pbuf_count=_count; pf->spi=SPIX; pf->p_pre_SetTXRXBuf=EXT_SetTXRXBuf;//ну я хз, пока делаем так... ПЕРЕДЕЛАТЬ!!!!!! return i; //ad0x0_spi1_push(ADQS_USE_EXT,i); //c_enter_ext--; } void ad0x0_spi1_push_txrx_dma_ext(uint8_t *_tx_pbuf,uint8_t *_rx_pbuf, uint8_t _count){ //c_enter_ext++; ad0x0_spi1_push(ADQS_TXRX_PBUF_DMA_EXT,ad0x0_spi1_get_ext_setbuf(_tx_pbuf,_rx_pbuf,_count)); //c_enter_ext--; } void ad0x0_spi1_push_tx_pbuf_ext(uint8_t *_tx_pbuf,uint8_t *_rx_pbuf, uint8_t _count){ //c_enter_ext++; ad0x0_spi1_push(ADQS_TX_PBUF_EXT,ad0x0_spi1_get_ext_setbuf(_tx_pbuf,_rx_pbuf,_count)); //c_enter_ext--; } void ad0x0_spi1_push_tx_pbuf_dma_ext(uint8_t *_tx_pbuf,uint8_t *_rx_pbuf, uint8_t _count){ //c_enter_ext++; ad0x0_spi1_push(ADQS_TX_PBUF_DMA_EXT,ad0x0_spi1_get_ext_setbuf(_tx_pbuf,_rx_pbuf,_count)); //c_enter_ext--; } void ad0x0_spi1_push_ext_setfunc(uint8_t _sf_id,void (*_p_cb_func)(uint8_t _sf_id,ad0x0_spi_desc_s *pdspi,void *p_spi_ext_t)){ //c_enter_ext++; uint8_t i; ad0x0_spi_ext_t *pf; ad0x0_spi1_get_ext_async(&i,&pf); pf->sf_id=_sf_id; pf->_p_post_cb_func=_p_cb_func;//ну я хз, пока делаем так... ПЕРЕДЕЛАТЬ!!!!!! pf->spi=SPIX; ad0x0_spi1_push(ADQS_USE_EXT,i); //c_enter_ext--; }