static void s_hal_spi_periph_dma_disable(hal_spi_t id) { SPI_TypeDef* SPIx = HAL_spi_id2stmSPI(id); SPI_Cmd(SPIx, DISABLE); hal_dma_disable(s_hal_spi_dma_port2use_rx[HAL_spi_id2index(id)]); hal_dma_disable(s_hal_spi_dma_port2use_tx[HAL_spi_id2index(id)]); s_hal_spi_set_dma_enabled(id, hal_false); }
static hal_result_t s_hal_spi_get(hal_spi_t id, uint8_t* rxframe, uint8_t* remainingrxframes) { hal_spi_internal_item_t* intitem = s_hal_spi_theinternals.items[HAL_spi_id2index(id)]; #if 1 return(hal_utility_fifo_get(&intitem->fiforx, rxframe, remainingrxframes)); #else hal_result_t res = hal_res_NOK_generic; hal_spi_cfg_t* cfg = &intitem->config; if(hal_spi_act_framebased != cfg->activity) { return(hal_res_NOK_generic); } hal_bool_t isrisenabled = s_hal_spi_is_isr_enabled(id); if(hal_true == isrisenabled) { s_hal_spi_rx_isr_disable(id); } res = hal_utility_fifo_get(&intitem->fiforx, rxframe, remainingrxframes); if(hal_true == isrisenabled) { s_hal_spi_rx_isr_enable(id); } return(res); #endif }
static void s_hal_spi_hw_init(hal_spi_t id) { #if defined(HAL_USE_CPU_FAM_STM32F1) || defined(HAL_USE_CPU_FAM_STM32F4) //uint32_t RCC_APB1Periph_SPIx = (hal_spi1 == id) ? (RCC_APB1Periph_SPI1) : (RCC_APB1Periph_SPI2); RCC_APB1Periph_SPI3 if(hal_spi1 == id) { // spi periph clock enable RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); // the reset and exit from reset is also done by SPI_I2S_DeInit() ..... thus it can be removed from here // reset spi periph RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, ENABLE); // release reset RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, DISABLE); } else { uint32_t RCC_APB1Periph_SPIx = s_hal_spi_hw_rcc[HAL_spi_id2index(id)]; // spi periph clock enable RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPIx, ENABLE); // the reset and exit from reset is also done by SPI_I2S_DeInit() ..... thus it can be removed from here // reset spi periph RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPIx, ENABLE); // release reset RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPIx, DISABLE); } // // // system configuration controller clock // #warning --> in stm32f4 removed "RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);" from spi_hw_init() and it still works.... // // RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); // // // spi periph clock enable // RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPIx, ENABLE); // // // reset spi periph // RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPIx, ENABLE); // // // release reset // RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPIx, DISABLE); #else //defined(HAL_USE_CPU_FAM_*) #error ERR --> choose a HAL_USE_CPU_FAM_* #endif }
extern hal_result_t hal_spi_on_framereceiv_set(hal_spi_t id, hal_callback_t onframereceiv, void* arg) { hal_spi_internal_item_t* intitem = s_hal_spi_theinternals.items[HAL_spi_id2index(id)]; if(hal_false == hal_spi_hid_initted_is(id)) { return(hal_res_NOK_generic); } intitem->config.onframereceiv = onframereceiv; intitem->config.argonframereceiv = arg; return(hal_res_OK); }
static void s_hal_spi_read_isr(hal_spi_t id) { hal_spi_internal_item_t* intitem = s_hal_spi_theinternals.items[HAL_spi_id2index(id)]; SPI_TypeDef* SPIx = HAL_spi_id2stmSPI(id); uint8_t rxbyte = SPI_I2S_ReceiveData(SPIx); if(intitem->isrrxcounter < intitem->config.sizeofframe) { intitem->isrrxframe[intitem->isrrxcounter] = rxbyte; intitem->isrrxcounter ++; } if(intitem->isrrxcounter == intitem->config.sizeofframe) { // ok. the frame is finished // 1. stop spi s_hal_spi_periph_disable(id); // disable periph s_hal_spi_rx_isr_disable(id); //hal_SPI4ENCODER_IT_RX_DISA(port); // disable interrupt rx // set back to zero the frame burst intitem->frameburstcountdown = 0; // set rx counter to zero again intitem->isrrxcounter = 0; // copy the rxframe into the rx fifo if(hal_true == hal_utility_fifo_full(&(intitem->fiforx))) { hal_utility_fifo_pop(&(intitem->fiforx)); } hal_utility_fifo_put(&(intitem->fiforx), intitem->isrrxframe); // now manage the callback hal_callback_t onframereceiv = intitem->config.onframereceiv; void *arg = intitem->config.argonframereceiv; if(NULL != onframereceiv) { onframereceiv(arg); } } else { // transmit one dummy byte to trigger yet another reception SPI_I2S_SendData(SPIx, intitem->config.dummytxvalue); } }
extern hal_result_t hal_spi_raw_master_writeread(hal_spi_t id, uint8_t byte, uint8_t* readbyte) { hal_spi_internal_item_t* intitem = s_hal_spi_theinternals.items[HAL_spi_id2index(id)]; hal_spi_cfg_t* cfg = NULL; volatile uint32_t timeout = 0; SPI_TypeDef* SPIx = HAL_spi_id2stmSPI(id); if(hal_false == hal_spi_hid_initted_is(id)) { return(hal_res_NOK_generic); } cfg = &intitem->config; if(hal_spi_act_raw != cfg->activity) { return(hal_res_NOK_generic); } // before we write we need to wait for the spi has txe set timeout = s_hal_spi_timeout_flag; while(RESET == SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE)) { if(0 == (timeout--)) s_hal_spi_timeoutexpired(); } // ok. we send the byte SPI_I2S_SendData(SPIx, byte); // we need to wait for a reply from the slave timeout = s_hal_spi_timeout_flag; while(RESET == SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE)) { if(0 == (timeout--)) s_hal_spi_timeoutexpired(); } // ok. here it is uint8_t rb = SPI_I2S_ReceiveData(SPIx); // if we want to retrieve it we copy into return value if(NULL != readbyte) { *readbyte = rb; } return(hal_res_OK); }
static void s_hal_spi_dma_on_tranfer_done_tx(void* p) { hal_spi_internal_item_t* intitem = (hal_spi_internal_item_t*)p; hal_dma_dontdisable(s_hal_spi_dma_port2use_tx[HAL_spi_id2index(intitem->id)]); // alert about a transmission done if(hal_spi_dir_rxonly != intitem->config.direction) { hal_callback_t onframetransm = intitem->config.onframetransm; if(NULL != onframetransm) { onframetransm(intitem->config.argonframetransm); } } }
extern hal_result_t hal_spi_start(hal_spi_t id, uint8_t lengthofburst) { hal_spi_internal_item_t* intitem = s_hal_spi_theinternals.items[HAL_spi_id2index(id)]; SPI_TypeDef* SPIx = HAL_spi_id2stmSPI(id); uint8_t num2use = 1; if(hal_false == hal_spi_hid_initted_is(id)) { return(hal_res_NOK_generic); } #if 0 if(hal_spi_act_framebased != intitem->config.activity) { return(hal_res_NOK_generic); } #endif // protect ... may be not needed s_hal_spi_rx_isr_disable(id); //hal_SPI4ENCODER_IT_RX_DISA(SPIx); // tells how many frames to use intitem->frameburstcountdown = num2use; // reset isrrxframe and its counter memset(intitem->isrrxframe, 0, intitem->config.sizeofframe); intitem->isrrxcounter = 0; s_hal_spi_rx_isr_enable(id); // hal_SPI4ENCODER_IT_RX_ENA(SPIx); // enable interrupt rx s_hal_spi_periph_enable(id); // hal_SPI4ENCODER_ENA(SPIx); // enable spi peripheral // in order to read data I have to write a dummy byte. the channel is configured in full duplex mode. while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(SPIx, intitem->config.dummytxvalue); // ok, the isr shall read n frames of m bytes each and then issue a callback to me. // n = intitem->frameburstcountdown (=1 for encoder), and m = intitem->config.sizeofframe (=3 for encoder) return(hal_res_OK); }
static hal_result_t s_hal_spi_init(hal_spi_t id, const hal_spi_cfg_t *cfg) { hal_spi_internal_item_t* intitem = s_hal_spi_theinternals.items[HAL_spi_id2index(id)]; //hal_spi_cfg_t *usedcfg = NULL; uint8_t* tmpbuffer = NULL; if(NULL == cfg) { cfg = &hal_spi_cfg_default; } if(hal_true != s_hal_spi_supported_is(id)) { return(hal_res_NOK_unsupported); } if(hal_true == hal_spi_hid_initted_is(id)) { return(hal_res_OK); } // mild verification of the config: speed, activity, sizeofframe only if(hal_false == s_hal_spi_is_speed_correct((int32_t)cfg->speed)) { return(hal_res_NOK_generic); } if(hal_spi_ownership_master != cfg->ownership) { return(hal_res_NOK_generic); } if(hal_spi_act_framebased != cfg->activity) { return(hal_res_NOK_generic); } if(0 == cfg->sizeofframe) { return(hal_res_NOK_generic); } if(hal_spi_dir_rxonly != cfg->direction) { return(hal_res_NOK_generic); } if(0 == cfg->capacityofrxfifoofframes) { return(hal_res_NOK_generic); } // acemor: very important info. // init the miso and mosi gpio before calling hw_init. // because if the spi is already initted and it detects mosi or miso low it sets // register SPI_SR2.BUSY to 1, which makes things hang up. //s_hal_spi_hw_gpio_init(id, cfg->ownership); //s_hal_spi_hw_init(id); //s_hal_spi_hw_enable(id, cfg); // on ems001 and ems4rd it works with SPI_CPOL_High const hl_spi_advcfg_t hl_spi_advcfg_ems4rd = { .SPI_Direction = SPI_Direction_2Lines_FullDuplex, .SPI_Mode = SPI_Mode_Master, // param .SPI_DataSize = SPI_DataSize_8b, .SPI_CPOL = SPI_CPOL_High, //SPI_CPOL_High, //SPI_CPOL_Low, //SPI_CPOL_Low, // SPI_CPOL_High high is ok with display and also ok with isr mode .SPI_CPHA = SPI_CPHA_1Edge, //SPI_CPHA_2Edge, .SPI_NSS = SPI_NSS_Soft, .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64, // param: depends on speed. with 64 it it is 42/64 = 0.65625 mhz (or 1.3125 w/ 32) .SPI_FirstBit = SPI_FirstBit_MSB, // SPI_FirstBit_MSB is ok with display, su stm3210c e' indifferente .SPI_CRCPolynomial = 0x0007 // reset value }; hl_spi_cfg_t hlcfg = { .mode = hl_spi_mode_master, .prescaler = hl_spi_prescaler_064, .advcfg = &hl_spi_advcfg_ems4rd }; hlcfg.mode = (hal_spi_ownership_master == cfg->ownership) ? (hl_spi_mode_master) : (hl_spi_mode_slave); hlcfg.prescaler = s_hal_spi_get_hl_prescaler(id, cfg);; // we must initialise hl_spi_map w/ suited values. // we have built hal_brdcfg_spi__theconfig to have the same layout, but we verify it anyway hl_VERIFYproposition(xxx, sizeof(hl_spi_mapping_t) == sizeof(hal_spi_hid_brdcfg_t)); hl_spi_map = (hl_spi_mapping_t*)&hal_brdcfg_spi__theconfig; hl_spi_init((hl_spi_t)id, &hlcfg); // the gpio, the clock hl_spi_enable((hl_spi_t)id); // the SPI_Init(), but not the DMA ... #warning --> see in hal1 if there is anything about isr of spi // -------------------------------------------------------------------------------------- // init the spi internals data structure // if it does not have ram yet, then attempt to allocate it. if(NULL == intitem) { intitem = s_hal_spi_theinternals.items[HAL_spi_id2index(id)] = hal_heap_new(sizeof(hal_spi_internal_item_t)); // minimal initialisation of the internal item // nothing to init. } // - the config memcpy(&intitem->config, cfg, sizeof(hal_spi_cfg_t)); hal_spi_cfg_t *usedcfg = NULL; usedcfg = &intitem->config; // only frame-based // - the isr rx frame intitem->isrrxframe = (uint8_t*)hal_heap_new(usedcfg->sizeofframe); intitem->isrrxcounter = 0; // - the fifo of rx frames. but only if it is needed ... we dont need it if ... tmpbuffer = (uint8_t*) hal_heap_new(usedcfg->capacityofrxfifoofframes*usedcfg->sizeofframe); hal_utility_fifo_init(&intitem->fiforx, usedcfg->capacityofrxfifoofframes, usedcfg->sizeofframe, tmpbuffer, NULL); // - the id intitem->id = id; // - frameburstcountdown intitem->frameburstcountdown = 0; // -- locked intitem->isrisenabled = hal_false; // now ... init the isr (only for frame-based activity) s_hal_spi_isr_init(id, usedcfg); // ok, it is initted s_hal_spi_initted_set(id); return(hal_res_OK); } static hal_bool_t s_hal_spi_is_speed_correct(int32_t speed) { if(hal_spi_speed_dontuse == speed) { return(hal_true); } else { return(hal_false); } } static hl_spi_prescaler_t s_hal_spi_get_hl_prescaler(hal_spi_t id, const hal_spi_cfg_t* cfg) { hl_spi_prescaler_t hlprescaler = hl_spi_prescaler_064; return(hlprescaler); // if((hal_spi_speed_dontuse == cfg->speed) && (hal_spi_prescaler_dontuse == cfg->prescaler)) // { // hal_base_on_fatalerror(hal_fatalerror_incorrectparameter, "hal_spi_init(): use one of speed or prescaler"); // } // if((hal_spi_speed_dontuse != cfg->speed) && (hal_spi_prescaler_dontuse != cfg->prescaler)) // { // hal_base_on_fatalerror(hal_fatalerror_incorrectparameter, "hal_spi_init(): use either speed or prescaler, not both"); // } // // if(hal_spi_prescaler_dontuse != cfg->prescaler) // { // ok, we have the prescaler. need only to convert it in stm32fx format // // switch(cfg->prescaler) // { // remember that hal_spi_prescaler_xxx is referred to high speed bus, // // and prescaler_stm32fx to high speed bus for spi1 but to low speed for spi2 and spi3 // case hal_spi_prescaler_004: // { // hlprescaler = hl_spi_prescaler_004; // } break; // case hal_spi_prescaler_008: // { // hlprescaler = hl_spi_prescaler_008; // } break; // case hal_spi_prescaler_016: // { // hlprescaler = hl_spi_prescaler_016; // } break; // case hal_spi_prescaler_032: // { // hlprescaler = hl_spi_prescaler_032; // } break; // case hal_spi_prescaler_064: // { // hlprescaler = hl_spi_prescaler_064; // } break; // case hal_spi_prescaler_128: // { // hlprescaler = hl_spi_prescaler_128; // } break; // case hal_spi_prescaler_256: // { // hlprescaler = hl_spi_prescaler_256; // } break; // default: // { // hlprescaler = hl_spi_prescaler_256; // } break; // } // } // else if(hal_spi_speed_dontuse != cfg->speed) // { // ok, use the speed to compute the prescaler in stm32fx format // // // remember that hal_spi_prescaler_xxx is referred to high speed bus, // // and prescaler_stm32fx to high speed bus for spi1 but to low speed for spi2 and spi3 // uint16_t factor = (hal_spi1 == id) ? (hal_brdcfg_cpu__theconfig.speeds.fastbus / cfg->speed) : (hal_brdcfg_cpu__theconfig.speeds.slowbus / cfg->speed); // // switch(factor) // { // case 2: hlprescaler = hl_spi_prescaler_002; break; // case 4: hlprescaler = hl_spi_prescaler_004; break; // case 8: hlprescaler = hl_spi_prescaler_008; break; // case 16: hlprescaler = hl_spi_prescaler_016; break; // case 32: hlprescaler = hl_spi_prescaler_032; break; // case 64: hlprescaler = hl_spi_prescaler_064; break; // case 128: hlprescaler = hl_spi_prescaler_128; break; // case 256: hlprescaler = hl_spi_prescaler_256; break; // default: hlprescaler = hl_spi_prescaler_256; break; // } // } // return(hlprescaler); }
static void s_hal_spi_hw_gpio_init(hal_spi_t id, hal_spi_ownership_t ownership) { #if defined(HAL_USE_CPU_FAM_STM32F1) static const GPIO_InitTypeDef s_hal_spi_sckmosi_master_altcfg = { .GPIO_Pin = 0, .GPIO_Speed = GPIO_Speed_50MHz, .GPIO_Mode = GPIO_Mode_AF_PP, // il PP serve per spi del display3 .... GPIO_Mode_AF_OD, }; static const GPIO_InitTypeDef s_hal_spi_miso_master_altcfg = { .GPIO_Pin = 0, .GPIO_Speed = GPIO_Speed_50MHz, .GPIO_Mode = GPIO_Mode_IN_FLOATING, //GPIO_Mode_IPD, // oppure ... GPIO_Mode_IN_FLOATING? }; static const GPIO_InitTypeDef s_hal_spi_sckmosi_slave_altcfg = { .GPIO_Pin = 0, .GPIO_Speed = GPIO_Speed_50MHz, .GPIO_Mode = GPIO_Mode_IN_FLOATING, //GPIO_Mode_IPD, // oppure ... GPIO_Mode_IN_FLOATING, }; static const GPIO_InitTypeDef s_hal_spi_miso_slave_altcfg = { .GPIO_Pin = 0, .GPIO_Speed = GPIO_Speed_50MHz, .GPIO_Mode = GPIO_Mode_AF_PP, }; // 1. prepare af. // for spi1 (sck, miso, mosi): no-remap if it is (PA5, PA6, PA7). GPIO_Remap_SPI1 if it is (PB3, PB4, PB5). // for spi2 (sck, miso, mosi): no remap if it is (PB13, PB14, PB15). // for spi3 (sck, miso, mosi): no-remap if it is (PB3, PB4, PB5). GPIO_Remap_SPI3 if it is (PC10, PC11, PC12). uint32_t afname = HAL_GPIO_AFNAME_NONE; uint32_t afmode = HAL_GPIO_AFMODE_NONE; hal_bool_t found = hal_false; hal_gpio_port_t portsck = hal_brdcfg_spi__theconfig.gpio_sck[HAL_spi_id2index(id)].gpio.port; hal_gpio_pin_t pinsck = hal_brdcfg_spi__theconfig.gpio_sck[HAL_spi_id2index(id)].gpio.pin; hal_gpio_port_t portmiso = hal_brdcfg_spi__theconfig.gpio_miso[HAL_spi_id2index(id)].gpio.port; hal_gpio_pin_t pinmiso = hal_brdcfg_spi__theconfig.gpio_miso[HAL_spi_id2index(id)].gpio.pin; hal_gpio_port_t portmosi = hal_brdcfg_spi__theconfig.gpio_mosi[HAL_spi_id2index(id)].gpio.port; hal_gpio_pin_t pinmosi = hal_brdcfg_spi__theconfig.gpio_mosi[HAL_spi_id2index(id)].gpio.pin; if(hal_spi1 == id) { if((hal_gpio_portA == portsck) && (hal_gpio_pin5 == pinsck) && (hal_gpio_portA == portmiso) && (hal_gpio_pin6 == pinmiso) && (hal_gpio_portA == portmosi) && (hal_gpio_pin7 == pinmosi)) { // PA5, PA6, PA7 afname = HAL_GPIO_AFNAME_NONE; afmode = HAL_GPIO_AFMODE_NONE; found = hal_true; } else if((hal_gpio_portB == portsck) && (hal_gpio_pin3 == pinsck) && (hal_gpio_portB == portmiso) && (hal_gpio_pin4 == pinmiso) && (hal_gpio_portB == portmosi) && (hal_gpio_pin5 == pinmosi)) { // PB3, PB4, PB5 afname = GPIO_Remap_SPI1; afmode = ENABLE; found = hal_true; } } else if(hal_spi2 == id) { if((hal_gpio_portB == portmiso) && (hal_gpio_portB == portmosi) && (hal_gpio_portB == portsck) && (hal_gpio_pin14 == pinmiso) && (hal_gpio_pin15 == pinmosi) && (hal_gpio_pin13 == pinsck)) { // PB13, PB14, PB15 afname = HAL_GPIO_AFNAME_NONE; afmode = HAL_GPIO_AFMODE_NONE; found = hal_true; } } else if(hal_spi3 == id) { if((hal_gpio_portB == portsck) && (hal_gpio_pin3 == pinsck) && (hal_gpio_portB == portmiso) && (hal_gpio_pin4 == pinmiso) && (hal_gpio_portB == portmosi) && (hal_gpio_pin5 == pinmosi)) { // PB3, PB4, PB5 afname = HAL_GPIO_AFNAME_NONE; afmode = HAL_GPIO_AFMODE_NONE; found = hal_true; } else if((hal_gpio_portC == portsck) && (hal_gpio_pin10 == pinsck) && (hal_gpio_portC == portmiso) && (hal_gpio_pin11 == pinmiso) && (hal_gpio_portC == portmosi) && (hal_gpio_pin12 == pinmosi)) { // PC10, PC11, PC12 afname = GPIO_Remap_SPI3; afmode = ENABLE; found = hal_true; } } if(hal_false == found) { hal_base_on_fatalerror(hal_fatalerror_incorrectparameter, "hal_spi_init(): incorrect pin mapping"); } hal_gpio_altcfg_t hal_spi_sck_altcfg; hal_gpio_altcfg_t hal_spi_miso_altcfg; hal_gpio_altcfg_t hal_spi_mosi_altcfg; hal_gpio_cfg_t config; // prepare the altcfg for sck, miso, mosi pins if(hal_spi_ownership_master == ownership) { memcpy(&hal_spi_sck_altcfg, &s_hal_spi_sckmosi_master_altcfg, sizeof(hal_gpio_altcfg_t)); memcpy(&hal_spi_miso_altcfg, &s_hal_spi_miso_master_altcfg, sizeof(hal_gpio_altcfg_t)); memcpy(&hal_spi_mosi_altcfg, &s_hal_spi_sckmosi_master_altcfg, sizeof(hal_gpio_altcfg_t)); } else { memcpy(&hal_spi_sck_altcfg, &s_hal_spi_sckmosi_slave_altcfg, sizeof(hal_gpio_altcfg_t)); memcpy(&hal_spi_miso_altcfg, &s_hal_spi_miso_slave_altcfg, sizeof(hal_gpio_altcfg_t)); memcpy(&hal_spi_mosi_altcfg, &s_hal_spi_sckmosi_slave_altcfg, sizeof(hal_gpio_altcfg_t)); } hal_spi_sck_altcfg.afname = hal_spi_miso_altcfg.afname = hal_spi_mosi_altcfg.afname = afname; hal_spi_sck_altcfg.afname = hal_spi_miso_altcfg.afmode = hal_spi_mosi_altcfg.afmode = afmode; // configure miso, mosi, sck pins memcpy(&config, &hal_brdcfg_spi__theconfig.gpio_sck[HAL_spi_id2index(id)].config, sizeof(hal_gpio_cfg_t)); config.altcfg = &hal_spi_sck_altcfg; hal_gpio_init(hal_brdcfg_spi__theconfig.gpio_sck[HAL_spi_id2index(id)].gpio, &config); memcpy(&config, &hal_brdcfg_spi__theconfig.gpio_miso[HAL_spi_id2index(id)].config, sizeof(hal_gpio_cfg_t)); config.altcfg = &hal_spi_miso_altcfg; hal_gpio_init(hal_brdcfg_spi__theconfig.gpio_miso[HAL_spi_id2index(id)].gpio, &config); memcpy(&config, &hal_brdcfg_spi__theconfig.gpio_mosi[HAL_spi_id2index(id)].config, sizeof(hal_gpio_cfg_t)); config.altcfg = &hal_spi_mosi_altcfg; hal_gpio_init(hal_brdcfg_spi__theconfig.gpio_mosi[HAL_spi_id2index(id)].gpio, &config); // hal_gpio_configure(hal_brdcfg_spi__theconfig.gpio_sck[HAL_spi_id2index(id)], &hal_spi_sck_altcfg); // hal_gpio_configure(hal_brdcfg_spi__theconfig.gpio_miso[HAL_spi_id2index(id)], &hal_spi_miso_altcfg); // hal_gpio_configure(hal_brdcfg_spi__theconfig.gpio_mosi[HAL_spi_id2index(id)], &hal_spi_mosi_altcfg); #elif defined(HAL_USE_CPU_FAM_STM32F4) static const GPIO_InitTypeDef s_hal_spi_misomosisck_altcfg = { .GPIO_Pin = 0, .GPIO_Mode = GPIO_Mode_AF, .GPIO_Speed = GPIO_Speed_50MHz, .GPIO_OType = GPIO_OType_PP, .GPIO_PuPd = GPIO_PuPd_DOWN }; // 1. prepare af. // for spi1 (sck, miso, mosi): sck -> PA5, PB3. miso -> PA6, PB4. mosi -> PA7, PB5. // for spi2 (sck, miso, mosi): sck -> PB10, PB13, PI1. miso -> PAB14, PC2, PI2. mosi -> PB15, PC3, PI3. // for spi3 (sck, miso, mosi): sck -> PB3, PC10. miso -> PB4, PC11. mosi -> PB5, PC12. uint32_t afname = HAL_GPIO_AFNAME_NONE; uint32_t afmode = HAL_GPIO_AFMODE_NONE; hal_bool_t foundsck = hal_false; hal_bool_t foundmiso = hal_false; hal_bool_t foundmosi = hal_false; hal_gpio_port_t portsck = hal_brdcfg_spi__theconfig.gpiomap[HAL_spi_id2index(id)].sck.gpio.port; hal_gpio_pin_t pinsck = hal_brdcfg_spi__theconfig.gpiomap[HAL_spi_id2index(id)].sck.gpio.pin; hal_gpio_port_t portmiso = hal_brdcfg_spi__theconfig.gpiomap[HAL_spi_id2index(id)].miso.gpio.port; hal_gpio_pin_t pinmiso = hal_brdcfg_spi__theconfig.gpiomap[HAL_spi_id2index(id)].miso.gpio.pin; hal_gpio_port_t portmosi = hal_brdcfg_spi__theconfig.gpiomap[HAL_spi_id2index(id)].mosi.gpio.port; hal_gpio_pin_t pinmosi = hal_brdcfg_spi__theconfig.gpiomap[HAL_spi_id2index(id)].mosi.gpio.pin; if(hal_spi1 == id) { afname = GPIO_AF_SPI1; afmode = ENABLE; if( ((hal_gpio_portA == portsck) && (hal_gpio_pin5 == pinsck)) || ((hal_gpio_portB == portsck) && (hal_gpio_pin3 == pinsck)) ) { // PA5, PB3 foundsck = hal_true; } if( ((hal_gpio_portA == portmiso) && (hal_gpio_pin6 == pinmiso)) || ((hal_gpio_portB == portmiso) && (hal_gpio_pin4 == pinmiso)) ) { // PA6, PB4 foundmiso = hal_true; } if( ((hal_gpio_portA == portmosi) && (hal_gpio_pin7 == pinmosi)) || ((hal_gpio_portB == portmosi) && (hal_gpio_pin5 == pinmosi)) ) { // PA7, PB5 foundmosi = hal_true; } } else if(hal_spi2 == id) { afname = GPIO_AF_SPI2; afmode = ENABLE; if( ((hal_gpio_portB == portsck) && (hal_gpio_pin10 == pinsck)) || ((hal_gpio_portB == portsck) && (hal_gpio_pin13 == pinsck)) || ((hal_gpio_portI == portsck) && (hal_gpio_pin1 == pinsck)) ) { // PB10, PB13, PI1 foundsck = hal_true; } if( ((hal_gpio_portB == portmiso) && (hal_gpio_pin14 == pinmiso)) || ((hal_gpio_portC == portmiso) && (hal_gpio_pin2 == pinmiso)) || ((hal_gpio_portI == portmiso) && (hal_gpio_pin2 == pinmiso)) ) { // PAB14, PC2, PI2 foundmiso = hal_true; } if( ((hal_gpio_portB == portmosi) && (hal_gpio_pin15 == pinmosi)) || ((hal_gpio_portC == portmosi) && (hal_gpio_pin3 == pinmosi)) || ((hal_gpio_portI == portmosi) && (hal_gpio_pin3 == pinmosi)) ) { // PB15, PC3, PI3 foundmosi = hal_true; } } else if(hal_spi3 == id) { afname = GPIO_AF_SPI3; afmode = ENABLE; if( ((hal_gpio_portB == portsck) && (hal_gpio_pin3 == pinsck)) || ((hal_gpio_portC == portsck) && (hal_gpio_pin10 == pinsck)) ) { // PB3, PC10 foundsck = hal_true; } if( ((hal_gpio_portB == portmiso) && (hal_gpio_pin4 == pinmiso)) || ((hal_gpio_portC == portmiso) && (hal_gpio_pin11 == pinmiso)) ) { // PB4, PC11 foundmiso = hal_true; } if( ((hal_gpio_portB == portmosi) && (hal_gpio_pin5 == pinmosi)) || ((hal_gpio_portC == portmosi) && (hal_gpio_pin12 == pinmosi)) ) { // PB5, PC12 foundmosi = hal_true; } } if((hal_false == foundsck) || (hal_false == foundmiso) || (hal_false == foundmosi)) { hal_base_on_fatalerror(hal_fatalerror_incorrectparameter, "hal_spi_init(): incorrect pin mapping"); } hal_gpio_cfg_t hal_spi_sck_cfg; hal_gpio_cfg_t hal_spi_miso_cfg; hal_gpio_cfg_t hal_spi_mosi_cfg; hal_gpio_altcfg_t hal_spi_sck_altcfg; hal_gpio_altcfg_t hal_spi_miso_altcfg; hal_gpio_altcfg_t hal_spi_mosi_altcfg; // prepare the altcfg for sck miso mosi pins memcpy(&hal_spi_sck_altcfg.gpioext, &s_hal_spi_misomosisck_altcfg, sizeof(GPIO_InitTypeDef)); memcpy(&hal_spi_miso_altcfg.gpioext, &s_hal_spi_misomosisck_altcfg, sizeof(GPIO_InitTypeDef)); memcpy(&hal_spi_mosi_altcfg.gpioext, &s_hal_spi_misomosisck_altcfg, sizeof(GPIO_InitTypeDef)); hal_spi_sck_altcfg.afname = hal_spi_miso_altcfg.afname = hal_spi_mosi_altcfg.afname = afname; hal_spi_sck_altcfg.afmode = hal_spi_miso_altcfg.afmode = hal_spi_mosi_altcfg.afmode = afmode; // the gpiocfgs. hal_spi_sck_cfg.dir = hal_gpio_dirALT; hal_spi_sck_cfg.speed = hal_gpio_speed_default; hal_spi_sck_cfg.altcfg = &hal_spi_sck_altcfg; hal_spi_miso_cfg.dir = hal_gpio_dirALT; hal_spi_miso_cfg.speed = hal_gpio_speed_default; hal_spi_miso_cfg.altcfg = &hal_spi_miso_altcfg; hal_spi_mosi_cfg.dir = hal_gpio_dirALT; hal_spi_mosi_cfg.speed = hal_gpio_speed_default; hal_spi_mosi_cfg.altcfg = &hal_spi_mosi_altcfg; // configure sck miso mosi pins hal_gpio_init(hal_brdcfg_spi__theconfig.gpiomap[HAL_spi_id2index(id)].sck.gpio, &hal_spi_sck_cfg); hal_gpio_init(hal_brdcfg_spi__theconfig.gpiomap[HAL_spi_id2index(id)].miso.gpio, &hal_spi_miso_cfg); hal_gpio_init(hal_brdcfg_spi__theconfig.gpiomap[HAL_spi_id2index(id)].mosi.gpio, &hal_spi_mosi_cfg); #else //defined(HAL_USE_CPU_FAM_*) #error ERR --> choose a HAL_USE_CPU_FAM_* #endif } static void s_hal_spi_hw_enable(hal_spi_t id, const hal_spi_cfg_t* cfg) { #if defined(HAL_USE_CPU_FAM_STM32F1) || defined(HAL_USE_CPU_FAM_STM32F4) SPI_TypeDef* SPIx = HAL_spi_id2stmSPI(id); uint16_t prescaler_stm32fx = 0; SPI_InitTypeDef spi_cfg; SPI_I2S_DeInit(SPIx); memcpy(&spi_cfg, &s_hal_spi_stm32_cfg, sizeof(SPI_InitTypeDef)); // apply the mode spi_cfg.SPI_Mode = (hal_spi_ownership_master == cfg->ownership) ? (SPI_Mode_Master) : (SPI_Mode_Slave); // configure speed of spi ... if((hal_spi_speed_dontuse == cfg->speed) && (hal_spi_prescaler_dontuse == cfg->prescaler)) { hal_base_on_fatalerror(hal_fatalerror_incorrectparameter, "hal_spi_init(): use one of speed or prescaler"); } if((hal_spi_speed_dontuse != cfg->speed) && (hal_spi_prescaler_dontuse != cfg->prescaler)) { hal_base_on_fatalerror(hal_fatalerror_incorrectparameter, "hal_spi_init(): use either speed or prescaler, not both"); } if(hal_spi_prescaler_dontuse != cfg->prescaler) { // ok, we have the prescaler. need only to convert it in stm32fx format switch(cfg->prescaler) { // remember that hal_spi_prescaler_xxx is referred to high speed bus, // and prescaler_stm32fx to high speed bus for spi1 but to low speed for spi2 and spi3 case hal_spi_prescaler_004: { prescaler_stm32fx = (hal_spi1 == id) ? SPI_BaudRatePrescaler_4 : SPI_BaudRatePrescaler_2; } break; case hal_spi_prescaler_008: { prescaler_stm32fx = (hal_spi1 == id) ? SPI_BaudRatePrescaler_8 : SPI_BaudRatePrescaler_4; } break; case hal_spi_prescaler_016: { prescaler_stm32fx = (hal_spi1 == id) ? SPI_BaudRatePrescaler_16 : SPI_BaudRatePrescaler_8; } break; case hal_spi_prescaler_032: { prescaler_stm32fx = (hal_spi1 == id) ? SPI_BaudRatePrescaler_32 : SPI_BaudRatePrescaler_16; } break; case hal_spi_prescaler_064: { prescaler_stm32fx = (hal_spi1 == id) ? SPI_BaudRatePrescaler_64 : SPI_BaudRatePrescaler_32; } break; case hal_spi_prescaler_128: { prescaler_stm32fx = (hal_spi1 == id) ? SPI_BaudRatePrescaler_128 : SPI_BaudRatePrescaler_64; } break; case hal_spi_prescaler_256: { prescaler_stm32fx = (hal_spi1 == id) ? SPI_BaudRatePrescaler_256 : SPI_BaudRatePrescaler_128; } break; default: { prescaler_stm32fx = SPI_BaudRatePrescaler_256; } break; } } else if(hal_spi_speed_dontuse != cfg->speed) { // ok, use the speed to compute the prescaler in stm32fx format // remember that hal_spi_prescaler_xxx is referred to high speed bus, // and prescaler_stm32fx to high speed bus for spi1 but to low speed for spi2 and spi3 uint16_t factor = (hal_spi1 == id) ? (hal_brdcfg_cpu__theconfig.speeds.fastbus / cfg->speed) : (hal_brdcfg_cpu__theconfig.speeds.slowbus / cfg->speed); switch(factor) { case 2: prescaler_stm32fx = SPI_BaudRatePrescaler_2; break; case 4: prescaler_stm32fx = SPI_BaudRatePrescaler_4; break; case 8: prescaler_stm32fx = SPI_BaudRatePrescaler_8; break; case 16: prescaler_stm32fx = SPI_BaudRatePrescaler_16; break; case 32: prescaler_stm32fx = SPI_BaudRatePrescaler_32; break; case 64: prescaler_stm32fx = SPI_BaudRatePrescaler_64; break; case 128: prescaler_stm32fx = SPI_BaudRatePrescaler_128; break; case 256: prescaler_stm32fx = SPI_BaudRatePrescaler_256; break; default: prescaler_stm32fx = SPI_BaudRatePrescaler_256; break; } } // ok ... we have prescaler_stm32fx at last. spi_cfg.SPI_BaudRatePrescaler = prescaler_stm32fx; // can init spi SPI_Init(SPIx, &spi_cfg); if(hal_spi_act_framebased == cfg->activity) { // enable dma rx request SPI_I2S_DMACmd(SPIx, SPI_I2S_DMAReq_Rx, ENABLE); // enable dma tx request SPI_I2S_DMACmd(SPIx, SPI_I2S_DMAReq_Tx, ENABLE); } #else //defined(HAL_USE_CPU_FAM_*) #error ERR --> choose a HAL_USE_CPU_FAM_* #endif } static hal_result_t s_hal_spi_timeoutexpired(void) { hal_base_on_fatalerror(hal_fatalerror_incorrectparameter, "timeout error in spi raw operations"); return(hal_res_NOK_generic); } #if 0 static void s_hal_spi_scheduling_suspend(void) { hal_base_osal_scheduling_suspend(); } static void s_hal_spi_scheduling_restart(void) { hal_base_osal_scheduling_restart(); } #endif static hal_result_t s_hal_spi_put(hal_spi_t id, uint8_t* txframe) { hal_result_t res = hal_res_NOK_generic; hal_spi_internal_item_t* intitem = s_hal_spi_theinternals.items[HAL_spi_id2index(id)]; hal_spi_cfg_t* cfg = &intitem->config; if(hal_spi_act_framebased != cfg->activity) { return(hal_res_NOK_generic); } if(hal_spi_dir_rxonly != cfg->direction) { // disable so that we can change a data structure which is used by the isr hal_bool_t dmaisenabled = s_hal_spi_is_dma_enabled(id); if(hal_true == dmaisenabled) { s_hal_spi_periph_dma_isr_disable(id); } res = hal_utility_fifo_put(&intitem->fifotx, txframe); if(hal_true == dmaisenabled) { s_hal_spi_periph_dma_isr_enable(id); } } // if(hal_true == sendnow) // { // // enable again // s_hal_spi_periph_dma_enable(id); // } return(res); } static hal_result_t s_hal_spi_get(hal_spi_t id, uint8_t* rxframe, uint8_t* remainingrxframes) { hal_result_t res = hal_res_NOK_generic; hal_spi_internal_item_t* intitem = s_hal_spi_theinternals.items[HAL_spi_id2index(id)]; hal_spi_cfg_t* cfg = &intitem->config; if(hal_spi_act_framebased != cfg->activity) { return(hal_res_NOK_generic); } if(hal_spi_dir_txonly != intitem->config.direction) { hal_bool_t dmaisenabled = s_hal_spi_is_dma_enabled(id); if(hal_true == dmaisenabled) { s_hal_spi_periph_dma_isr_disable(id); } res = hal_utility_fifo_get(&intitem->fiforx, rxframe, remainingrxframes); if(hal_true == dmaisenabled) { s_hal_spi_periph_dma_isr_enable(id); } } // if(NULL != size) // { // *size = (hal_res_OK == res) ? (s_hal_spi_internals[HAL_spi_id2index(id)].config.sizeofframe) : (0); // } // enable again // s_hal_spi_isr_enable(id); return(res); } static void s_hal_spi_periph_dma_isr_enable(hal_spi_t id) { hal_dma_isr_enable(s_hal_spi_dma_port2use_rx[HAL_spi_id2index(id)]); hal_dma_isr_enable(s_hal_spi_dma_port2use_tx[HAL_spi_id2index(id)]); }
static hal_bool_t s_hal_spi_is_dma_enabled(hal_spi_t id) { return(s_hal_spi_theinternals.items[HAL_spi_id2index(id)]->dmaisenabled); }
static hal_result_t s_hal_spi_init(hal_spi_t id, const hal_spi_cfg_t *cfg) { hal_spi_internal_item_t* intitem = s_hal_spi_theinternals.items[HAL_spi_id2index(id)]; hal_spi_cfg_t *usedcfg = NULL; uint8_t* tmpbuffer = NULL; if(NULL == cfg) { cfg = &hal_spi_cfg_default; } if(hal_true != s_hal_spi_supported_is(id)) { return(hal_res_NOK_unsupported); } if(hal_true == hal_spi_hid_initted_is(id)) { return(hal_res_OK); } // mild verification of the config: speed, activity, sizeofframe only if(hal_false == s_hal_spi_is_speed_correct((int32_t)cfg->speed)) { return(hal_res_NOK_generic); } if(hal_spi_act_raw == cfg->activity) { // verify only ownership: it can be only master if(hal_spi_ownership_master != cfg->ownership) { return(hal_res_NOK_generic); } } else if(hal_spi_act_framebased == cfg->activity) { // verify only size of frame if(0 == cfg->sizeofframe) { return(hal_res_NOK_generic); } } // acemor: very important info. // init the miso and mosi gpio before calling hw_init. // because if the spi is already initted and it detects mosi or miso low it sets // register SPI_SR2.BUSY to 1, which makes things hang up. s_hal_spi_hw_gpio_init(id, cfg->ownership); s_hal_spi_hw_init(id); s_hal_spi_hw_enable(id, cfg); // -------------------------------------------------------------------------------------- // init the spi internals data structure // if it does not have ram yet, then attempt to allocate it. if(NULL == intitem) { intitem = s_hal_spi_theinternals.items[HAL_spi_id2index(id)] = hal_heap_new(sizeof(hal_spi_internal_item_t)); // minimal initialisation of the internal item // nothing to init. } // - the config usedcfg = &intitem->config; memcpy(usedcfg, cfg, sizeof(hal_spi_cfg_t)); if(hal_spi_act_raw == usedcfg->activity) { // the rest is not used ... however i initialise it anyway ... intitem->dummytxframe = NULL; intitem->dmatxframe = NULL; intitem->dmarxframe = NULL; intitem->dmatxframe = NULL; hal_utility_fifo_init(&intitem->fifotx, 0, 0, NULL, NULL); hal_utility_fifo_init(&intitem->fiforx, 0, 0, NULL, NULL); intitem->id = id; intitem->frameburstcountdown = 0; intitem->forcestop = 0; intitem->dmaisenabled = hal_false; } else if(hal_spi_act_framebased == usedcfg->activity) { // - the dummy tx frame intitem->dummytxframe = (uint8_t*)hal_heap_new(usedcfg->sizeofframe); #if defined(HAL_MPU_SPI_DEBUG_MODE ) uint8_t i; for(i=0; i<usedcfg->sizeofframe; i++) { intitem->dummytxframe[i] = usedcfg->dummytxvalue + i; } #else memset(intitem->dummytxframe, usedcfg->dummytxvalue, usedcfg->sizeofframe); #endif // - the dma tx frame intitem->dmatxframe = (uint8_t*)hal_heap_new(usedcfg->sizeofframe); memcpy(intitem->dmatxframe, intitem->dummytxframe, usedcfg->sizeofframe); // - the dma rx frame intitem->dmarxframe = (uint8_t*)hal_heap_new(usedcfg->sizeofframe); // - the fifo of tx frames. but only if it needed ... we dont need it if ... if((0 == usedcfg->capacityoftxfifoofframes) || (hal_spi_dir_rxonly == usedcfg->direction)) { usedcfg->capacityoftxfifoofframes = 0; hal_utility_fifo_init(&intitem->fifotx, 0, 0, NULL, NULL); } else { tmpbuffer = (uint8_t*)hal_heap_new(usedcfg->capacityoftxfifoofframes*usedcfg->sizeofframe); hal_utility_fifo_init(&intitem->fifotx, usedcfg->capacityoftxfifoofframes, usedcfg->sizeofframe, tmpbuffer, NULL); } // - the fifo of rx frames. but only if it needed ... we dont need it if ... if((0 == usedcfg->capacityofrxfifoofframes) || (hal_spi_dir_txonly == usedcfg->direction)) { usedcfg->capacityofrxfifoofframes = 0; hal_utility_fifo_init(&intitem->fiforx, 0, 0, NULL, NULL); } else { tmpbuffer = (uint8_t*) hal_heap_new(usedcfg->capacityofrxfifoofframes*usedcfg->sizeofframe); hal_utility_fifo_init(&intitem->fiforx, usedcfg->capacityofrxfifoofframes, usedcfg->sizeofframe, tmpbuffer, NULL); } // - the id intitem->id = id; // - frameburstcountdown intitem->frameburstcountdown = 0; // - forcestop intitem->forcestop = 0; // -- locked intitem->dmaisenabled = hal_false; } // now ... init the dma (only for frame-based activity) if(hal_spi_act_framebased == usedcfg->activity) { s_hal_spi_dma_init(id, usedcfg); } // ok, it is initted s_hal_spi_initted_set(id); return(hal_res_OK); }
static hal_boolval_t s_hal_spi_initted_is(hal_spi_t id) { return(hal_utility_bits_byte_bitcheck(s_hal_spi_theinternals.initted, HAL_spi_id2index(id))); }
static void s_hal_spi_set_dma_enabled(hal_spi_t id, hal_bool_t value) { s_hal_spi_theinternals.items[HAL_spi_id2index(id)]->dmaisenabled = value; }
static void s_hal_spi_initted_set(hal_spi_t id) { hal_utility_bits_byte_bitset(&s_hal_spi_theinternals.initted, HAL_spi_id2index(id)); }
static hal_boolval_t s_hal_spi_supported_is(hal_spi_t id) { return(hal_utility_bits_byte_bitcheck(hal_brdcfg_spi__theconfig.supported_mask, HAL_spi_id2index(id)) ); }
extern hal_result_t hal_spi_start(hal_spi_t id, uint8_t lengthofburst) { hal_spi_internal_item_t* intitem = s_hal_spi_theinternals.items[HAL_spi_id2index(id)]; if(hal_false == hal_spi_hid_initted_is(id)) { return(hal_res_NOK_generic); } #if 0 s_hal_spi_scheduling_suspend(); if(hal_false == s_hal_spi_is_status_locked(id)) { s_hal_spi_scheduling_restart(); return(hal_res_NOK_generic); } s_hal_spi_status_setlock(); and unlock etc .... #endif if(hal_spi_act_framebased != intitem->config.activity) { return(hal_res_NOK_generic); } uint8_t num2use = 0; if(hal_spi_ownership_slave == intitem->config.ownership) { // slave ... num2use = 255; } else if((hal_spi_ownership_master == intitem->config.ownership) && (0 == lengthofburst)) { // master ... only the size of the tx buffer num2use = hal_utility_fifo_size(&intitem->fifotx); if(0 == num2use) { return(hal_res_NOK_generic); } } else { num2use = lengthofburst; } // protect s_hal_spi_periph_dma_disable(id); // tells how many frames to use intitem->frameburstcountdown = num2use; // load tx frame into dma if(hal_spi_dir_rxonly != intitem->config.direction) { if(hal_res_OK != hal_utility_fifo_get(&(intitem->fifotx), intitem->dmatxframe, NULL)) { // put the dummy one. memcpy(intitem->dmatxframe, intitem->dummytxframe, intitem->config.sizeofframe); } } s_hal_spi_periph_dma_enable(id); return(hal_res_OK); }
static void s_hal_spi_periph_dma_isr_disable(hal_spi_t id) { hal_dma_isr_disable(s_hal_spi_dma_port2use_rx[HAL_spi_id2index(id)]); hal_dma_isr_disable(s_hal_spi_dma_port2use_tx[HAL_spi_id2index(id)]); }
static void s_hal_spi_dma_init(hal_spi_t id, const hal_spi_cfg_t *cfg) { hal_spi_internal_item_t* intitem = s_hal_spi_theinternals.items[HAL_spi_id2index(id)]; hal_dma_cfg_t s_hal_spi_dma_cfg = { .transfer = hal_dma_transfer_mem2per, // it changes .mode = hal_dma_mode_oneshot, // fixed .intpriority = hal_int_priority06, // fixed .datasize = cfg->sizeofframe, // fixed .source = 0, // it changes .destin = 0, // it changes .cbk_on_transfer_done = NULL, // it changes .arg_on_transfer_done = NULL // it changes }; s_hal_spi_dma_cfg.transfer = hal_dma_transfer_per2mem; s_hal_spi_dma_cfg.source = (void*)&s_hal_spi_stmSPImap[HAL_spi_id2index(id)]->DR; s_hal_spi_dma_cfg.destin = intitem->dmarxframe; s_hal_spi_dma_cfg.cbk_on_transfer_done = s_hal_spi_dma_on_tranfer_done_rx; s_hal_spi_dma_cfg.arg_on_transfer_done = intitem; hal_dma_init(s_hal_spi_dma_port2use_rx[HAL_spi_id2index(id)], &s_hal_spi_dma_cfg); // init dma for tx s_hal_spi_dma_cfg.transfer = hal_dma_transfer_mem2per; // s_hal_spi_dma_cfg.source = intitem->dmatxframe; // s_hal_spi_dma_cfg.destin = &s_hal_spi_stmSPImap[HAL_spi_id2index(id)]->DR; s_hal_spi_dma_cfg.source = (void*)&s_hal_spi_stmSPImap[HAL_spi_id2index(id)]->DR; s_hal_spi_dma_cfg.destin = intitem->dmatxframe; s_hal_spi_dma_cfg.cbk_on_transfer_done = s_hal_spi_dma_on_tranfer_done_tx; s_hal_spi_dma_cfg.arg_on_transfer_done = intitem; hal_dma_init(s_hal_spi_dma_port2use_tx[HAL_spi_id2index(id)], &s_hal_spi_dma_cfg); } static void s_hal_spi_dma_on_tranfer_done_rx(void* p) { hal_spi_internal_item_t* intitem = (hal_spi_internal_item_t*)p; // 1. copy the rx frame into fifo if(hal_spi_dir_txonly != intitem->config.direction) { if(hal_true == hal_utility_fifo_full(&(intitem->fiforx))) { hal_utility_fifo_pop(&(intitem->fiforx)); } hal_utility_fifo_put(&(intitem->fiforx), intitem->dmarxframe); } // 2. verify if we need to stop hal_bool_t stopit = hal_false; if(hal_spi_ownership_slave == intitem->config.ownership) { stopit = hal_false; } else if(hal_spi_ownership_master == intitem->config.ownership) { if(255 == intitem->frameburstcountdown) { stopit = hal_false; } else if(0 == intitem->frameburstcountdown) { stopit = hal_true; } else { intitem->frameburstcountdown --; if(0 == intitem->frameburstcountdown) { stopit = hal_true; } else { stopit = hal_false; } } } if(hal_true == stopit) { // stop } else { if(hal_spi_dir_rxonly != intitem->config.direction) { // copy into txbuffer a new frame if(hal_res_OK != hal_utility_fifo_get(&(intitem->fifotx), intitem->dmatxframe, NULL)) { // put the dummy one. memcpy(intitem->dmatxframe, intitem->dummytxframe, intitem->config.sizeofframe); } } // retrigger tx hal_dma_retrigger(s_hal_spi_dma_port2use_tx[HAL_spi_id2index(intitem->id)]); // retrigger rx hal_dma_retrigger(s_hal_spi_dma_port2use_rx[HAL_spi_id2index(intitem->id)]); } if(hal_spi_dir_txonly != intitem->config.direction) { // alert about a reception hal_callback_t onframereceiv = intitem->config.onframereceiv; if(NULL != onframereceiv) { onframereceiv(intitem->config.argonframereceiv); } } }