extern hal_result_t hal_spi_get(hal_spi_t id, uint8_t* rxframe, uint8_t* remainingrxframes) { 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(NULL == rxframe) { return(hal_res_NOK_nullpointer); } return(s_hal_spi_get(id, rxframe, remainingrxframes)); }
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); }
extern hal_result_t hal_spi_stop(hal_spi_t id) { if(hal_false == hal_spi_hid_initted_is(id)) { return(hal_res_NOK_generic); } // empty ... #warning --> it must be called only if the spi has already stopped inside the isr //s_hal_spi_periph_dma_disable(id); return(hal_res_OK); }
extern hal_result_t hal_spi_get(hal_spi_t id, uint8_t* rxframe, uint8_t* remainingrxframes) { if(hal_false == hal_spi_hid_initted_is(id)) { return(hal_res_NOK_generic); } if(NULL == rxframe) { return(hal_res_NOK_nullpointer); } return(s_hal_spi_get(id, rxframe, remainingrxframes)); }
extern hal_result_t hal_spi_put(hal_spi_t id, uint8_t* txframe) { if(hal_false == hal_spi_hid_initted_is(id)) { return(hal_res_NOK_generic); } if(NULL == txframe) { return(hal_res_NOK_nullpointer); } return(hal_res_NOK_generic); //return(s_hal_spi_put(id, txframe)); }
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); }
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); }
extern hal_result_t hal_spi_stop(hal_spi_t 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 s_hal_spi_periph_dma_disable(id); 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_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); }
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 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); }