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);
        }
    }

}