初始版本
This commit is contained in:
95
components/drivers_nrf/nrf_soc_nosd/nrf_error.h
Normal file
95
components/drivers_nrf/nrf_soc_nosd/nrf_error.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Copyright (c) 2012 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/* Header guard */
|
||||
|
||||
#ifndef SOFTDEVICE_PRESENT
|
||||
|
||||
/**
|
||||
@defgroup nrf_error Global Error Codes
|
||||
@{
|
||||
|
||||
@brief Global Error definitions
|
||||
*/
|
||||
|
||||
#ifndef NRF_ERROR_H__
|
||||
#define NRF_ERROR_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup NRF_ERRORS_BASE Error Codes Base number definitions
|
||||
* @{ */
|
||||
#define NRF_ERROR_BASE_NUM (0x0) ///< Global error base
|
||||
#define NRF_ERROR_SDM_BASE_NUM (0x1000) ///< SDM error base
|
||||
#define NRF_ERROR_SOC_BASE_NUM (0x2000) ///< SoC error base
|
||||
#define NRF_ERROR_STK_BASE_NUM (0x3000) ///< STK error base
|
||||
/** @} */
|
||||
|
||||
#define NRF_SUCCESS (NRF_ERROR_BASE_NUM + 0) ///< Successful command
|
||||
#define NRF_ERROR_SVC_HANDLER_MISSING (NRF_ERROR_BASE_NUM + 1) ///< SVC handler is missing
|
||||
#define NRF_ERROR_SOFTDEVICE_NOT_ENABLED (NRF_ERROR_BASE_NUM + 2) ///< SoftDevice has not been enabled
|
||||
#define NRF_ERROR_INTERNAL (NRF_ERROR_BASE_NUM + 3) ///< Internal Error
|
||||
#define NRF_ERROR_NO_MEM (NRF_ERROR_BASE_NUM + 4) ///< No Memory for operation
|
||||
#define NRF_ERROR_NOT_FOUND (NRF_ERROR_BASE_NUM + 5) ///< Not found
|
||||
#define NRF_ERROR_NOT_SUPPORTED (NRF_ERROR_BASE_NUM + 6) ///< Not supported
|
||||
#define NRF_ERROR_INVALID_PARAM (NRF_ERROR_BASE_NUM + 7) ///< Invalid Parameter
|
||||
#define NRF_ERROR_INVALID_STATE (NRF_ERROR_BASE_NUM + 8) ///< Invalid state, operation disallowed in this state
|
||||
#define NRF_ERROR_INVALID_LENGTH (NRF_ERROR_BASE_NUM + 9) ///< Invalid Length
|
||||
#define NRF_ERROR_INVALID_FLAGS (NRF_ERROR_BASE_NUM + 10) ///< Invalid Flags
|
||||
#define NRF_ERROR_INVALID_DATA (NRF_ERROR_BASE_NUM + 11) ///< Invalid Data
|
||||
#define NRF_ERROR_DATA_SIZE (NRF_ERROR_BASE_NUM + 12) ///< Data size exceeds limit
|
||||
#define NRF_ERROR_TIMEOUT (NRF_ERROR_BASE_NUM + 13) ///< Operation timed out
|
||||
#define NRF_ERROR_NULL (NRF_ERROR_BASE_NUM + 14) ///< Null Pointer
|
||||
#define NRF_ERROR_FORBIDDEN (NRF_ERROR_BASE_NUM + 15) ///< Forbidden Operation
|
||||
#define NRF_ERROR_INVALID_ADDR (NRF_ERROR_BASE_NUM + 16) ///< Bad Memory Address
|
||||
#define NRF_ERROR_BUSY (NRF_ERROR_BASE_NUM + 17) ///< Busy
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRF_ERROR_H__
|
||||
|
||||
/**
|
||||
@}
|
||||
*/
|
||||
|
||||
#endif // SOFTDEVICE_PRESENT
|
||||
123
components/drivers_nrf/nrf_soc_nosd/nrf_nvic.c
Normal file
123
components/drivers_nrf/nrf_soc_nosd/nrf_nvic.c
Normal file
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include "nrf_soc.h"
|
||||
#include "nrf_error.h"
|
||||
|
||||
static uint8_t m_in_critical_region = 0;
|
||||
|
||||
uint32_t sd_nvic_EnableIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
NVIC_EnableIRQ(IRQn);
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t sd_nvic_DisableIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
NVIC_DisableIRQ(IRQn);
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t sd_nvic_GetPendingIRQ(IRQn_Type IRQn, uint32_t * p_pending_irq)
|
||||
{
|
||||
if (p_pending_irq != NULL)
|
||||
{
|
||||
*p_pending_irq = NVIC_GetPendingIRQ(IRQn);
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
return NRF_ERROR_NULL;
|
||||
}
|
||||
|
||||
uint32_t sd_nvic_SetPendingIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
NVIC_SetPendingIRQ(IRQn);
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t sd_nvic_ClearPendingIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
NVIC_ClearPendingIRQ(IRQn);
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t sd_nvic_SetPriority(IRQn_Type IRQn, uint32_t priority)
|
||||
{
|
||||
NVIC_SetPriority(IRQn, priority);
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t sd_nvic_GetPriority(IRQn_Type IRQn, uint32_t * p_priority)
|
||||
{
|
||||
if (p_priority != NULL)
|
||||
{
|
||||
*p_priority = NVIC_GetPriority(IRQn);
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
return NRF_ERROR_NULL;
|
||||
}
|
||||
|
||||
uint32_t sd_nvic_SystemReset(void)
|
||||
{
|
||||
NVIC_SystemReset();
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t sd_nvic_critical_region_enter(uint8_t * p_is_nested_critical_region)
|
||||
{
|
||||
__disable_irq();
|
||||
|
||||
*p_is_nested_critical_region = (m_in_critical_region != 0);
|
||||
m_in_critical_region++;
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t sd_nvic_critical_region_exit(uint8_t is_nested_critical_region)
|
||||
{
|
||||
m_in_critical_region--;
|
||||
|
||||
if (is_nested_critical_region == 0)
|
||||
{
|
||||
m_in_critical_region = 0;
|
||||
__enable_irq();
|
||||
}
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
166
components/drivers_nrf/nrf_soc_nosd/nrf_nvic.h
Normal file
166
components/drivers_nrf/nrf_soc_nosd/nrf_nvic.h
Normal file
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* Copyright (c) 2014 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#ifndef NRF_NVIC_H__
|
||||
#define NRF_NVIC_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "nrf.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**@brief Enable External Interrupt.
|
||||
* @note Corresponds to NVIC_EnableIRQ in CMSIS.
|
||||
*
|
||||
* @pre{IRQn is valid and not reserved by the stack}
|
||||
*
|
||||
* @param[in] IRQn See the NVIC_EnableIRQ documentation in CMSIS.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS The interrupt was enabled.
|
||||
*/
|
||||
uint32_t sd_nvic_EnableIRQ(IRQn_Type IRQn);
|
||||
|
||||
/**@brief Disable External Interrupt.
|
||||
* @note Corresponds to NVIC_DisableIRQ in CMSIS.
|
||||
*
|
||||
* @pre{IRQn is valid and not reserved by the stack}
|
||||
*
|
||||
* @param[in] IRQn See the NVIC_DisableIRQ documentation in CMSIS
|
||||
*
|
||||
* @retval ::NRF_SUCCESS The interrupt was disabled.
|
||||
*/
|
||||
uint32_t sd_nvic_DisableIRQ(IRQn_Type IRQn);
|
||||
|
||||
/**@brief Get Pending Interrupt.
|
||||
* @note Corresponds to NVIC_GetPendingIRQ in CMSIS.
|
||||
*
|
||||
* @pre{IRQn is valid and not reserved by the stack}
|
||||
*
|
||||
* @param[in] IRQn See the NVIC_GetPendingIRQ documentation in CMSIS.
|
||||
* @param[out] p_pending_irq Return value from NVIC_GetPendingIRQ.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS The interrupt is available for the application.
|
||||
*/
|
||||
uint32_t sd_nvic_GetPendingIRQ(IRQn_Type IRQn, uint32_t * p_pending_irq);
|
||||
|
||||
/**@brief Set Pending Interrupt.
|
||||
* @note Corresponds to NVIC_SetPendingIRQ in CMSIS.
|
||||
*
|
||||
* @pre{IRQn is valid and not reserved by the stack}
|
||||
*
|
||||
* @param[in] IRQn See the NVIC_SetPendingIRQ documentation in CMSIS.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS The interrupt is set pending.
|
||||
*/
|
||||
uint32_t sd_nvic_SetPendingIRQ(IRQn_Type IRQn);
|
||||
|
||||
/**@brief Clear Pending Interrupt.
|
||||
* @note Corresponds to NVIC_ClearPendingIRQ in CMSIS.
|
||||
*
|
||||
* @pre{IRQn is valid and not reserved by the stack}
|
||||
*
|
||||
* @param[in] IRQn See the NVIC_ClearPendingIRQ documentation in CMSIS.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS The interrupt pending flag is cleared.
|
||||
*/
|
||||
uint32_t sd_nvic_ClearPendingIRQ(IRQn_Type IRQn);
|
||||
|
||||
/**@brief Set Interrupt Priority.
|
||||
* @note Corresponds to NVIC_SetPriority in CMSIS.
|
||||
*
|
||||
* @pre{IRQn is valid and not reserved by the stack}
|
||||
* @pre{priority is valid and not reserved by the stack}
|
||||
*
|
||||
* @param[in] IRQn See the NVIC_SetPriority documentation in CMSIS.
|
||||
* @param[in] priority A valid IRQ priority for use by the application.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS The interrupt and priority level is available for the application.
|
||||
*/
|
||||
uint32_t sd_nvic_SetPriority(IRQn_Type IRQn, uint32_t priority);
|
||||
|
||||
/**@brief Get Interrupt Priority.
|
||||
* @note Corresponds to NVIC_GetPriority in CMSIS.
|
||||
*
|
||||
* @pre{IRQn is valid and not reserved by the stack}
|
||||
*
|
||||
* @param[in] IRQn See the NVIC_GetPriority documentation in CMSIS.
|
||||
* @param[out] p_priority Return value from NVIC_GetPriority.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS The interrupt priority is returned in p_priority.
|
||||
*/
|
||||
uint32_t sd_nvic_GetPriority(IRQn_Type IRQn, uint32_t * p_priority);
|
||||
|
||||
/**@brief System Reset.
|
||||
* @note Corresponds to NVIC_SystemReset in CMSIS.
|
||||
*
|
||||
* @retval ::NRF_ERROR_SOC_NVIC_SHOULD_NOT_RETURN
|
||||
*/
|
||||
uint32_t sd_nvic_SystemReset(void);
|
||||
|
||||
/**@brief Enters critical region.
|
||||
*
|
||||
* @post Application interrupts will be disabled.
|
||||
* @sa sd_nvic_critical_region_exit
|
||||
*
|
||||
* @param[out] p_is_nested_critical_region 1: If in a nested critical region.
|
||||
* 0: Otherwise.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
uint32_t sd_nvic_critical_region_enter(uint8_t * p_is_nested_critical_region);
|
||||
|
||||
/**@brief Exit critical region.
|
||||
*
|
||||
* @pre Application has entered a critical region using ::sd_nvic_critical_region_enter.
|
||||
* @post If not in a nested critical region, the application interrupts will restored to the state before ::sd_nvic_critical_region_enter was called.
|
||||
*
|
||||
* @param[in] is_nested_critical_region If this is set to 1, the critical region won't be exited. @sa sd_nvic_critical_region_enter.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
uint32_t sd_nvic_critical_region_exit(uint8_t is_nested_critical_region);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NRF_NVIC_H__ */
|
||||
56
components/drivers_nrf/nrf_soc_nosd/nrf_sdm.h
Normal file
56
components/drivers_nrf/nrf_soc_nosd/nrf_sdm.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright (c) 2015 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#ifndef NRF_SDM_H__
|
||||
#define NRF_SDM_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define NRF_FAULT_ID_SD_RANGE_START 0x00000000 /**< SoftDevice ID range start. */
|
||||
#define NRF_FAULT_ID_APP_RANGE_START 0x00001000 /**< Application ID range start. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // NRF_SDM_H__
|
||||
|
||||
|
||||
48
components/drivers_nrf/nrf_soc_nosd/nrf_soc.c
Normal file
48
components/drivers_nrf/nrf_soc_nosd/nrf_soc.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Copyright (c) 2014 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include "nrf_soc.h"
|
||||
#include "nrf_error.h"
|
||||
|
||||
uint32_t sd_app_evt_wait(void)
|
||||
{
|
||||
__WFE();
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
80
components/drivers_nrf/nrf_soc_nosd/nrf_soc.h
Normal file
80
components/drivers_nrf/nrf_soc_nosd/nrf_soc.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Copyright (c) 2014 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#ifndef NRF_SOC_H__
|
||||
#define NRF_SOC_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "nrf.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**@brief Waits for an application event.
|
||||
*
|
||||
* An application event is either an application interrupt or a pended interrupt when the
|
||||
* interrupt is disabled. When the interrupt is enabled it will be taken immediately since
|
||||
* this function will wait in thread mode, then the execution will return in the application's
|
||||
* main thread. When an interrupt is disabled and gets pended it will return to the application's
|
||||
* thread main. The application must ensure that the pended flag is cleared using
|
||||
* ::sd_nvic_ClearPendingIRQ in order to sleep using this function. This is only necessary for
|
||||
* disabled interrupts, as the interrupt handler will clear the pending flag automatically for
|
||||
* enabled interrupts.
|
||||
*
|
||||
* In order to wake up from disabled interrupts, the SEVONPEND flag has to be set in the Cortex-M0
|
||||
* System Control Register (SCR). @sa CMSIS_SCB
|
||||
*
|
||||
* @note If an application interrupt has happened since the last time sd_app_evt_wait was
|
||||
* called this function will return immediately and not go to sleep. This is to avoid race
|
||||
* conditions that can occur when a flag is updated in the interrupt handler and processed
|
||||
* in the main loop.
|
||||
*
|
||||
* @post An application interrupt has happened or a interrupt pending flag is set.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
uint32_t sd_app_evt_wait(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NRF_SOC_H__ */
|
||||
188
components/drivers_nrf/radio_config/radio_config.c
Normal file
188
components/drivers_nrf/radio_config/radio_config.c
Normal file
@@ -0,0 +1,188 @@
|
||||
/**
|
||||
* Copyright (c) 2009 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/** @file
|
||||
* @addtogroup nrf_dev_radio_rx_example_main nrf_dev_radio_tx_example_main
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "radio_config.h"
|
||||
#include "nrf_delay.h"
|
||||
|
||||
/* These are set to zero as ShockBurst packets don't have corresponding fields. */
|
||||
#define PACKET_S1_FIELD_SIZE (0UL) /**< Packet S1 field size in bits. */
|
||||
#define PACKET_S0_FIELD_SIZE (0UL) /**< Packet S0 field size in bits. */
|
||||
#define PACKET_LENGTH_FIELD_SIZE (0UL) /**< Packet length field size in bits. */
|
||||
|
||||
/**
|
||||
* @brief Function for swapping/mirroring bits in a byte.
|
||||
*
|
||||
*@verbatim
|
||||
* output_bit_7 = input_bit_0
|
||||
* output_bit_6 = input_bit_1
|
||||
* :
|
||||
* output_bit_0 = input_bit_7
|
||||
*@endverbatim
|
||||
*
|
||||
* @param[in] inp is the input byte to be swapped.
|
||||
*
|
||||
* @return
|
||||
* Returns the swapped/mirrored input byte.
|
||||
*/
|
||||
static uint32_t swap_bits(uint32_t inp);
|
||||
|
||||
/**
|
||||
* @brief Function for swapping bits in a 32 bit word for each byte individually.
|
||||
*
|
||||
* The bits are swapped as follows:
|
||||
* @verbatim
|
||||
* output[31:24] = input[24:31]
|
||||
* output[23:16] = input[16:23]
|
||||
* output[15:8] = input[8:15]
|
||||
* output[7:0] = input[0:7]
|
||||
* @endverbatim
|
||||
* @param[in] input is the input word to be swapped.
|
||||
*
|
||||
* @return
|
||||
* Returns the swapped input byte.
|
||||
*/
|
||||
static uint32_t bytewise_bitswap(uint32_t inp);
|
||||
|
||||
static uint32_t swap_bits(uint32_t inp)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t retval = 0;
|
||||
|
||||
inp = (inp & 0x000000FFUL);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
retval |= ((inp >> i) & 0x01) << (7 - i);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t bytewise_bitswap(uint32_t inp)
|
||||
{
|
||||
return (swap_bits(inp >> 24) << 24)
|
||||
| (swap_bits(inp >> 16) << 16)
|
||||
| (swap_bits(inp >> 8) << 8)
|
||||
| (swap_bits(inp));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Function for configuring the radio to operate in ShockBurst compatible mode.
|
||||
*
|
||||
* To configure the application running on nRF24L series devices:
|
||||
*
|
||||
* @verbatim
|
||||
* uint8_t tx_address[5] = { 0xC0, 0x01, 0x23, 0x45, 0x67 };
|
||||
* hal_nrf_set_rf_channel(7);
|
||||
* hal_nrf_set_address_width(HAL_NRF_AW_5BYTES);
|
||||
* hal_nrf_set_address(HAL_NRF_TX, tx_address);
|
||||
* hal_nrf_set_address(HAL_NRF_PIPE0, tx_address);
|
||||
* hal_nrf_open_pipe(0, false);
|
||||
* hal_nrf_set_datarate(HAL_NRF_1MBPS);
|
||||
* hal_nrf_set_crc_mode(HAL_NRF_CRC_16BIT);
|
||||
* hal_nrf_setup_dynamic_payload(0xFF);
|
||||
* hal_nrf_enable_dynamic_payload(false);
|
||||
* @endverbatim
|
||||
*
|
||||
* When transmitting packets with hal_nrf_write_tx_payload(const uint8_t *tx_pload, uint8_t length),
|
||||
* match the length with PACKET_STATIC_LENGTH.
|
||||
* hal_nrf_write_tx_payload(payload, PACKET_STATIC_LENGTH);
|
||||
*
|
||||
*/
|
||||
void radio_configure()
|
||||
{
|
||||
// Radio config
|
||||
NRF_RADIO->TXPOWER = (RADIO_TXPOWER_TXPOWER_0dBm << RADIO_TXPOWER_TXPOWER_Pos);
|
||||
NRF_RADIO->FREQUENCY = 7UL; // Frequency bin 7, 2407MHz
|
||||
NRF_RADIO->MODE = (RADIO_MODE_MODE_Nrf_1Mbit << RADIO_MODE_MODE_Pos);
|
||||
|
||||
// Radio address config
|
||||
NRF_RADIO->PREFIX0 =
|
||||
((uint32_t)swap_bits(0xC3) << 24) // Prefix byte of address 3 converted to nRF24L series format
|
||||
| ((uint32_t)swap_bits(0xC2) << 16) // Prefix byte of address 2 converted to nRF24L series format
|
||||
| ((uint32_t)swap_bits(0xC1) << 8) // Prefix byte of address 1 converted to nRF24L series format
|
||||
| ((uint32_t)swap_bits(0xC0) << 0); // Prefix byte of address 0 converted to nRF24L series format
|
||||
|
||||
NRF_RADIO->PREFIX1 =
|
||||
((uint32_t)swap_bits(0xC7) << 24) // Prefix byte of address 7 converted to nRF24L series format
|
||||
| ((uint32_t)swap_bits(0xC6) << 16) // Prefix byte of address 6 converted to nRF24L series format
|
||||
| ((uint32_t)swap_bits(0xC4) << 0); // Prefix byte of address 4 converted to nRF24L series format
|
||||
|
||||
NRF_RADIO->BASE0 = bytewise_bitswap(0x01234567UL); // Base address for prefix 0 converted to nRF24L series format
|
||||
NRF_RADIO->BASE1 = bytewise_bitswap(0x89ABCDEFUL); // Base address for prefix 1-7 converted to nRF24L series format
|
||||
|
||||
NRF_RADIO->TXADDRESS = 0x00UL; // Set device address 0 to use when transmitting
|
||||
NRF_RADIO->RXADDRESSES = 0x01UL; // Enable device address 0 to use to select which addresses to receive
|
||||
|
||||
// Packet configuration
|
||||
NRF_RADIO->PCNF0 = (PACKET_S1_FIELD_SIZE << RADIO_PCNF0_S1LEN_Pos) |
|
||||
(PACKET_S0_FIELD_SIZE << RADIO_PCNF0_S0LEN_Pos) |
|
||||
(PACKET_LENGTH_FIELD_SIZE << RADIO_PCNF0_LFLEN_Pos); //lint !e845 "The right argument to operator '|' is certain to be 0"
|
||||
|
||||
// Packet configuration
|
||||
NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) |
|
||||
(RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) |
|
||||
(PACKET_BASE_ADDRESS_LENGTH << RADIO_PCNF1_BALEN_Pos) |
|
||||
(PACKET_STATIC_LENGTH << RADIO_PCNF1_STATLEN_Pos) |
|
||||
(PACKET_PAYLOAD_MAXSIZE << RADIO_PCNF1_MAXLEN_Pos); //lint !e845 "The right argument to operator '|' is certain to be 0"
|
||||
|
||||
// CRC Config
|
||||
NRF_RADIO->CRCCNF = (RADIO_CRCCNF_LEN_Two << RADIO_CRCCNF_LEN_Pos); // Number of checksum bits
|
||||
if ((NRF_RADIO->CRCCNF & RADIO_CRCCNF_LEN_Msk) == (RADIO_CRCCNF_LEN_Two << RADIO_CRCCNF_LEN_Pos))
|
||||
{
|
||||
NRF_RADIO->CRCINIT = 0xFFFFUL; // Initial value
|
||||
NRF_RADIO->CRCPOLY = 0x11021UL; // CRC poly: x^16 + x^12^x^5 + 1
|
||||
}
|
||||
else if ((NRF_RADIO->CRCCNF & RADIO_CRCCNF_LEN_Msk) == (RADIO_CRCCNF_LEN_One << RADIO_CRCCNF_LEN_Pos))
|
||||
{
|
||||
NRF_RADIO->CRCINIT = 0xFFUL; // Initial value
|
||||
NRF_RADIO->CRCPOLY = 0x107UL; // CRC poly: x^8 + x^2^x^1 + 1
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
58
components/drivers_nrf/radio_config/radio_config.h
Normal file
58
components/drivers_nrf/radio_config/radio_config.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright (c) 2009 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#ifndef RADIO_CONFIG_H
|
||||
#define RADIO_CONFIG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PACKET_BASE_ADDRESS_LENGTH (4UL) //!< Packet base address length field size in bytes
|
||||
#define PACKET_STATIC_LENGTH (1UL) //!< Packet static length in bytes
|
||||
#define PACKET_PAYLOAD_MAXSIZE (PACKET_STATIC_LENGTH) //!< Packet payload maximum size in bytes
|
||||
|
||||
void radio_configure(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
55
components/drivers_nrf/sdio/config/sdio_config.h
Normal file
55
components/drivers_nrf/sdio/config/sdio_config.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) 2012 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#ifndef SDIO_CONFIG_H
|
||||
#define SDIO_CONFIG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SDIO_CONFIG_CLOCK_PIN_NUMBER 24
|
||||
#define SDIO_CONFIG_DATA_PIN_NUMBER 25
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
244
components/drivers_nrf/sdio/sdio.c
Normal file
244
components/drivers_nrf/sdio/sdio.c
Normal file
@@ -0,0 +1,244 @@
|
||||
/**
|
||||
* Copyright (c) 2009 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
||||
#include "nrf.h"
|
||||
#include "nrf_delay.h"
|
||||
#include "sdio.h"
|
||||
#include "nrf_gpio.h"
|
||||
|
||||
#include "sdio_config.h"
|
||||
|
||||
/*lint ++flb "Enter library region" */
|
||||
|
||||
/*lint -e717 -save "Suppress do {} while (0) for these macros" */
|
||||
#define SDIO_CLOCK_HIGH() do { NRF_GPIO->OUTSET = (1UL << SDIO_CONFIG_CLOCK_PIN_NUMBER); } while (0) /*!< Pulls SCL line high */
|
||||
#define SDIO_CLOCK_LOW() do { NRF_GPIO->OUTCLR = (1UL << SDIO_CONFIG_CLOCK_PIN_NUMBER); } while (0) /*!< Pulls SCL line low */
|
||||
#define SDIO_DATA_HIGH() do { NRF_GPIO->OUTSET = (1UL << SDIO_CONFIG_DATA_PIN_NUMBER); } while (0) /*!< Pulls SDA line high */
|
||||
#define SDIO_DATA_LOW() do { NRF_GPIO->OUTCLR = (1UL << SDIO_CONFIG_DATA_PIN_NUMBER); } while (0) /*!< Pulls SDA line low */
|
||||
#define SDIO_DATA_OUTPUT() do { NRF_GPIO->DIRSET = (1UL << SDIO_CONFIG_DATA_PIN_NUMBER); } while (0) /*!< Configures SDA pin as output */
|
||||
#define SDIO_CLOCK_OUTPUT() do { NRF_GPIO->DIRSET = (1UL << SDIO_CONFIG_CLOCK_PIN_NUMBER); } while (0) /*!< Configures SCL pin as output */
|
||||
/*lint -restore */
|
||||
|
||||
/*lint -emacro(845,SDIO_DATA_INPUT) // A zero has been given as right argument to operator '|'" */
|
||||
|
||||
#define SDIO_DATA_INPUT() do { \
|
||||
nrf_gpio_cfg_input(25, NRF_GPIO_PIN_NOPULL); \
|
||||
} while (0)
|
||||
|
||||
#define SDIO_DATA_READ() ((NRF_GPIO->IN >> SDIO_CONFIG_DATA_PIN_NUMBER) & 0x1UL) /*!< Reads current state of SDA */
|
||||
#define SDIO_CLOCK_READ() ((NRF_GPIO->IN >> SDIO_CONFIG_CLOCK_PIN_NUMBER) & 0x1UL) /*!< Reads current state of SCL */
|
||||
#define SDIO_DELAY() nrf_delay_us(10) /*!< Time to wait when pin states are changed. For fast-mode the delay can be zero and for standard-mode 4 us delay is sufficient. */
|
||||
|
||||
void sdio_init(void)
|
||||
{
|
||||
SDIO_CLOCK_HIGH();
|
||||
SDIO_DATA_HIGH();
|
||||
SDIO_CLOCK_OUTPUT();
|
||||
SDIO_DATA_INPUT();
|
||||
|
||||
// If slave is stuck in the middle of transfer, clock out bits until the slave ACKs the transfer
|
||||
for (uint_fast8_t i = 16; i--;)
|
||||
{
|
||||
SDIO_DELAY();
|
||||
SDIO_CLOCK_LOW();
|
||||
SDIO_DELAY();
|
||||
SDIO_CLOCK_HIGH();
|
||||
SDIO_DELAY();
|
||||
|
||||
if (SDIO_DATA_READ())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint_fast8_t i = 5; i--;)
|
||||
{
|
||||
SDIO_DELAY();
|
||||
SDIO_CLOCK_LOW();
|
||||
SDIO_DELAY();
|
||||
SDIO_CLOCK_HIGH();
|
||||
}
|
||||
|
||||
SDIO_DATA_OUTPUT();
|
||||
SDIO_DATA_HIGH();
|
||||
|
||||
SDIO_DELAY();
|
||||
}
|
||||
|
||||
uint8_t sdio_read_byte(uint8_t address)
|
||||
{
|
||||
uint8_t data_byte = 0;
|
||||
|
||||
SDIO_DATA_OUTPUT();
|
||||
|
||||
for (uint_fast8_t i = 8; i--;)
|
||||
{
|
||||
SDIO_DELAY();
|
||||
|
||||
SDIO_CLOCK_LOW();
|
||||
|
||||
if (address & (1U << i))
|
||||
{
|
||||
SDIO_DATA_HIGH();
|
||||
}
|
||||
else
|
||||
{
|
||||
SDIO_DATA_LOW();
|
||||
}
|
||||
|
||||
SDIO_DELAY();
|
||||
|
||||
SDIO_CLOCK_HIGH();
|
||||
}
|
||||
|
||||
nrf_delay_us(20);
|
||||
|
||||
SDIO_DATA_INPUT();
|
||||
|
||||
for (uint_fast8_t i = 8; i--;)
|
||||
{
|
||||
SDIO_CLOCK_LOW();
|
||||
SDIO_DELAY();
|
||||
SDIO_CLOCK_HIGH();
|
||||
SDIO_DELAY();
|
||||
data_byte |= (uint8_t)(SDIO_DATA_READ() << i);
|
||||
}
|
||||
|
||||
SDIO_DATA_HIGH();
|
||||
SDIO_DATA_OUTPUT();
|
||||
|
||||
SDIO_DELAY();
|
||||
|
||||
return data_byte;
|
||||
}
|
||||
|
||||
void sdio_read_burst(uint8_t * target_buffer, uint8_t target_buffer_size)
|
||||
{
|
||||
uint_fast8_t address = 0x63;
|
||||
|
||||
SDIO_DATA_OUTPUT();
|
||||
|
||||
for (uint_fast8_t bit_index=8; bit_index--;)
|
||||
{
|
||||
SDIO_CLOCK_LOW();
|
||||
|
||||
if (address & (1U << bit_index))
|
||||
{
|
||||
SDIO_DATA_HIGH();
|
||||
}
|
||||
else
|
||||
{
|
||||
SDIO_DATA_LOW();
|
||||
}
|
||||
|
||||
SDIO_CLOCK_HIGH();
|
||||
}
|
||||
|
||||
SDIO_DATA_INPUT();
|
||||
|
||||
for (uint_fast8_t target_buffer_index = 0; target_buffer_index < target_buffer_size; target_buffer_index++)
|
||||
{
|
||||
target_buffer[target_buffer_index] = 0;
|
||||
|
||||
for (uint_fast8_t bit_index = 8; bit_index--;)
|
||||
{
|
||||
SDIO_CLOCK_LOW();
|
||||
SDIO_CLOCK_HIGH();
|
||||
target_buffer[target_buffer_index] |= (uint8_t)(SDIO_DATA_READ() << bit_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sdio_write_byte(uint8_t address, uint8_t data_byte)
|
||||
{
|
||||
// Add write indication bit
|
||||
address |= 0x80;
|
||||
|
||||
SDIO_DATA_OUTPUT();
|
||||
|
||||
for (uint_fast8_t i = 8; i--;)
|
||||
{
|
||||
SDIO_DELAY();
|
||||
|
||||
SDIO_CLOCK_LOW();
|
||||
|
||||
if (address & (1U << i))
|
||||
{
|
||||
SDIO_DATA_HIGH();
|
||||
}
|
||||
else
|
||||
{
|
||||
SDIO_DATA_LOW();
|
||||
}
|
||||
|
||||
SDIO_DELAY();
|
||||
|
||||
SDIO_CLOCK_HIGH();
|
||||
}
|
||||
|
||||
SDIO_DELAY();
|
||||
|
||||
for (uint_fast8_t i = 8; i--;)
|
||||
{
|
||||
SDIO_CLOCK_LOW();
|
||||
|
||||
if (data_byte & (1U << i))
|
||||
{
|
||||
SDIO_DATA_HIGH();
|
||||
}
|
||||
else
|
||||
{
|
||||
SDIO_DATA_LOW();
|
||||
}
|
||||
|
||||
SDIO_DELAY();
|
||||
|
||||
SDIO_CLOCK_HIGH();
|
||||
|
||||
SDIO_DELAY();
|
||||
}
|
||||
|
||||
SDIO_DATA_HIGH();
|
||||
|
||||
SDIO_DELAY();
|
||||
}
|
||||
|
||||
/*lint --flb "Leave library region" */
|
||||
105
components/drivers_nrf/sdio/sdio.h
Normal file
105
components/drivers_nrf/sdio/sdio.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Copyright (c) 2009 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#ifndef SDIO_H
|
||||
#define SDIO_H
|
||||
|
||||
/*lint ++flb "Enter library region" */
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @file
|
||||
* @brief 2-wire serial interface driver (compatible with ADNS2080 mouse sensor driver)
|
||||
*
|
||||
*
|
||||
* @defgroup nrf_drivers_sdio SDIO driver
|
||||
* @{
|
||||
* @ingroup nrf_drivers
|
||||
* @brief 2-wire serial interface driver.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Function for initializing 2-wire serial interface and trying to handle stuck slaves.
|
||||
*
|
||||
*/
|
||||
void sdio_init(void);
|
||||
|
||||
/**
|
||||
* @brief Function for reading a byte over 2-wire serial interface.
|
||||
*
|
||||
* Developer needs to implement this function in a way that suits the hardware.
|
||||
* @param address Register address to read from
|
||||
* @return Byte read
|
||||
*/
|
||||
uint8_t sdio_read_byte(uint8_t address);
|
||||
|
||||
/**
|
||||
* @brief Function for reading several bytes over 2-wire serial interface using burst mode.
|
||||
*
|
||||
* Developer needs to implement this function in a way that suits the hardware.
|
||||
* @param target_buffer Buffer location to store read bytes to
|
||||
* @param target_buffer_size Bytes allocated for target_buffer
|
||||
*/
|
||||
void sdio_read_burst(uint8_t *target_buffer, uint8_t target_buffer_size);
|
||||
|
||||
/**
|
||||
* @brief Function for writing a byte over 2-wire serial interface.
|
||||
*
|
||||
* Developer needs to implement this function in a way that suits the hardware.
|
||||
* @param address Register address to write to
|
||||
* @param data_byte Data byte to write
|
||||
*/
|
||||
void sdio_write_byte(uint8_t address, uint8_t data_byte);
|
||||
|
||||
/**
|
||||
*@}
|
||||
**/
|
||||
|
||||
/*lint --flb "Leave library region" */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
629
components/drivers_nrf/spi_master/spi_5W_master.c
Normal file
629
components/drivers_nrf/spi_master/spi_5W_master.c
Normal file
@@ -0,0 +1,629 @@
|
||||
/**
|
||||
* Copyright (c) 2014 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/**@file
|
||||
*
|
||||
* @defgroup ser_phy_spi_5W_hw_driver_master spi_5W_master.c
|
||||
* @{
|
||||
* @ingroup ser_phy_spi_5W_hw_driver_master
|
||||
*
|
||||
* @brief SPI_5W_RAW hardware driver.
|
||||
*/
|
||||
|
||||
#include "app_error.h"
|
||||
#include "app_util_platform.h"
|
||||
#include "nrf_gpio.h"
|
||||
#include "nrf.h"
|
||||
#include "spi_5W_master.h"
|
||||
#include "ser_config_5W_app.h"
|
||||
#include "ser_phy_debug_app.h"
|
||||
#include "sdk_common.h"
|
||||
|
||||
|
||||
#define _static
|
||||
|
||||
#define DOUBLE_BUFFERED /**< A flag for enabling double buffering. */
|
||||
|
||||
#define SPI_PIN_DISCONNECTED 0xFFFFFFFF /**< A value used to the PIN deinitialization. */
|
||||
#define SPI_DEFAULT_TX_BYTE 0x00 /**< Default byte (used to clock transmission
|
||||
from slave to the master) */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NRF_SPI_Type * p_nrf_spi; /**< A pointer to the NRF SPI master */
|
||||
IRQn_Type irq_type; /**< A type of NVIC IRQn */
|
||||
|
||||
uint8_t * p_tx_buffer; /**< A pointer to TX buffer. */
|
||||
uint16_t tx_length; /**< A length of TX buffer. */
|
||||
uint16_t tx_index; /**< A index of the current element in the TX buffer. */
|
||||
|
||||
uint8_t * p_rx_buffer; /**< A pointer to RX buffer. */
|
||||
uint16_t rx_length; /**< A length RX buffer. */
|
||||
uint16_t rx_index; /**< A index of the current element in the RX buffer. */
|
||||
|
||||
uint16_t max_length; /**< Max length (Max of the TX and RX length). */
|
||||
uint16_t bytes_count;
|
||||
uint8_t pin_slave_select; /**< A pin for Slave Select. */
|
||||
|
||||
spi_master_event_handler_t callback_event_handler; /**< A handler for event callback function. */
|
||||
spi_master_state_t state; /**< A state of an instance of SPI master. */
|
||||
bool start_flag;
|
||||
bool abort_flag;
|
||||
|
||||
} spi_master_instance_t;
|
||||
|
||||
#ifdef _SPI_5W_
|
||||
typedef enum
|
||||
{
|
||||
HOOK_STATE_DISABLED,
|
||||
HOOK_STATE_IDLE,
|
||||
HOOK_STATE_GUARDED,
|
||||
HOOK_STATE_ABORTED,
|
||||
HOOK_STATE_RESTARTED,
|
||||
HOOK_STATE_PASSING
|
||||
} spi_hook_state_t;
|
||||
|
||||
|
||||
_static spi_master_event_handler_t m_ser_phy_event_handler;
|
||||
_static spi_master_hw_instance_t m_spi_master_hw_instance;
|
||||
_static spi_hook_state_t m_hook_state = HOOK_STATE_DISABLED;
|
||||
#endif
|
||||
|
||||
#ifdef SER_PHY_DEBUG_APP_ENABLE
|
||||
_static spi_master_raw_callback_t m_debug_callback;
|
||||
#endif
|
||||
|
||||
_static spi_master_instance_t m_spi_master_instances[SPI_MASTER_HW_ENABLED_COUNT];
|
||||
|
||||
static __INLINE spi_master_instance_t * spi_master_get_instance(
|
||||
const spi_master_hw_instance_t spi_master_hw_instance);
|
||||
static __INLINE void spi_master_send_recv_irq(spi_master_instance_t * const p_spi_instance);
|
||||
static __INLINE void spi_master_signal_evt(spi_master_instance_t * const p_spi_instance,
|
||||
spi_master_evt_type_t event_type,
|
||||
const uint16_t data);
|
||||
|
||||
#ifdef SPI_MASTER_0_ENABLE
|
||||
/**
|
||||
* @brief SPI0 interrupt handler.
|
||||
*/
|
||||
void SPI0_TWI0_IRQHandler(void)
|
||||
{
|
||||
if (NRF_SPI0->EVENTS_READY != 0)
|
||||
{
|
||||
NRF_SPI0->EVENTS_READY = 0;
|
||||
|
||||
spi_master_instance_t * p_spi_instance = spi_master_get_instance(SPI_MASTER_0);
|
||||
|
||||
spi_master_send_recv_irq(p_spi_instance);
|
||||
}
|
||||
}
|
||||
#endif //SPI_MASTER_0_ENABLE
|
||||
|
||||
#ifdef SPI_MASTER_1_ENABLE
|
||||
/**
|
||||
* @brief SPI0 interrupt handler.
|
||||
*/
|
||||
void SPI1_TWI1_IRQHandler(void)
|
||||
{
|
||||
if (NRF_SPI1->EVENTS_READY != 0)
|
||||
{
|
||||
NRF_SPI1->EVENTS_READY = 0;
|
||||
|
||||
spi_master_instance_t * p_spi_instance = spi_master_get_instance(SPI_MASTER_1);
|
||||
|
||||
spi_master_send_recv_irq(p_spi_instance);
|
||||
}
|
||||
}
|
||||
#endif //SPI_MASTER_1_ENABLE
|
||||
|
||||
#if defined(SPI_MASTER_0_ENABLE) || defined(SPI_MASTER_1_ENABLE)
|
||||
|
||||
/**@brief Function for getting an instance of SPI master. */
|
||||
static __INLINE spi_master_instance_t * spi_master_get_instance(
|
||||
const spi_master_hw_instance_t spi_master_hw_instance)
|
||||
{
|
||||
return &(m_spi_master_instances[(uint8_t)spi_master_hw_instance]);
|
||||
}
|
||||
|
||||
/** @brief Function for initializing instance of SPI master by default values. */
|
||||
static __INLINE void spi_master_init_hw_instance(NRF_SPI_Type * p_nrf_spi,
|
||||
IRQn_Type irq_type,
|
||||
spi_master_instance_t * p_spi_instance)
|
||||
{
|
||||
APP_ERROR_CHECK_BOOL(p_spi_instance != NULL);
|
||||
|
||||
p_spi_instance->p_nrf_spi = p_nrf_spi;
|
||||
p_spi_instance->irq_type = irq_type;
|
||||
|
||||
p_spi_instance->p_tx_buffer = NULL;
|
||||
p_spi_instance->tx_length = 0;
|
||||
p_spi_instance->tx_index = 0;
|
||||
|
||||
p_spi_instance->p_rx_buffer = NULL;
|
||||
p_spi_instance->rx_length = 0;
|
||||
p_spi_instance->rx_index = 0;
|
||||
|
||||
p_spi_instance->bytes_count = 0;
|
||||
p_spi_instance->max_length = 0;
|
||||
p_spi_instance->pin_slave_select = 0;
|
||||
|
||||
p_spi_instance->callback_event_handler = NULL;
|
||||
|
||||
p_spi_instance->state = SPI_MASTER_STATE_DISABLED;
|
||||
p_spi_instance->abort_flag = false;
|
||||
p_spi_instance->start_flag = false;
|
||||
}
|
||||
|
||||
/**@brief Function for initializing TX or RX buffer. */
|
||||
static __INLINE void spi_master_buffer_init(uint8_t * const p_buf,
|
||||
const uint16_t buf_len,
|
||||
uint8_t * * pp_buf,
|
||||
uint16_t * const p_buf_len,
|
||||
uint16_t * const p_index)
|
||||
{
|
||||
APP_ERROR_CHECK_BOOL(pp_buf != NULL);
|
||||
APP_ERROR_CHECK_BOOL(p_buf_len != NULL);
|
||||
APP_ERROR_CHECK_BOOL(p_index != NULL);
|
||||
|
||||
*pp_buf = p_buf;
|
||||
*p_buf_len = (p_buf != NULL) ? buf_len : 0;
|
||||
*p_index = 0;
|
||||
}
|
||||
|
||||
/**@brief Function for releasing TX or RX buffer. */
|
||||
static __INLINE void spi_master_buffer_release(uint8_t * * const pp_buf, uint16_t * const p_buf_len)
|
||||
{
|
||||
APP_ERROR_CHECK_BOOL(pp_buf != NULL);
|
||||
APP_ERROR_CHECK_BOOL(p_buf_len != NULL);
|
||||
|
||||
*pp_buf = NULL;
|
||||
*p_buf_len = 0;
|
||||
}
|
||||
|
||||
/**@brief Function for sending events by callback. */
|
||||
static __INLINE void spi_master_signal_evt(spi_master_instance_t * const p_spi_instance,
|
||||
spi_master_evt_type_t event_type,
|
||||
const uint16_t data)
|
||||
{
|
||||
APP_ERROR_CHECK_BOOL(p_spi_instance != NULL);
|
||||
|
||||
if (p_spi_instance->callback_event_handler != NULL)
|
||||
{
|
||||
spi_master_evt_t event = {SPI_MASTER_EVT_TYPE_MAX, 0};
|
||||
event.type = event_type;
|
||||
event.data = data;
|
||||
p_spi_instance->callback_event_handler(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**@brief Function insert to a TX buffer another byte or two bytes (depends on flag @ref DOUBLE_BUFFERED). */
|
||||
static __INLINE void spi_master_send_initial_bytes(spi_master_instance_t * const p_spi_instance)
|
||||
{
|
||||
APP_ERROR_CHECK_BOOL(p_spi_instance != NULL);
|
||||
|
||||
p_spi_instance->p_nrf_spi->TXD = ((p_spi_instance->p_tx_buffer != NULL) &&
|
||||
(p_spi_instance->tx_index < p_spi_instance->tx_length)) ?
|
||||
p_spi_instance->p_tx_buffer[p_spi_instance->tx_index] :
|
||||
SPI_DEFAULT_TX_BYTE;
|
||||
(p_spi_instance->tx_index)++;
|
||||
|
||||
#ifdef DOUBLE_BUFFERED
|
||||
|
||||
if (p_spi_instance->tx_index < p_spi_instance->max_length)
|
||||
{
|
||||
p_spi_instance->p_nrf_spi->TXD = ((p_spi_instance->p_tx_buffer != NULL) &&
|
||||
(p_spi_instance->tx_index < p_spi_instance->tx_length)) ?
|
||||
p_spi_instance->p_tx_buffer[p_spi_instance->tx_index] :
|
||||
SPI_DEFAULT_TX_BYTE;
|
||||
(p_spi_instance->tx_index)++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**@brief Function for receiving and sending data from IRQ. (The same for both IRQs). */
|
||||
static __INLINE void spi_master_send_recv_irq(spi_master_instance_t * const p_spi_instance)
|
||||
{
|
||||
|
||||
uint8_t rx_byte;
|
||||
|
||||
APP_ERROR_CHECK_BOOL(p_spi_instance != NULL);
|
||||
APP_ERROR_CHECK_BOOL(p_spi_instance->state == SPI_MASTER_STATE_BUSY);
|
||||
|
||||
p_spi_instance->bytes_count++;
|
||||
rx_byte = p_spi_instance->p_nrf_spi->RXD;
|
||||
|
||||
if (p_spi_instance->start_flag)
|
||||
{
|
||||
p_spi_instance->start_flag = false;
|
||||
spi_master_signal_evt(p_spi_instance, SPI_MASTER_EVT_FIRST_BYTE_RECEIVED, (uint16_t)rx_byte);
|
||||
}
|
||||
else if (p_spi_instance->abort_flag ) //this is tricky, but callback for SPI_MASTER_EVT_FIRST_BYTE_RECEIVED will set this flag for a first byte, which is bad because there is still byte in a buffer
|
||||
{ //and for a single byte transaction you will get XFERDONE event to restart
|
||||
p_spi_instance->abort_flag = false;
|
||||
p_spi_instance->state = SPI_MASTER_STATE_ABORTED;
|
||||
nrf_gpio_pin_set(p_spi_instance->pin_slave_select);
|
||||
spi_master_signal_evt(p_spi_instance, SPI_MASTER_EVT_TRANSFER_ABORTED, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((p_spi_instance->p_rx_buffer != NULL) &&
|
||||
(p_spi_instance->rx_index < p_spi_instance->rx_length))
|
||||
{
|
||||
p_spi_instance->p_rx_buffer[p_spi_instance->rx_index++] = rx_byte;
|
||||
}
|
||||
|
||||
if ((p_spi_instance->tx_index < p_spi_instance->max_length) && (!(p_spi_instance->abort_flag))) //do not TX if you know that there is an abort to be done - this should work for a DOUBLE BUFFERING ???
|
||||
{
|
||||
p_spi_instance->p_nrf_spi->TXD = ((p_spi_instance->p_tx_buffer != NULL) &&
|
||||
(p_spi_instance->tx_index < p_spi_instance->tx_length)) ?
|
||||
p_spi_instance->p_tx_buffer[p_spi_instance->tx_index] :
|
||||
SPI_DEFAULT_TX_BYTE;
|
||||
(p_spi_instance->tx_index)++;
|
||||
}
|
||||
|
||||
if (p_spi_instance->bytes_count >= p_spi_instance->max_length)
|
||||
{
|
||||
APP_ERROR_CHECK_BOOL(p_spi_instance->bytes_count == p_spi_instance->max_length);
|
||||
nrf_gpio_pin_set(p_spi_instance->pin_slave_select);
|
||||
p_spi_instance->state = SPI_MASTER_STATE_IDLE;
|
||||
spi_master_signal_evt(p_spi_instance,
|
||||
SPI_MASTER_EVT_TRANSFER_COMPLETED,
|
||||
p_spi_instance->tx_index);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif //defined(SPI_MASTER_0_ENABLE) || defined(SPI_MASTER_1_ENABLE)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Function for opening and initializing a SPI master driver. */
|
||||
uint32_t spi_master_open(const spi_master_hw_instance_t spi_master_hw_instance,
|
||||
spi_master_config_t const * const p_spi_master_config)
|
||||
{
|
||||
#if defined(SPI_MASTER_0_ENABLE) || defined(SPI_MASTER_1_ENABLE)
|
||||
|
||||
|
||||
VERIFY_PARAM_NOT_NULL(p_spi_master_config);
|
||||
|
||||
spi_master_instance_t * p_spi_instance = spi_master_get_instance(spi_master_hw_instance);
|
||||
|
||||
switch (spi_master_hw_instance)
|
||||
{
|
||||
#ifdef SPI_MASTER_0_ENABLE
|
||||
case SPI_MASTER_0:
|
||||
spi_master_init_hw_instance(NRF_SPI0, SPI0_TWI0_IRQn, p_spi_instance);
|
||||
break;
|
||||
#endif //SPI_MASTER_0_ENABLE
|
||||
|
||||
#ifdef SPI_MASTER_1_ENABLE
|
||||
case SPI_MASTER_1:
|
||||
spi_master_init_hw_instance(NRF_SPI1, SPI1_TWI1_IRQn, p_spi_instance);
|
||||
break;
|
||||
#endif //SPI_MASTER_1_ENABLE
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//A Slave select must be set as high before setting it as output,
|
||||
//because during connect it to the pin it causes glitches.
|
||||
nrf_gpio_pin_set(p_spi_master_config->SPI_Pin_SS);
|
||||
nrf_gpio_cfg_output(p_spi_master_config->SPI_Pin_SS);
|
||||
nrf_gpio_pin_set(p_spi_master_config->SPI_Pin_SS);
|
||||
|
||||
//Configure GPIO
|
||||
nrf_gpio_cfg_output(p_spi_master_config->SPI_Pin_SCK);
|
||||
nrf_gpio_cfg_output(p_spi_master_config->SPI_Pin_MOSI);
|
||||
nrf_gpio_cfg_input(p_spi_master_config->SPI_Pin_MISO, NRF_GPIO_PIN_NOPULL);
|
||||
p_spi_instance->pin_slave_select = p_spi_master_config->SPI_Pin_SS;
|
||||
|
||||
/* Configure SPI hardware */
|
||||
p_spi_instance->p_nrf_spi->PSELSCK = p_spi_master_config->SPI_Pin_SCK;
|
||||
p_spi_instance->p_nrf_spi->PSELMOSI = p_spi_master_config->SPI_Pin_MOSI;
|
||||
p_spi_instance->p_nrf_spi->PSELMISO = p_spi_master_config->SPI_Pin_MISO;
|
||||
|
||||
p_spi_instance->p_nrf_spi->FREQUENCY = p_spi_master_config->SPI_Freq;
|
||||
|
||||
p_spi_instance->p_nrf_spi->CONFIG =
|
||||
(uint32_t)(p_spi_master_config->SPI_CPHA << SPI_CONFIG_CPHA_Pos) |
|
||||
(p_spi_master_config->SPI_CPOL << SPI_CONFIG_CPOL_Pos) |
|
||||
(p_spi_master_config->SPI_ORDER << SPI_CONFIG_ORDER_Pos);
|
||||
|
||||
|
||||
/* Clear waiting interrupts and events */
|
||||
p_spi_instance->p_nrf_spi->EVENTS_READY = 0;
|
||||
|
||||
NVIC_ClearPendingIRQ(p_spi_instance->irq_type);
|
||||
NVIC_SetPriority(p_spi_instance->irq_type, APP_IRQ_PRIORITY_MID);
|
||||
|
||||
/* Clear event handler */
|
||||
p_spi_instance->callback_event_handler = NULL;
|
||||
|
||||
/* Enable interrupt */
|
||||
p_spi_instance->p_nrf_spi->INTENSET = (SPI_INTENSET_READY_Set << SPI_INTENCLR_READY_Pos);
|
||||
NVIC_EnableIRQ(p_spi_instance->irq_type);
|
||||
|
||||
/* Enable SPI hardware */
|
||||
p_spi_instance->p_nrf_spi->ENABLE = (SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos);
|
||||
|
||||
/* Change state to IDLE */
|
||||
p_spi_instance->state = SPI_MASTER_STATE_IDLE;
|
||||
|
||||
return NRF_SUCCESS;
|
||||
#else
|
||||
return NRF_ERROR_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for closing a SPI master driver.
|
||||
*/
|
||||
void spi_master_close(const spi_master_hw_instance_t spi_master_hw_instance)
|
||||
{
|
||||
#if defined(SPI_MASTER_0_ENABLE) || defined(SPI_MASTER_1_ENABLE)
|
||||
spi_master_instance_t * p_spi_instance = spi_master_get_instance(spi_master_hw_instance);
|
||||
|
||||
/* Disable interrupt */
|
||||
NVIC_ClearPendingIRQ(p_spi_instance->irq_type);
|
||||
NVIC_DisableIRQ(p_spi_instance->irq_type);
|
||||
|
||||
p_spi_instance->p_nrf_spi->ENABLE = (SPI_ENABLE_ENABLE_Disabled << SPI_ENABLE_ENABLE_Pos);
|
||||
|
||||
/* Set Slave Select pin as input with pull-up. */
|
||||
nrf_gpio_pin_set(p_spi_instance->pin_slave_select);
|
||||
nrf_gpio_cfg_input(p_spi_instance->pin_slave_select, NRF_GPIO_PIN_PULLUP);
|
||||
p_spi_instance->pin_slave_select = (uint8_t)0xFF;
|
||||
|
||||
/* Disconnect pins from SPI hardware */
|
||||
p_spi_instance->p_nrf_spi->PSELSCK = (uint32_t)SPI_PIN_DISCONNECTED;
|
||||
p_spi_instance->p_nrf_spi->PSELMOSI = (uint32_t)SPI_PIN_DISCONNECTED;
|
||||
p_spi_instance->p_nrf_spi->PSELMISO = (uint32_t)SPI_PIN_DISCONNECTED;
|
||||
|
||||
/* Reset to default values */
|
||||
spi_master_init_hw_instance(NULL, (IRQn_Type)0, p_spi_instance);
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for getting current state of the SPI master driver.
|
||||
*/
|
||||
__INLINE spi_master_state_t spi_master_get_state(
|
||||
const spi_master_hw_instance_t spi_master_hw_instance)
|
||||
{
|
||||
#if defined(SPI_MASTER_0_ENABLE) || defined(SPI_MASTER_1_ENABLE)
|
||||
spi_master_instance_t * spi_instance = spi_master_get_instance(spi_master_hw_instance);
|
||||
return spi_instance->state;
|
||||
#else
|
||||
return SPI_MASTER_STATE_DISABLED;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for event handler registration.
|
||||
*/
|
||||
__INLINE void spi_master_evt_handler_reg(const spi_master_hw_instance_t spi_master_hw_instance,
|
||||
spi_master_event_handler_t event_handler)
|
||||
{
|
||||
#if defined(SPI_MASTER_0_ENABLE) || defined(SPI_MASTER_1_ENABLE)
|
||||
spi_master_instance_t * spi_instance = spi_master_get_instance(spi_master_hw_instance);
|
||||
spi_instance->callback_event_handler = event_handler;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for transmitting data between SPI master and SPI slave.
|
||||
*/
|
||||
uint32_t spi_master_send_recv(const spi_master_hw_instance_t spi_master_hw_instance,
|
||||
uint8_t * const p_tx_buf, const uint16_t tx_buf_len,
|
||||
uint8_t * const p_rx_buf, const uint16_t rx_buf_len)
|
||||
{
|
||||
#if defined(SPI_MASTER_0_ENABLE) || defined(SPI_MASTER_1_ENABLE)
|
||||
spi_master_instance_t * p_spi_instance = spi_master_get_instance(spi_master_hw_instance);
|
||||
|
||||
uint32_t err_code = NRF_SUCCESS;
|
||||
uint16_t max_length = 0;
|
||||
|
||||
if (p_spi_instance->state == SPI_MASTER_STATE_IDLE)
|
||||
{
|
||||
NVIC_DisableIRQ(p_spi_instance->irq_type);
|
||||
|
||||
max_length = (rx_buf_len > tx_buf_len) ? rx_buf_len : tx_buf_len;
|
||||
|
||||
if (max_length > 0)
|
||||
{
|
||||
p_spi_instance->state = SPI_MASTER_STATE_BUSY;
|
||||
p_spi_instance->start_flag = true; //abort_flag should set by abort and cleared only by restart
|
||||
p_spi_instance->bytes_count = 0;
|
||||
p_spi_instance->max_length = max_length;
|
||||
spi_master_buffer_release(&(p_spi_instance->p_tx_buffer), &(p_spi_instance->tx_length));
|
||||
spi_master_buffer_release(&(p_spi_instance->p_rx_buffer), &(p_spi_instance->rx_length));
|
||||
/* Initialize buffers */
|
||||
spi_master_buffer_init(p_tx_buf, tx_buf_len, &(p_spi_instance->p_tx_buffer),
|
||||
&(p_spi_instance->tx_length), &(p_spi_instance->tx_index));
|
||||
spi_master_buffer_init(p_rx_buf, rx_buf_len, &(p_spi_instance->p_rx_buffer),
|
||||
&(p_spi_instance->rx_length), &(p_spi_instance->rx_index));
|
||||
nrf_gpio_pin_clear(p_spi_instance->pin_slave_select);
|
||||
spi_master_send_initial_bytes(p_spi_instance);
|
||||
spi_master_signal_evt(p_spi_instance, SPI_MASTER_EVT_TRANSFER_STARTED, max_length);
|
||||
}
|
||||
else
|
||||
{
|
||||
err_code = NRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
NVIC_EnableIRQ(p_spi_instance->irq_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
err_code = NRF_ERROR_BUSY;
|
||||
}
|
||||
|
||||
return err_code;
|
||||
#else
|
||||
return NRF_ERROR_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _SPI_5W_
|
||||
|
||||
/**
|
||||
* @brief Function for aborting transfer
|
||||
*/
|
||||
uint32_t spi_master_abort(const spi_master_hw_instance_t spi_master_hw_instance)
|
||||
{
|
||||
spi_master_instance_t * p_spi_instance = spi_master_get_instance(spi_master_hw_instance);
|
||||
|
||||
NVIC_DisableIRQ(p_spi_instance->irq_type);
|
||||
|
||||
if (p_spi_instance->state == SPI_MASTER_STATE_BUSY)
|
||||
{
|
||||
//set_flag - but only when there are events pending
|
||||
//ignore when in IDLE - must be able to restart a completed transfer
|
||||
p_spi_instance->abort_flag = true;
|
||||
}
|
||||
NVIC_EnableIRQ(p_spi_instance->irq_type);
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for restarting transfer
|
||||
*/
|
||||
uint32_t spi_master_restart(const spi_master_hw_instance_t spi_master_hw_instance)
|
||||
{
|
||||
spi_master_instance_t * p_spi_instance = spi_master_get_instance(spi_master_hw_instance);
|
||||
|
||||
NVIC_DisableIRQ(p_spi_instance->irq_type);
|
||||
spi_master_signal_evt(p_spi_instance, SPI_MASTER_EVT_TRANSFER_RESTARTED, 0);
|
||||
p_spi_instance->state = SPI_MASTER_STATE_BUSY;
|
||||
p_spi_instance->bytes_count = 0;
|
||||
p_spi_instance->tx_index = 0;
|
||||
p_spi_instance->rx_index = 0;
|
||||
p_spi_instance->start_flag = true;
|
||||
p_spi_instance->abort_flag = false; //you should force clearing abort flag - no other way for 1 byte transfer
|
||||
nrf_gpio_pin_clear(p_spi_instance->pin_slave_select);
|
||||
spi_master_send_initial_bytes(p_spi_instance);
|
||||
NVIC_EnableIRQ(p_spi_instance->irq_type);
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
static void spi_5W_master_event_handler(spi_master_evt_t evt)
|
||||
{
|
||||
|
||||
switch (m_hook_state)
|
||||
{
|
||||
case HOOK_STATE_IDLE:
|
||||
|
||||
if (evt.type == SPI_MASTER_EVT_TRANSFER_STARTED)
|
||||
{
|
||||
DEBUG_EVT_SPI_MASTER_RAW_XFER_GUARDED(0);
|
||||
m_hook_state = HOOK_STATE_GUARDED;
|
||||
m_ser_phy_event_handler(evt);
|
||||
}
|
||||
break;
|
||||
|
||||
case HOOK_STATE_GUARDED:
|
||||
|
||||
if (evt.type == SPI_MASTER_EVT_FIRST_BYTE_RECEIVED)
|
||||
{
|
||||
if (evt.data == 0)
|
||||
{
|
||||
DEBUG_EVT_SPI_MASTER_RAW_XFER_PASSED(0);
|
||||
m_hook_state = HOOK_STATE_PASSING;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_EVT_SPI_MASTER_RAW_XFER_ABORTED(0);
|
||||
m_hook_state = HOOK_STATE_ABORTED;
|
||||
(void)spi_master_abort(m_spi_master_hw_instance);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case HOOK_STATE_ABORTED:
|
||||
|
||||
if ((evt.type == SPI_MASTER_EVT_TRANSFER_ABORTED) ||
|
||||
(evt.type == SPI_MASTER_EVT_TRANSFER_COMPLETED))
|
||||
{
|
||||
DEBUG_EVT_SPI_MASTER_RAW_XFER_RESTARTED(0);
|
||||
m_hook_state = HOOK_STATE_RESTARTED;
|
||||
(void)spi_master_restart(m_spi_master_hw_instance);
|
||||
}
|
||||
break;
|
||||
|
||||
case HOOK_STATE_RESTARTED:
|
||||
|
||||
if (evt.type == SPI_MASTER_EVT_TRANSFER_RESTARTED)
|
||||
{
|
||||
DEBUG_EVT_SPI_MASTER_RAW_XFER_GUARDED(0);
|
||||
m_hook_state = HOOK_STATE_GUARDED;
|
||||
}
|
||||
break;
|
||||
|
||||
case HOOK_STATE_PASSING:
|
||||
|
||||
if (evt.type == SPI_MASTER_EVT_TRANSFER_COMPLETED)
|
||||
{
|
||||
m_hook_state = HOOK_STATE_IDLE;
|
||||
m_ser_phy_event_handler(evt); //this is the only way to get a signal from complete transaction
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void spi_5W_master_evt_handler_reg(const spi_master_hw_instance_t spi_master_hw_instance,
|
||||
spi_master_event_handler_t event_handler)
|
||||
{
|
||||
m_ser_phy_event_handler = event_handler;
|
||||
m_spi_master_hw_instance = spi_master_hw_instance;
|
||||
m_hook_state = HOOK_STATE_IDLE;
|
||||
spi_master_evt_handler_reg(spi_master_hw_instance, spi_5W_master_event_handler);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
206
components/drivers_nrf/spi_master/spi_5W_master.h
Normal file
206
components/drivers_nrf/spi_master/spi_5W_master.h
Normal file
@@ -0,0 +1,206 @@
|
||||
/**
|
||||
* Copyright (c) 2014 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#ifndef APP_SPI_MASTER_H
|
||||
#define APP_SPI_MASTER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "boards.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define _SPI_5W_
|
||||
|
||||
/**@brief Struct containing configuration parameters of the SPI master. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t SPI_Freq; /**< SPI frequency. */
|
||||
uint32_t SPI_Pin_SCK; /**< SCK pin number. */
|
||||
uint32_t SPI_Pin_MISO; /**< MISO pin number. */
|
||||
uint32_t SPI_Pin_MOSI; /**< MOSI pin number .*/
|
||||
uint32_t SPI_Pin_SS; /**< Slave select pin number. */
|
||||
uint8_t SPI_ORDER; /**< Bytes order MSBFIRST or LSBFIRST. */
|
||||
uint8_t SPI_CPOL; /**< Serial clock polarity ACTIVEHIGH or ACTIVELOW. */
|
||||
uint8_t SPI_CPHA; /**< Serial clock phase LEADING or TRAILING. */
|
||||
} spi_master_config_t;
|
||||
|
||||
/**@brief SPI master driver events types. */
|
||||
typedef enum
|
||||
{
|
||||
SPI_MASTER_EVT_TRANSFER_STARTED = 0, /**< An event indicating that transfer has been started */
|
||||
SPI_MASTER_EVT_TRANSFER_COMPLETED, /**< An event indicating that transfer has been completed */
|
||||
SPI_MASTER_EVT_TRANSFER_ABORTED, /**< An event indicating that transfer has been aborted */
|
||||
SPI_MASTER_EVT_TRANSFER_RESTARTED, /**< An event indicating that transfer has been resumed */
|
||||
SPI_MASTER_EVT_FIRST_BYTE_RECEIVED, /**< An event indicating end of one byte transfer */
|
||||
SPI_MASTER_EVT_TYPE_MAX /**< Enumeration upper bound. */
|
||||
} spi_master_evt_type_t;
|
||||
|
||||
/**@brief Struct containing parameters of the SPI MASTER event */
|
||||
typedef struct
|
||||
{
|
||||
spi_master_evt_type_t type; /**< Type of an event */
|
||||
uint16_t data; /**< event data - context dependent */
|
||||
} spi_master_evt_t;
|
||||
|
||||
/**@brief SPI MASTER internal states types. */
|
||||
typedef enum
|
||||
{
|
||||
SPI_MASTER_STATE_DISABLED, /**< A state indicating that SPI master is disabled. */
|
||||
SPI_MASTER_STATE_BUSY, /**< A state indicating that SPI master is sending now. */
|
||||
SPI_MASTER_STATE_ABORTED,
|
||||
SPI_MASTER_STATE_IDLE /**< A state indicating that SPI master is idle now. */
|
||||
} spi_master_state_t;
|
||||
|
||||
/**@brief Instances of SPI master module. */
|
||||
typedef enum
|
||||
{
|
||||
#ifdef SPI_MASTER_0_ENABLE
|
||||
SPI_MASTER_0, /**< A instance of SPI master 0. */
|
||||
#endif
|
||||
|
||||
#ifdef SPI_MASTER_1_ENABLE
|
||||
SPI_MASTER_1, /**< A instance of SPI master 1. */
|
||||
#endif
|
||||
|
||||
SPI_MASTER_HW_ENABLED_COUNT /**< A number of enabled instances of SPI master. */
|
||||
} spi_master_hw_instance_t;
|
||||
|
||||
/**@brief Type of generic callback function handler to be used by all SPI MASTER driver events.
|
||||
*
|
||||
* @param[in] spi_master_evt SPI MASTER driver event.
|
||||
*/
|
||||
typedef void (*spi_master_event_handler_t) (spi_master_evt_t spi_master_evt);
|
||||
|
||||
|
||||
/**@brief Function for opening and initializing a SPI master driver.
|
||||
*
|
||||
* @note Function initializes SPI master hardware and internal module states, unregister events callback.
|
||||
*
|
||||
* @warning If the function has been already called, the function @ref spi_master_close has to be
|
||||
* called before spi_master_open can be called again.
|
||||
*
|
||||
* @param[in] spi_master_hw_instance Instance of SPI master module.
|
||||
* @param[in] p_spi_master_config Pointer to configuration structure which will be used
|
||||
* to initialize SPI MASTER hardware.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
* @retval NRF_ERROR_INVALID_STATE Operation failure. The function has been already called.
|
||||
* To call it again the function @ref spi_master_close
|
||||
* has to be called previously.
|
||||
* @retval NRF_ERROR_NULL Operation failure. NULL pointer supplied.
|
||||
*/
|
||||
uint32_t spi_master_open(const spi_master_hw_instance_t spi_master_hw_instance,
|
||||
spi_master_config_t const * const p_spi_master_config);
|
||||
|
||||
|
||||
/**@brief Function for closing a SPI MASTER driver.
|
||||
*
|
||||
* @note Function disable hardware, reset internal module states and unregister events callback
|
||||
* function.
|
||||
*
|
||||
* @param[in] spi_master_hw_instance A instance of SPI master.
|
||||
*/
|
||||
void spi_master_close(const spi_master_hw_instance_t spi_master_hw_instance);
|
||||
|
||||
|
||||
/**@brief Function for transferring data between SPI master and SPI slave
|
||||
*
|
||||
* @note Function registers buffers pointed by p_tx_buf and p_rx_buf parameters, after that starts transmission.
|
||||
* Function generates an event of type @ref SPI_MASTER_EVT_TRANSFER_STARTED when transfer has been started
|
||||
* and @ref SPI_MASTER_EVT_TRANSFER_COMPLETED when transfer has been completed.
|
||||
*
|
||||
* @param[in] spi_master_hw_instance Instance of SPI master module.
|
||||
* @param[in] p_tx_buf Pointer to a transmit buffer.
|
||||
* @param[in] tx_buf_len Number of octets to the transfer.
|
||||
* @param[out] p_rx_buf Pointer to a receive buffer.
|
||||
* @param[in] rx_buf_len Number of octets to be received.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success. Packet was registered to the transmission
|
||||
* and event will be send upon transmission completion.
|
||||
* @retval NRF_ERROR_BUSY Operation failure. Transmitting of a data is in progress.
|
||||
*/
|
||||
uint32_t spi_master_send_recv(const spi_master_hw_instance_t spi_master_hw_instance,
|
||||
uint8_t * const p_tx_buf, const uint16_t tx_buf_len,
|
||||
uint8_t * const p_rx_buf, const uint16_t rx_buf_len);
|
||||
|
||||
|
||||
/**@brief Function for registration event handler.
|
||||
*
|
||||
* @note Function registers a event handler to be used by SPI MASTER driver for sending events.
|
||||
* @ref SPI_MASTER_EVT_TRANSFER_STARTED and @ref SPI_MASTER_EVT_TRANSFER_COMPLETED.
|
||||
*
|
||||
* @param[in] spi_master_hw_instance Instance of SPI master module.
|
||||
* @param[in] event_handler Generic callback function handler to be used
|
||||
* by all SPI master driver events.
|
||||
*/
|
||||
void spi_master_evt_handler_reg(const spi_master_hw_instance_t spi_master_hw_instance,
|
||||
spi_master_event_handler_t event_handler);
|
||||
|
||||
|
||||
/**@brief Function for getting current state of the SPI master driver.
|
||||
*
|
||||
* @note Function gets current state of the SPI master driver.
|
||||
*
|
||||
* @param[in] spi_master_hw_instance Instance of SPI master module.
|
||||
*
|
||||
* @retval SPI_MASTER_STATE_DISABLED SPI MASTER is disabled.
|
||||
* @retval SPI_MASTER_STATE_BUSY SPI_MASTER is sending now.
|
||||
* @retval SPI_MASTER_STATE_IDLE SPI_MASTER is idle now.
|
||||
*/
|
||||
spi_master_state_t spi_master_get_state(const spi_master_hw_instance_t spi_master_hw_instance);
|
||||
|
||||
#ifdef _SPI_5W_
|
||||
|
||||
uint32_t spi_master_abort(const spi_master_hw_instance_t spi_master_hw_instance);
|
||||
|
||||
uint32_t spi_master_restart(const spi_master_hw_instance_t spi_master_hw_instance);
|
||||
|
||||
void spi_5W_master_evt_handler_reg(const spi_master_hw_instance_t spi_master_hw_instance,
|
||||
spi_master_event_handler_t event_handler);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) 2012 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#ifndef TWI_MASTER_CONFIG
|
||||
#define TWI_MASTER_CONFIG
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER (24U)
|
||||
#define TWI_MASTER_CONFIG_DATA_PIN_NUMBER (25U)
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
331
components/drivers_nrf/twi_master/deprecated/twi_hw_master.c
Normal file
331
components/drivers_nrf/twi_master/deprecated/twi_hw_master.c
Normal file
@@ -0,0 +1,331 @@
|
||||
/**
|
||||
* Copyright (c) 2009 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include "twi_master.h"
|
||||
#include "twi_master_config.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "nrf.h"
|
||||
#include "nrf_delay.h"
|
||||
#include "nrf_gpio.h"
|
||||
|
||||
/* Max cycles approximately to wait on RXDREADY and TXDREADY event,
|
||||
* This is optimized way instead of using timers, this is not power aware. */
|
||||
#define MAX_TIMEOUT_LOOPS (20000UL) /**< MAX while loops to wait for RXD/TXD event */
|
||||
|
||||
static bool twi_master_write(uint8_t * data, uint8_t data_length, bool issue_stop_condition)
|
||||
{
|
||||
uint32_t timeout = MAX_TIMEOUT_LOOPS; /* max loops to wait for EVENTS_TXDSENT event*/
|
||||
|
||||
if (data_length == 0)
|
||||
{
|
||||
/* Return false for requesting data of size 0 */
|
||||
return false;
|
||||
}
|
||||
|
||||
NRF_TWI1->TXD = *data++;
|
||||
NRF_TWI1->TASKS_STARTTX = 1;
|
||||
|
||||
/** @snippet [TWI HW master write] */
|
||||
while (true)
|
||||
{
|
||||
while (NRF_TWI1->EVENTS_TXDSENT == 0 && NRF_TWI1->EVENTS_ERROR == 0 && (--timeout))
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
if (timeout == 0 || NRF_TWI1->EVENTS_ERROR != 0)
|
||||
{
|
||||
// Recover the peripheral as indicated by PAN 56: "TWI: TWI module lock-up." found at
|
||||
// Product Anomaly Notification document found at
|
||||
// https://www.nordicsemi.com/eng/Products/Bluetooth-R-low-energy/nRF51822/#Downloads
|
||||
NRF_TWI1->EVENTS_ERROR = 0;
|
||||
NRF_TWI1->ENABLE = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos;
|
||||
NRF_TWI1->POWER = 0;
|
||||
nrf_delay_us(5);
|
||||
NRF_TWI1->POWER = 1;
|
||||
NRF_TWI1->ENABLE = TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos;
|
||||
|
||||
(void)twi_master_init();
|
||||
|
||||
return false;
|
||||
}
|
||||
NRF_TWI1->EVENTS_TXDSENT = 0;
|
||||
if (--data_length == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
NRF_TWI1->TXD = *data++;
|
||||
}
|
||||
/** @snippet [TWI HW master write] */
|
||||
|
||||
if (issue_stop_condition)
|
||||
{
|
||||
NRF_TWI1->EVENTS_STOPPED = 0;
|
||||
NRF_TWI1->TASKS_STOP = 1;
|
||||
/* Wait until stop sequence is sent */
|
||||
while (NRF_TWI1->EVENTS_STOPPED == 0)
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Function for read by twi_master.
|
||||
*/
|
||||
static bool twi_master_read(uint8_t * data, uint8_t data_length, bool issue_stop_condition)
|
||||
{
|
||||
uint32_t timeout = MAX_TIMEOUT_LOOPS; /* max loops to wait for RXDREADY event*/
|
||||
|
||||
if (data_length == 0)
|
||||
{
|
||||
/* Return false for requesting data of size 0 */
|
||||
return false;
|
||||
}
|
||||
else if (data_length == 1)
|
||||
{
|
||||
NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_STOP;
|
||||
}
|
||||
else
|
||||
{
|
||||
NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_SUSPEND;
|
||||
}
|
||||
|
||||
NRF_PPI->CHENSET = PPI_CHENSET_CH0_Msk;
|
||||
NRF_TWI1->EVENTS_RXDREADY = 0;
|
||||
NRF_TWI1->TASKS_STARTRX = 1;
|
||||
|
||||
/** @snippet [TWI HW master read] */
|
||||
while (true)
|
||||
{
|
||||
while (NRF_TWI1->EVENTS_RXDREADY == 0 && NRF_TWI1->EVENTS_ERROR == 0 && (--timeout))
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
NRF_TWI1->EVENTS_RXDREADY = 0;
|
||||
|
||||
if (timeout == 0 || NRF_TWI1->EVENTS_ERROR != 0)
|
||||
{
|
||||
// Recover the peripheral as indicated by PAN 56: "TWI: TWI module lock-up." found at
|
||||
// Product Anomaly Notification document found at
|
||||
// https://www.nordicsemi.com/eng/Products/Bluetooth-R-low-energy/nRF51822/#Downloads
|
||||
NRF_TWI1->EVENTS_ERROR = 0;
|
||||
NRF_TWI1->ENABLE = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos;
|
||||
NRF_TWI1->POWER = 0;
|
||||
nrf_delay_us(5);
|
||||
NRF_TWI1->POWER = 1;
|
||||
NRF_TWI1->ENABLE = TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos;
|
||||
|
||||
(void)twi_master_init();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
*data++ = NRF_TWI1->RXD;
|
||||
|
||||
/* Configure PPI to stop TWI master before we get last BB event */
|
||||
if (--data_length == 1)
|
||||
{
|
||||
NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_STOP;
|
||||
}
|
||||
|
||||
if (data_length == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Recover the peripheral as indicated by PAN 56: "TWI: TWI module lock-up." found at
|
||||
// Product Anomaly Notification document found at
|
||||
// https://www.nordicsemi.com/eng/Products/Bluetooth-R-low-energy/nRF51822/#Downloads
|
||||
nrf_delay_us(20);
|
||||
NRF_TWI1->TASKS_RESUME = 1;
|
||||
}
|
||||
/** @snippet [TWI HW master read] */
|
||||
|
||||
/* Wait until stop sequence is sent */
|
||||
while (NRF_TWI1->EVENTS_STOPPED == 0)
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
NRF_TWI1->EVENTS_STOPPED = 0;
|
||||
|
||||
NRF_PPI->CHENCLR = PPI_CHENCLR_CH0_Msk;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Function for detecting stuck slaves (SDA = 0 and SCL = 1) and tries to clear the bus.
|
||||
*
|
||||
* @return
|
||||
* @retval false Bus is stuck.
|
||||
* @retval true Bus is clear.
|
||||
*/
|
||||
static bool twi_master_clear_bus(void)
|
||||
{
|
||||
uint32_t twi_state;
|
||||
bool bus_clear;
|
||||
uint32_t clk_pin_config;
|
||||
uint32_t data_pin_config;
|
||||
|
||||
// Save and disable TWI hardware so software can take control over the pins.
|
||||
twi_state = NRF_TWI1->ENABLE;
|
||||
NRF_TWI1->ENABLE = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos;
|
||||
|
||||
clk_pin_config = \
|
||||
NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER];
|
||||
NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER] = \
|
||||
(GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \
|
||||
| (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) \
|
||||
| (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) \
|
||||
| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) \
|
||||
| (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
|
||||
|
||||
data_pin_config = \
|
||||
NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_DATA_PIN_NUMBER];
|
||||
NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_DATA_PIN_NUMBER] = \
|
||||
(GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \
|
||||
| (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) \
|
||||
| (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) \
|
||||
| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) \
|
||||
| (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
|
||||
|
||||
TWI_SDA_HIGH();
|
||||
TWI_SCL_HIGH();
|
||||
TWI_DELAY();
|
||||
|
||||
if ((TWI_SDA_READ() == 1) && (TWI_SCL_READ() == 1))
|
||||
{
|
||||
bus_clear = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint_fast8_t i;
|
||||
bus_clear = false;
|
||||
|
||||
// Clock max 18 pulses worst case scenario(9 for master to send the rest of command and 9
|
||||
// for slave to respond) to SCL line and wait for SDA come high.
|
||||
for (i=18; i--;)
|
||||
{
|
||||
TWI_SCL_LOW();
|
||||
TWI_DELAY();
|
||||
TWI_SCL_HIGH();
|
||||
TWI_DELAY();
|
||||
|
||||
if (TWI_SDA_READ() == 1)
|
||||
{
|
||||
bus_clear = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER] = clk_pin_config;
|
||||
NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_DATA_PIN_NUMBER] = data_pin_config;
|
||||
|
||||
NRF_TWI1->ENABLE = twi_state;
|
||||
|
||||
return bus_clear;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Function for initializing the twi_master.
|
||||
*/
|
||||
bool twi_master_init(void)
|
||||
{
|
||||
/* To secure correct signal levels on the pins used by the TWI
|
||||
master when the system is in OFF mode, and when the TWI master is
|
||||
disabled, these pins must be configured in the GPIO peripheral.
|
||||
*/
|
||||
NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER] = \
|
||||
(GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \
|
||||
| (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) \
|
||||
| (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) \
|
||||
| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) \
|
||||
| (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);
|
||||
|
||||
NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_DATA_PIN_NUMBER] = \
|
||||
(GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \
|
||||
| (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) \
|
||||
| (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) \
|
||||
| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) \
|
||||
| (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);
|
||||
|
||||
NRF_TWI1->EVENTS_RXDREADY = 0;
|
||||
NRF_TWI1->EVENTS_TXDSENT = 0;
|
||||
NRF_TWI1->PSELSCL = TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER;
|
||||
NRF_TWI1->PSELSDA = TWI_MASTER_CONFIG_DATA_PIN_NUMBER;
|
||||
NRF_TWI1->FREQUENCY = TWI_FREQUENCY_FREQUENCY_K100 << TWI_FREQUENCY_FREQUENCY_Pos;
|
||||
NRF_PPI->CH[0].EEP = (uint32_t)&NRF_TWI1->EVENTS_BB;
|
||||
NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_SUSPEND;
|
||||
NRF_PPI->CHENCLR = PPI_CHENCLR_CH0_Msk;
|
||||
NRF_TWI1->ENABLE = TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos;
|
||||
|
||||
return twi_master_clear_bus();
|
||||
}
|
||||
|
||||
|
||||
/** @brief Function for transfer by twi_master.
|
||||
*/
|
||||
bool twi_master_transfer(uint8_t address,
|
||||
uint8_t * data,
|
||||
uint8_t data_length,
|
||||
bool issue_stop_condition)
|
||||
{
|
||||
bool transfer_succeeded = false;
|
||||
if (data_length > 0 && twi_master_clear_bus())
|
||||
{
|
||||
NRF_TWI1->ADDRESS = (address >> 1);
|
||||
|
||||
if ((address & TWI_READ_BIT))
|
||||
{
|
||||
transfer_succeeded = twi_master_read(data, data_length, issue_stop_condition);
|
||||
}
|
||||
else
|
||||
{
|
||||
transfer_succeeded = twi_master_write(data, data_length, issue_stop_condition);
|
||||
}
|
||||
}
|
||||
return transfer_succeeded;
|
||||
}
|
||||
|
||||
/*lint --flb "Leave library region" */
|
||||
137
components/drivers_nrf/twi_master/deprecated/twi_master.h
Normal file
137
components/drivers_nrf/twi_master/deprecated/twi_master.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* Copyright (c) 2009 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#ifndef TWI_MASTER_H
|
||||
#define TWI_MASTER_H
|
||||
|
||||
/*lint ++flb "Enter library region" */
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @file
|
||||
* @brief Software controlled TWI Master driver.
|
||||
*
|
||||
*
|
||||
* @defgroup lib_driver_twi_master Software controlled TWI Master driver
|
||||
* @{
|
||||
* @ingroup nrf_twi
|
||||
* @brief Software controlled TWI Master driver (deprecated).
|
||||
*
|
||||
* @warning This module is deprecated.
|
||||
*
|
||||
* Supported features:
|
||||
* - Repeated start
|
||||
* - No multi-master
|
||||
* - Only 7-bit addressing
|
||||
* - Supports clock stretching (with optional SMBus style slave timeout)
|
||||
* - Tries to handle slaves stuck in the middle of transfer
|
||||
*/
|
||||
|
||||
#define TWI_READ_BIT (0x01) //!< If this bit is set in the address field, transfer direction is from slave to master.
|
||||
|
||||
#define TWI_ISSUE_STOP ((bool)true) //!< Parameter for @ref twi_master_transfer
|
||||
#define TWI_DONT_ISSUE_STOP ((bool)false) //!< Parameter for @ref twi_master_transfer
|
||||
|
||||
/* These macros are needed to see if the slave is stuck and we as master send dummy clock cycles to end its wait */
|
||||
/*lint -e717 -save "Suppress do {} while (0) for these macros" */
|
||||
/*lint ++flb "Enter library region" */
|
||||
#define TWI_SCL_HIGH() do { NRF_GPIO->OUTSET = (1UL << TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER); } while (0) /*!< Pulls SCL line high */
|
||||
#define TWI_SCL_LOW() do { NRF_GPIO->OUTCLR = (1UL << TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER); } while (0) /*!< Pulls SCL line low */
|
||||
#define TWI_SDA_HIGH() do { NRF_GPIO->OUTSET = (1UL << TWI_MASTER_CONFIG_DATA_PIN_NUMBER); } while (0) /*!< Pulls SDA line high */
|
||||
#define TWI_SDA_LOW() do { NRF_GPIO->OUTCLR = (1UL << TWI_MASTER_CONFIG_DATA_PIN_NUMBER); } while (0) /*!< Pulls SDA line low */
|
||||
#define TWI_SDA_INPUT() do { NRF_GPIO->DIRCLR = (1UL << TWI_MASTER_CONFIG_DATA_PIN_NUMBER); } while (0) /*!< Configures SDA pin as input */
|
||||
#define TWI_SDA_OUTPUT() do { NRF_GPIO->DIRSET = (1UL << TWI_MASTER_CONFIG_DATA_PIN_NUMBER); } while (0) /*!< Configures SDA pin as output */
|
||||
#define TWI_SCL_OUTPUT() do { NRF_GPIO->DIRSET = (1UL << TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER); } while (0) /*!< Configures SCL pin as output */
|
||||
/*lint -restore */
|
||||
|
||||
#define TWI_SDA_READ() ((NRF_GPIO->IN >> TWI_MASTER_CONFIG_DATA_PIN_NUMBER) & 0x1UL) /*!< Reads current state of SDA */
|
||||
#define TWI_SCL_READ() ((NRF_GPIO->IN >> TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER) & 0x1UL) /*!< Reads current state of SCL */
|
||||
|
||||
#define TWI_DELAY() nrf_delay_us(4) /*!< Time to wait when pin states are changed. For fast-mode the delay can be zero and for standard-mode 4 us delay is sufficient. */
|
||||
|
||||
|
||||
/**
|
||||
* @brief Function for initializing TWI bus IO pins and checks if the bus is operational.
|
||||
*
|
||||
* Both pins are configured as Standard-0, No-drive-1 (open drain).
|
||||
*
|
||||
* @return
|
||||
* @retval true TWI bus is clear for transfers.
|
||||
* @retval false TWI bus is stuck.
|
||||
*/
|
||||
bool twi_master_init(void);
|
||||
|
||||
/**
|
||||
* @brief Function for transferring data over TWI bus.
|
||||
*
|
||||
* If TWI master detects even one NACK from the slave or timeout occurs, STOP condition is issued
|
||||
* and the function returns false.
|
||||
* Bit 0 (@ref TWI_READ_BIT) in the address parameter controls transfer direction;
|
||||
* - If 1, master reads data_length number of bytes from the slave
|
||||
* - If 0, master writes data_length number of bytes to the slave.
|
||||
*
|
||||
* @note Make sure at least data_length number of bytes is allocated in data if TWI_READ_BIT is set.
|
||||
* @note @ref TWI_ISSUE_STOP
|
||||
*
|
||||
* @param address Data transfer direction (LSB) / Slave address (7 MSBs).
|
||||
* @param data Pointer to data.
|
||||
* @param data_length Number of bytes to transfer.
|
||||
* @param issue_stop_condition If @ref TWI_ISSUE_STOP, STOP condition is issued before exiting function. If @ref TWI_DONT_ISSUE_STOP, STOP condition is not issued before exiting function. If transfer failed for any reason, STOP condition will be issued in any case.
|
||||
* @return
|
||||
* @retval true Data transfer succeeded without errors.
|
||||
* @retval false Data transfer failed.
|
||||
*/
|
||||
bool twi_master_transfer(uint8_t address, uint8_t *data, uint8_t data_length, bool issue_stop_condition);
|
||||
|
||||
/**
|
||||
*@}
|
||||
**/
|
||||
|
||||
/*lint --flb "Leave library region" */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //TWI_MASTER_H
|
||||
519
components/drivers_nrf/twi_master/deprecated/twi_sw_master.c
Normal file
519
components/drivers_nrf/twi_master/deprecated/twi_sw_master.c
Normal file
@@ -0,0 +1,519 @@
|
||||
/**
|
||||
* Copyright (c) 2009 - 2020, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "twi_master.h"
|
||||
#include "nrf_delay.h"
|
||||
|
||||
#include "twi_master_config.h"
|
||||
|
||||
/*lint -e415 -e845 -save "Out of bounds access" */
|
||||
#define TWI_SDA_STANDARD0_NODRIVE1() do { \
|
||||
NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_DATA_PIN_NUMBER] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \
|
||||
|(GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) \
|
||||
|(GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) \
|
||||
|(GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) \
|
||||
|(GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
|
||||
} while (0) /*!< Configures SDA pin to Standard-0, No-drive 1 */
|
||||
|
||||
|
||||
#define TWI_SCL_STANDARD0_NODRIVE1() do { \
|
||||
NRF_GPIO->PIN_CNF[TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \
|
||||
|(GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) \
|
||||
|(GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) \
|
||||
|(GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) \
|
||||
|(GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
|
||||
} while (0) /*!< Configures SCL pin to Standard-0, No-drive 1 */
|
||||
|
||||
|
||||
/*lint -restore */
|
||||
|
||||
#ifndef TWI_MASTER_TIMEOUT_COUNTER_LOAD_VALUE
|
||||
#define TWI_MASTER_TIMEOUT_COUNTER_LOAD_VALUE (0UL) //!< Unit is number of empty loops. Timeout for SMBus devices is 35 ms. Set to zero to disable slave timeout altogether.
|
||||
#endif
|
||||
|
||||
static bool twi_master_clear_bus(void);
|
||||
static bool twi_master_issue_startcondition(void);
|
||||
static bool twi_master_issue_stopcondition(void);
|
||||
static bool twi_master_clock_byte(uint_fast8_t databyte);
|
||||
static bool twi_master_clock_byte_in(uint8_t * databyte, bool ack);
|
||||
static bool twi_master_wait_while_scl_low(void);
|
||||
|
||||
bool twi_master_init(void)
|
||||
{
|
||||
// Configure both pins to output Standard 0, No-drive (open-drain) 1
|
||||
TWI_SDA_STANDARD0_NODRIVE1(); /*lint !e416 "Creation of out of bounds pointer" */
|
||||
TWI_SCL_STANDARD0_NODRIVE1(); /*lint !e416 "Creation of out of bounds pointer" */
|
||||
|
||||
// Configure SCL as output
|
||||
TWI_SCL_HIGH();
|
||||
TWI_SCL_OUTPUT();
|
||||
|
||||
// Configure SDA as output
|
||||
TWI_SDA_HIGH();
|
||||
TWI_SDA_OUTPUT();
|
||||
|
||||
return twi_master_clear_bus();
|
||||
}
|
||||
|
||||
bool twi_master_transfer(uint8_t address, uint8_t * data, uint8_t data_length, bool issue_stop_condition)
|
||||
{
|
||||
bool transfer_succeeded = true;
|
||||
|
||||
transfer_succeeded &= twi_master_issue_startcondition();
|
||||
transfer_succeeded &= twi_master_clock_byte(address);
|
||||
|
||||
if (address & TWI_READ_BIT)
|
||||
{
|
||||
/* Transfer direction is from Slave to Master */
|
||||
while (data_length-- && transfer_succeeded)
|
||||
{
|
||||
// To indicate to slave that we've finished transferring last data byte
|
||||
// we need to NACK the last transfer.
|
||||
if (data_length == 0)
|
||||
{
|
||||
transfer_succeeded &= twi_master_clock_byte_in(data, (bool)false);
|
||||
}
|
||||
else
|
||||
{
|
||||
transfer_succeeded &= twi_master_clock_byte_in(data, (bool)true);
|
||||
}
|
||||
data++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Transfer direction is from Master to Slave */
|
||||
while (data_length-- && transfer_succeeded)
|
||||
{
|
||||
transfer_succeeded &= twi_master_clock_byte(*data);
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
if (issue_stop_condition || !transfer_succeeded)
|
||||
{
|
||||
transfer_succeeded &= twi_master_issue_stopcondition();
|
||||
}
|
||||
|
||||
return transfer_succeeded;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for detecting stuck slaves and tries to clear the bus.
|
||||
*
|
||||
* @return
|
||||
* @retval false Bus is stuck.
|
||||
* @retval true Bus is clear.
|
||||
*/
|
||||
static bool twi_master_clear_bus(void)
|
||||
{
|
||||
bool bus_clear;
|
||||
|
||||
TWI_SDA_HIGH();
|
||||
TWI_SCL_HIGH();
|
||||
TWI_DELAY();
|
||||
|
||||
|
||||
if (TWI_SDA_READ() == 1 && TWI_SCL_READ() == 1)
|
||||
{
|
||||
bus_clear = true;
|
||||
}
|
||||
else if (TWI_SCL_READ() == 1)
|
||||
{
|
||||
bus_clear = false;
|
||||
// Clock max 18 pulses worst case scenario(9 for master to send the rest of command and 9 for slave to respond) to SCL line and wait for SDA come high
|
||||
for (uint_fast8_t i = 18; i--;)
|
||||
{
|
||||
TWI_SCL_LOW();
|
||||
TWI_DELAY();
|
||||
TWI_SCL_HIGH();
|
||||
TWI_DELAY();
|
||||
|
||||
if (TWI_SDA_READ() == 1)
|
||||
{
|
||||
bus_clear = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bus_clear = false;
|
||||
}
|
||||
|
||||
return bus_clear;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for issuing TWI START condition to the bus.
|
||||
*
|
||||
* START condition is signaled by pulling SDA low while SCL is high. After this function SCL and SDA will be low.
|
||||
*
|
||||
* @return
|
||||
* @retval false Timeout detected
|
||||
* @retval true Clocking succeeded
|
||||
*/
|
||||
static bool twi_master_issue_startcondition(void)
|
||||
{
|
||||
#if 0
|
||||
if (TWI_SCL_READ() == 1 && TWI_SDA_READ() == 1)
|
||||
{
|
||||
// Pull SDA low
|
||||
TWI_SDA_LOW();
|
||||
}
|
||||
else if (TWI_SCL_READ() == 1 && TWI_SDA_READ() == 0)
|
||||
{
|
||||
// Issue Stop by pulling SDA high
|
||||
TWI_SDA_HIGH();
|
||||
TWI_DELAY();
|
||||
|
||||
// Then Start by pulling SDA low
|
||||
TWI_SDA_LOW();
|
||||
}
|
||||
else if (TWI_SCL_READ() == 0 && TWI_SDA_READ() == 0)
|
||||
{
|
||||
// First pull SDA high
|
||||
TWI_SDA_HIGH();
|
||||
|
||||
// Then SCL high
|
||||
if (!twi_master_wait_while_scl_low())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Then SDA low
|
||||
TWI_SDA_LOW();
|
||||
}
|
||||
else if (TWI_SCL_READ() == 0 && TWI_SDA_READ() == 1)
|
||||
{
|
||||
// SCL high
|
||||
if (!twi_master_wait_while_scl_low())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Then SDA low
|
||||
TWI_SDA_LOW();
|
||||
}
|
||||
|
||||
TWI_DELAY();
|
||||
TWI_SCL_LOW();
|
||||
#endif
|
||||
|
||||
// Make sure both SDA and SCL are high before pulling SDA low.
|
||||
TWI_SDA_HIGH();
|
||||
TWI_DELAY();
|
||||
if (!twi_master_wait_while_scl_low())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TWI_SDA_LOW();
|
||||
TWI_DELAY();
|
||||
|
||||
// Other module function expect SCL to be low
|
||||
TWI_SCL_LOW();
|
||||
TWI_DELAY();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for issuing TWI STOP condition to the bus.
|
||||
*
|
||||
* STOP condition is signaled by pulling SDA high while SCL is high. After this function SDA and SCL will be high.
|
||||
*
|
||||
* @return
|
||||
* @retval false Timeout detected
|
||||
* @retval true Clocking succeeded
|
||||
*/
|
||||
static bool twi_master_issue_stopcondition(void)
|
||||
{
|
||||
#if 0
|
||||
if (TWI_SCL_READ() == 1 && TWI_SDA_READ() == 1)
|
||||
{
|
||||
// Issue start, then issue stop
|
||||
|
||||
// Pull SDA low to issue START
|
||||
TWI_SDA_LOW();
|
||||
TWI_DELAY();
|
||||
|
||||
// Pull SDA high while SCL is high to issue STOP
|
||||
TWI_SDA_HIGH();
|
||||
}
|
||||
else if (TWI_SCL_READ() == 1 && TWI_SDA_READ() == 0)
|
||||
{
|
||||
// Pull SDA high while SCL is high to issue STOP
|
||||
TWI_SDA_HIGH();
|
||||
}
|
||||
else if (TWI_SCL_READ() == 0 && TWI_SDA_READ() == 0)
|
||||
{
|
||||
if (!twi_master_wait_while_scl_low())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pull SDA high while SCL is high to issue STOP
|
||||
TWI_SDA_HIGH();
|
||||
}
|
||||
else if (TWI_SCL_READ() == 0 && TWI_SDA_READ() == 1)
|
||||
{
|
||||
TWI_SDA_LOW();
|
||||
TWI_DELAY();
|
||||
|
||||
// SCL high
|
||||
if (!twi_master_wait_while_scl_low())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pull SDA high while SCL is high to issue STOP
|
||||
TWI_SDA_HIGH();
|
||||
}
|
||||
|
||||
TWI_DELAY();
|
||||
#endif
|
||||
|
||||
TWI_SDA_LOW();
|
||||
TWI_DELAY();
|
||||
if (!twi_master_wait_while_scl_low())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TWI_SDA_HIGH();
|
||||
TWI_DELAY();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for clocking one data byte out and reads slave acknowledgment.
|
||||
*
|
||||
* Can handle clock stretching.
|
||||
* After calling this function SCL is low and SDA low/high depending on the
|
||||
* value of LSB of the data byte.
|
||||
* SCL is expected to be output and low when entering this function.
|
||||
*
|
||||
* @param databyte Data byte to clock out.
|
||||
* @return
|
||||
* @retval true Slave acknowledged byte.
|
||||
* @retval false Timeout or slave didn't acknowledge byte.
|
||||
*/
|
||||
static bool twi_master_clock_byte(uint_fast8_t databyte)
|
||||
{
|
||||
bool transfer_succeeded = true;
|
||||
|
||||
/** @snippet [TWI SW master write] */
|
||||
// Make sure SDA is an output
|
||||
TWI_SDA_OUTPUT();
|
||||
|
||||
// MSB first
|
||||
for (uint_fast8_t i = 0x80; i != 0; i >>= 1)
|
||||
{
|
||||
TWI_SCL_LOW();
|
||||
TWI_DELAY();
|
||||
|
||||
if (databyte & i)
|
||||
{
|
||||
TWI_SDA_HIGH();
|
||||
}
|
||||
else
|
||||
{
|
||||
TWI_SDA_LOW();
|
||||
}
|
||||
|
||||
if (!twi_master_wait_while_scl_low())
|
||||
{
|
||||
transfer_succeeded = false; // Timeout
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Finish last data bit by pulling SCL low
|
||||
TWI_SCL_LOW();
|
||||
TWI_DELAY();
|
||||
|
||||
/** @snippet [TWI SW master write] */
|
||||
|
||||
// Configure TWI_SDA pin as input for receiving the ACK bit
|
||||
TWI_SDA_INPUT();
|
||||
|
||||
// Give some time for the slave to load the ACK bit on the line
|
||||
TWI_DELAY();
|
||||
|
||||
// Pull SCL high and wait a moment for SDA line to settle
|
||||
// Make sure slave is not stretching the clock
|
||||
transfer_succeeded &= twi_master_wait_while_scl_low();
|
||||
|
||||
// Read ACK/NACK. NACK == 1, ACK == 0
|
||||
transfer_succeeded &= !(TWI_SDA_READ());
|
||||
|
||||
// Finish ACK/NACK bit clock cycle and give slave a moment to release control
|
||||
// of the SDA line
|
||||
TWI_SCL_LOW();
|
||||
TWI_DELAY();
|
||||
|
||||
// Configure TWI_SDA pin as output as other module functions expect that
|
||||
TWI_SDA_OUTPUT();
|
||||
|
||||
return transfer_succeeded;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Function for clocking one data byte in and sends ACK/NACK bit.
|
||||
*
|
||||
* Can handle clock stretching.
|
||||
* SCL is expected to be output and low when entering this function.
|
||||
* After calling this function, SCL is high and SDA low/high depending if ACK/NACK was sent.
|
||||
*
|
||||
* @param databyte Data byte to clock out.
|
||||
* @param ack If true, send ACK. Otherwise send NACK.
|
||||
* @return
|
||||
* @retval true Byte read succesfully
|
||||
* @retval false Timeout detected
|
||||
*/
|
||||
static bool twi_master_clock_byte_in(uint8_t *databyte, bool ack)
|
||||
{
|
||||
uint_fast8_t byte_read = 0;
|
||||
bool transfer_succeeded = true;
|
||||
|
||||
/** @snippet [TWI SW master read] */
|
||||
// Make sure SDA is an input
|
||||
TWI_SDA_INPUT();
|
||||
|
||||
// SCL state is guaranteed to be high here
|
||||
|
||||
// MSB first
|
||||
for (uint_fast8_t i = 0x80; i != 0; i >>= 1)
|
||||
{
|
||||
if (!twi_master_wait_while_scl_low())
|
||||
{
|
||||
transfer_succeeded = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (TWI_SDA_READ())
|
||||
{
|
||||
byte_read |= i;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No need to do anything
|
||||
}
|
||||
|
||||
TWI_SCL_LOW();
|
||||
TWI_DELAY();
|
||||
}
|
||||
|
||||
// Make sure SDA is an output before we exit the function
|
||||
TWI_SDA_OUTPUT();
|
||||
/** @snippet [TWI SW master read] */
|
||||
|
||||
*databyte = (uint8_t)byte_read;
|
||||
|
||||
// Send ACK bit
|
||||
|
||||
// SDA high == NACK, SDA low == ACK
|
||||
if (ack)
|
||||
{
|
||||
TWI_SDA_LOW();
|
||||
}
|
||||
else
|
||||
{
|
||||
TWI_SDA_HIGH();
|
||||
}
|
||||
|
||||
// Let SDA line settle for a moment
|
||||
TWI_DELAY();
|
||||
|
||||
// Drive SCL high to start ACK/NACK bit transfer
|
||||
// Wait until SCL is high, or timeout occurs
|
||||
if (!twi_master_wait_while_scl_low())
|
||||
{
|
||||
transfer_succeeded = false; // Timeout
|
||||
}
|
||||
|
||||
// Finish ACK/NACK bit clock cycle and give slave a moment to react
|
||||
TWI_SCL_LOW();
|
||||
TWI_DELAY();
|
||||
|
||||
return transfer_succeeded;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Function for pulling SCL high and waits until it is high or timeout occurs.
|
||||
*
|
||||
* SCL is expected to be output before entering this function.
|
||||
* @note If TWI_MASTER_TIMEOUT_COUNTER_LOAD_VALUE is set to zero, timeout functionality is not compiled in.
|
||||
* @return
|
||||
* @retval true SCL is now high.
|
||||
* @retval false Timeout occurred and SCL is still low.
|
||||
*/
|
||||
static bool twi_master_wait_while_scl_low(void)
|
||||
{
|
||||
#if TWI_MASTER_TIMEOUT_COUNTER_LOAD_VALUE != 0
|
||||
uint32_t volatile timeout_counter = TWI_MASTER_TIMEOUT_COUNTER_LOAD_VALUE;
|
||||
#endif
|
||||
|
||||
// Pull SCL high just in case if something left it low
|
||||
TWI_SCL_HIGH();
|
||||
TWI_DELAY();
|
||||
|
||||
while (TWI_SCL_READ() == 0)
|
||||
{
|
||||
// If SCL is low, one of the slaves is busy and we must wait
|
||||
|
||||
#if TWI_MASTER_TIMEOUT_COUNTER_LOAD_VALUE != 0
|
||||
if (timeout_counter-- == 0)
|
||||
{
|
||||
// If timeout_detected, return false
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*lint --flb "Leave library region" */
|
||||
Reference in New Issue
Block a user