📄 hal.c
字号:
/* Copyright (c) 2008, Swedish Institute of Computer Science * All rights reserved. * * Additional fixes for AVR contributed by: * * Colin O'Flynn coflynn@newae.com * Eric Gnoske egnoske@gmail.com * Blake Leverett bleverett@gmail.com * Mike Vidales mavida404@gmail.com * Kevin Brown kbrown3@uccs.edu * Nate Bohlmann nate@elfwerks.com * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form 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. * * Neither the name of the copyright holders nor the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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. * * $Id: hal.c,v 1.2 2008/10/14 18:37:28 c_oflynn Exp $*//** * \addtogroup wireless * @{*//** * \defgroup hal RF230 hardware level drivers * @{ *//** * \file * This file contains low-level radio driver code. *//*============================ INCLUDE =======================================*/#include <stdlib.h>#include "hal.h"#include "at86rf230_registermap.h"/*============================ MACROS ========================================*//* * Macros defined for the radio transceiver's access modes. * * These functions are implemented as macros since they are used very often. */#define HAL_DUMMY_READ (0x00) /**< Dummy value for the SPI. */#define HAL_TRX_CMD_RW (0xC0) /**< Register Write (short mode). */#define HAL_TRX_CMD_RR (0x80) /**< Register Read (short mode). */#define HAL_TRX_CMD_FW (0x60) /**< Frame Transmit Mode (long mode). */#define HAL_TRX_CMD_FR (0x20) /**< Frame Receive Mode (long mode). */#define HAL_TRX_CMD_SW (0x40) /**< SRAM Write. */#define HAL_TRX_CMD_SR (0x00) /**< SRAM Read. */#define HAL_TRX_CMD_RADDRM (0x7F) /**< Register Address Mask. */#define HAL_CALCULATED_CRC_OK (0) /**< CRC calculated over the frame including the CRC field should be 0. *//*============================ TYPDEFS =======================================*//*============================ VARIABLES =====================================*//** \brief This is a file internal variable that contains the 16 MSB of the * system time. * * The system time (32-bit) is the current time in microseconds. For the * AVR microcontroller implementation this is solved by using a 16-bit * timer (Timer1) with a clock frequency of 1MHz. The hal_system_time is * incremented when the 16-bit timer overflows, representing the 16 MSB. * The timer value it self (TCNT1) is then the 16 LSB. * * \see hal_get_system_time */static uint16_t hal_system_time = 0;/*Flag section.*/static uint8_t volatile hal_bat_low_flag; /**< BAT_LOW flag. */static uint8_t volatile hal_pll_lock_flag; /**< PLL_LOCK flag. *//*Callbacks.*//** \brief This function is called when a rx_start interrupt is signaled. * * If this function pointer is set to something else than NULL, it will * be called when a RX_START event is signaled. The function takes two * parameters: timestamp in IEEE 802.15.4 symbols (16 us resolution) and * frame length. The event handler will be called in the interrupt domain, * so the function must be kept short and not be blocking! Otherwise the * system performance will be greatly degraded. * * \see hal_set_rx_start_event_handler */static hal_rx_start_isr_event_handler_t rx_start_callback;/** \brief This function is called when a trx_end interrupt is signaled. * * If this function pointer is set to something else than NULL, it will * be called when a TRX_END event is signaled. The function takes one * parameter: timestamp in IEEE 802.15.4 symbols (16 us resolution). * The event handler will be called in the interrupt domain, * so the function must not block! * * \see hal_set_trx_end_event_handler */static hal_trx_end_isr_event_handler_t trx_end_callback;/*============================ PROTOTYPES ====================================*//*============================ IMPLEMENTATION ================================*//** \brief This function initializes the Hardware Abstraction Layer. */voidhal_init(void){ /*Reset variables used in file.*/ hal_system_time = 0; hal_reset_flags(); /*IO Specific Initialization.*/ DDR_SLP_TR |= (1 << SLP_TR); /* Enable SLP_TR as output. */ DDR_RST |= (1 << RST); /* Enable RST as output. */ /*SPI Specific Initialization.*/ /* Set SS, CLK and MOSI as output. */ HAL_DDR_SPI |= (1 << HAL_DD_SS) | (1 << HAL_DD_SCK) | (1 << HAL_DD_MOSI); HAL_PORT_SPI |= (1 << HAL_DD_SS) | (1 << HAL_DD_SCK); /* Set SS and CLK high */ /* Run SPI at max speed */ SPCR = (1 << SPE) | (1 << MSTR); /* Enable SPI module and master operation. */ SPSR = (1 << SPI2X); /* Enable doubled SPI speed in master mode. */ /*TIMER1 Specific Initialization.*/ TCCR1B = HAL_TCCR1B_CONFIG; /* Set clock prescaler */ TIFR1 |= (1 << ICF1); /* Clear Input Capture Flag. */ HAL_ENABLE_OVERFLOW_INTERRUPT(); /* Enable Timer1 overflow interrupt. */ hal_enable_trx_interrupt(); /* Enable interrupts from the radio transceiver. */}/*----------------------------------------------------------------------------*//** \brief This function reset the interrupt flags and interrupt event handlers * (Callbacks) to their default value. */voidhal_reset_flags(void){ AVR_ENTER_CRITICAL_REGION(); /* Reset Flags. */ hal_bat_low_flag = 0; hal_pll_lock_flag = 0; /* Reset Associated Event Handlers. */ rx_start_callback = NULL; trx_end_callback = NULL; AVR_LEAVE_CRITICAL_REGION();}/*----------------------------------------------------------------------------*//** \brief This function returns the current value of the BAT_LOW flag. * * The BAT_LOW flag is incremented each time a BAT_LOW event is signaled from the * radio transceiver. This way it is possible for the end user to poll the flag * for new event occurances. */uint8_thal_get_bat_low_flag(void){ return hal_bat_low_flag;}/*----------------------------------------------------------------------------*//** \brief This function clears the BAT_LOW flag. */voidhal_clear_bat_low_flag(void){ AVR_ENTER_CRITICAL_REGION(); hal_bat_low_flag = 0; AVR_LEAVE_CRITICAL_REGION();}/*----------------------------------------------------------------------------*//** \brief This function is used to set new TRX_END event handler, overriding * old handler reference. */hal_trx_end_isr_event_handler_thal_get_trx_end_event_handler(void){ return trx_end_callback;}/*----------------------------------------------------------------------------*//** \brief This function is used to set new TRX_END event handler, overriding * old handler reference. */voidhal_set_trx_end_event_handler(hal_trx_end_isr_event_handler_t trx_end_callback_handle){ AVR_ENTER_CRITICAL_REGION(); trx_end_callback = trx_end_callback_handle; AVR_LEAVE_CRITICAL_REGION();}/*----------------------------------------------------------------------------*//** \brief Remove event handler reference. */voidhal_clear_trx_end_event_handler(void){ AVR_ENTER_CRITICAL_REGION(); trx_end_callback = NULL; AVR_LEAVE_CRITICAL_REGION();}/*----------------------------------------------------------------------------*//** \brief This function returns the active RX_START event handler * * \return Current RX_START event handler registered. */hal_rx_start_isr_event_handler_thal_get_rx_start_event_handler(void){ return rx_start_callback;}/*----------------------------------------------------------------------------*//** \brief This function is used to set new RX_START event handler, overriding * old handler reference. */voidhal_set_rx_start_event_handler(hal_rx_start_isr_event_handler_t rx_start_callback_handle){ AVR_ENTER_CRITICAL_REGION(); rx_start_callback = rx_start_callback_handle; AVR_LEAVE_CRITICAL_REGION();}/*----------------------------------------------------------------------------*//** \brief Remove event handler reference. */voidhal_clear_rx_start_event_handler(void){ AVR_ENTER_CRITICAL_REGION(); rx_start_callback = NULL; AVR_LEAVE_CRITICAL_REGION();}/*----------------------------------------------------------------------------*//** \brief This function returns the current value of the PLL_LOCK flag. * * The PLL_LOCK flag is incremented each time a PLL_LOCK event is signaled from the * radio transceiver. This way it is possible for the end user to poll the flag * for new event occurances. */uint8_thal_get_pll_lock_flag(void){ return hal_pll_lock_flag;}/*----------------------------------------------------------------------------*//** \brief This function clears the PLL_LOCK flag. */voidhal_clear_pll_lock_flag(void){ AVR_ENTER_CRITICAL_REGION(); hal_pll_lock_flag = 0; AVR_LEAVE_CRITICAL_REGION();}/*----------------------------------------------------------------------------*//** \brief This function reads data from one of the radio transceiver's registers. * * \param address Register address to read from. See datasheet for register * map. * * \see Look at the at86rf230_registermap.h file for register address definitions. * * \returns The actual value of the read register. */uint8_thal_register_read(uint8_t address){ /* Add the register read command to the register address. */ address &= HAL_TRX_CMD_RADDRM; address |= HAL_TRX_CMD_RR; uint8_t register_value = 0; AVR_ENTER_CRITICAL_REGION(); HAL_SS_LOW(); /* Start the SPI transaction by pulling the Slave Select low. */ /*Send Register address and read register content.*/ SPDR = address; while ((SPSR & (1 << SPIF)) == 0) {;} register_value = SPDR; SPDR = register_value; while ((SPSR & (1 << SPIF)) == 0) {;} register_value = SPDR; HAL_SS_HIGH(); /* End the transaction by pulling the Slave Select High. */ AVR_LEAVE_CRITICAL_REGION(); return register_value;}/*----------------------------------------------------------------------------*//** \brief This function writes a new value to one of the radio transceiver's * registers. * * \see Look at the at86rf230_registermap.h file for register address definitions. * * \param address Address of register to write. * \param value Value to write. */voidhal_register_write(uint8_t address, uint8_t value){ /* Add the Register Write command to the address. */ address = HAL_TRX_CMD_RW | (HAL_TRX_CMD_RADDRM & address); AVR_ENTER_CRITICAL_REGION(); HAL_SS_LOW(); /* Start the SPI transaction by pulling the Slave Select low. */ /*Send Register address and write register content.*/ SPDR = address; while ((SPSR & (1 << SPIF)) == 0) {;} uint8_t dummy_read = SPDR; SPDR = value; while ((SPSR & (1 << SPIF)) == 0) {;} dummy_read = SPDR; HAL_SS_HIGH(); /* End the transaction by pulling the Slave Slect High. */ AVR_LEAVE_CRITICAL_REGION();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -